Skip to content

Commit 5e6029b

Browse files
committed
async
1 parent 6643cf2 commit 5e6029b

20 files changed

+989
-876
lines changed

Diff for: Cargo.lock

+516-326
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
[workspace]
2+
resolver = "2"
23
members = [
34
"src/security_api",
45
"src/security_poller",
56
"src/security_discord"
67
]
78

89
[workspace.dependencies]
10+
anyhow = "1.0.93"
911
tokio = { version = "1.38.0", features = ["full"] }
1012
serde = { version = "1.0.163", features = ["derive"] }
1113
serde_json = "1.0.96"
1214
log = "0.4.17"
13-
pretty_env_logger = "0.5.0"
15+
pretty_env_logger = "0.5.0"
16+
reqwest = { version = "0.12.9", default-features = false, features = ["json", "http2", "rustls-tls", "rustls-tls-webpki-roots"] }

Diff for: Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM rust:1.75 as builder
1+
FROM rust:1.82 as builder
22
WORKDIR /usr/src/security
33

44
COPY . .

Diff for: config.example.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ poller:
77
handle: "" # HackerOne team handle
88
session_token: "" # HackerOne session token (the "__Host-session" cookie), this is optional if you're using a public team
99

10-
### disable_reputation_polling: "true"
11-
### disable_hackactivity_polling: "true"
10+
### reputation_polling: "true"
11+
### hackactivity_polling: "true"

Diff for: src/security_api/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ edition = "2021"
77

88
[dependencies]
99
graphql_client = "0.12.0"
10-
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
10+
reqwest.workspace = true
1111
regex = "1.4.2"
1212
serde = "1.0.163"
1313
serde_json = "1.0.96"
1414
redis = "0.23.0"
1515
chrono = "0.4.24"
1616
nanoid = "0.4.0"
17+
anyhow.workspace = true
18+
deadpool-redis = "0.18.0"

Diff for: src/security_api/src/hackerone.rs

+10-17
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use graphql_client::GraphQLQuery;
22
use regex::Regex;
3-
use reqwest::blocking::{Client, ClientBuilder};
4-
use reqwest::header;
5-
use std::error::Error;
3+
use reqwest::{header, Client, ClientBuilder};
64
use std::time::Duration;
75

86
#[derive(Clone)]
@@ -29,6 +27,7 @@ impl HackerOneClient {
2927
.user_agent("HackerOneTracker (+github.com/hackermondev/hackerone-tracker)")
3028
.default_headers(headers)
3129
.connect_timeout(Duration::from_secs(5))
30+
.http2_prior_knowledge()
3231
.build()
3332
.unwrap();
3433

@@ -49,25 +48,26 @@ fn extract_csrf_token(html: &str) -> Option<String> {
4948
None
5049
}
5150

52-
pub fn get_hackerone_csrf_token(session_token: &str) -> Result<String, Box<dyn Error>> {
51+
pub async fn fetch_csrf_token(session_token: &str) -> Result<String, anyhow::Error> {
5352
let client = Client::new();
5453
let http_response = client
5554
.get("https://hackerone.com/bugs")
5655
.header("cookie", format!("__Host-session={};", session_token))
57-
.send()?
58-
.text()?;
56+
.send().await?;
57+
58+
let http_response = http_response.error_for_status()?;
59+
let http_response = http_response.text().await?;
5960

6061
let token = extract_csrf_token(&http_response);
6162
if token.is_none() {
62-
return Err("Could not extract token from page".into());
63+
return Err(anyhow::Error::msg("unable to find CSRF token in page"));
6364
}
6465

6566
Ok(token.unwrap())
6667
}
6768

6869
// GraphQL types
6970
type DateTime = String;
70-
type DateInput = String;
7171
type URI = String;
7272

7373
#[derive(GraphQLQuery, Debug)]
@@ -110,28 +110,21 @@ pub struct TeamNameHacktivityQuery;
110110
pub struct DiscoveryQuery;
111111

112112

113-
// impl Default for discovery_query::OrderDirection {
114-
// fn default() -> Self {
115-
// discovery_query::OrderDirection::popular
116-
// }
117-
// }
118-
119-
// Tests
120113
#[cfg(test)]
121114
mod tests {
122115
use super::*;
123116

124117
#[test]
125118
fn can_extract_csrf_token() {
126119
let csrf_token = "hello_world";
127-
let fake_page = format!(
120+
let mock_page = format!(
128121
r#"
129122
<meta name="csrf-param" content="authenticity_token" />
130123
<meta name="csrf-token" content="{csrf_token}" />
131124
"#
132125
);
133126

134-
let extracted_token = extract_csrf_token(&fake_page);
127+
let extracted_token = extract_csrf_token(&mock_page);
135128
assert_eq!(extracted_token.unwrap(), csrf_token);
136129
}
137130
}

Diff for: src/security_api/src/lib.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
11
pub mod hackerone;
22
pub mod models;
3-
pub mod redis;
4-
5-
pub fn add(left: usize, right: usize) -> usize {
6-
left + right
7-
}
8-
9-
#[cfg(test)]
10-
mod tests {
11-
use super::*;
12-
13-
#[test]
14-
fn it_works() {
15-
let result = add(2, 2);
16-
assert_eq!(result, 4);
17-
}
18-
}
3+
pub mod redis;

Diff for: src/security_api/src/models.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use chrono::NaiveDateTime;
22
use nanoid::nanoid;
33
use serde::{Deserialize, Serialize};
44

5-
#[derive(Debug, Deserialize, Serialize, Clone)]
5+
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
66
pub struct RepData {
77
pub reputation: i64,
88
pub rank: i64,
@@ -12,7 +12,7 @@ pub struct RepData {
1212
pub team_handle: Option<String>,
1313
}
1414

15-
#[derive(Debug, Deserialize, Serialize)]
15+
#[derive(Default, Debug, Deserialize, Serialize)]
1616
pub struct RepDataQueueItem {
1717
pub id: Option<String>,
1818
pub diff: Vec<Vec<RepData>>,
@@ -24,7 +24,6 @@ pub struct RepDataQueueItem {
2424

2525
impl RepDataQueueItem {
2626
pub fn create_id(&mut self) {
27-
// TODO: get rid of nanoid, write a unique id func
2827
let id = nanoid!();
2928
self.id = Some(id);
3029
}
@@ -60,7 +59,6 @@ pub struct ReportsDataQueueItem {
6059

6160
impl ReportsDataQueueItem {
6261
pub fn create_id(&mut self) {
63-
// TODO: get rid of nanoid, write a unique id func
6462
let id = nanoid!();
6563
self.id = Some(id);
6664
}

Diff for: src/security_api/src/redis.rs

+29-20
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,48 @@
1-
pub use redis;
1+
use std::sync::LazyLock;
22

3-
pub fn open(url: &str) -> Result<redis::Client, Box<dyn std::error::Error>> {
4-
let client = redis::Client::open(url)?;
5-
Ok(client)
3+
pub use deadpool_redis::redis;
4+
use deadpool_redis::{self as deadpool, redis::AsyncCommands, Connection};
5+
6+
static GLOBAL_REDIS_POOL: LazyLock<deadpool::Pool> = LazyLock::new(|| {
7+
let config = get_config();
8+
config.create_pool(Some(deadpool::Runtime::Tokio1)).unwrap()
9+
});
10+
11+
pub fn get_connection() -> deadpool::Pool {
12+
GLOBAL_REDIS_POOL.clone()
613
}
714

8-
pub fn save_vec_to_set<'a, V: serde::Deserialize<'a> + serde::Serialize>(
9-
name: String,
15+
pub fn get_config() -> deadpool::Config {
16+
let url = std::env::var("REDIS_URL");
17+
let url = url.expect("Redis connection URI required");
18+
deadpool::Config::from_url(url)
19+
}
20+
21+
pub async fn save_vec_to_set<'a, V: serde::Deserialize<'a> + serde::Serialize>(
22+
name: &str,
1023
data: Vec<V>,
1124
overwrite: bool,
12-
mut conn: &mut redis::Connection,
13-
) -> Result<(), Box<dyn std::error::Error>> {
25+
redis: &mut Connection,
26+
) -> Result<(), anyhow::Error> {
1427
if overwrite {
15-
redis::cmd("DEL").arg(&name).query(&mut conn)?;
28+
redis.del::<_, ()>(&name).await?;
1629
}
1730

1831
for i in data {
1932
let value_name = serde_json::to_string(&i)?;
20-
redis::cmd("SADD")
21-
.arg(&name)
22-
.arg(value_name)
23-
.query(&mut conn)?;
33+
redis.sadd::<_, _, ()>(&name, value_name).await?;
2434
}
2535

2636
Ok(())
2737
}
2838

29-
pub fn load_set_to_vec(
30-
name: String,
31-
mut conn: &mut redis::Connection,
32-
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
33-
let set_values: Vec<String> = redis::cmd("SMEMBERS").arg(&name).query(&mut conn)?;
34-
39+
pub async fn load_set_to_vec(
40+
name: &str,
41+
redis: &mut Connection,
42+
) -> Result<Vec<String>, anyhow::Error> {
43+
let set_members = redis.smembers::<_, Vec<String>>(&name).await?;
3544
let mut result = Vec::new();
36-
for mut value in set_values {
45+
for mut value in set_members {
3746
if value.starts_with('"') {
3847
value = value[1..value.len() - 1].to_string();
3948
}

Diff for: src/security_discord/Cargo.toml

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ edition = "2021"
77

88
[dependencies]
99
clap = { version = "4.0", features = ["derive", "env"] }
10-
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
10+
reqwest.workspace = true
1111
security_api = { path = "../security_api" }
1212
serde.workspace = true
1313
serde_json.workspace = true
1414
twilight-util = { version = "0.15.2", features = ["builder"] }
1515
twilight-model = "0.15.2"
1616
log.workspace = true
17-
pretty_env_logger.workspace = true
17+
pretty_env_logger.workspace = true
18+
tokio.workspace = true
19+
anyhow.workspace = true
20+
futures-util = "0.3.31"

0 commit comments

Comments
 (0)