+7
-7
src/main.rs
+7
-7
src/main.rs
···
21
21
use tower_governor::governor::GovernorConfigBuilder;
22
22
use tower_http::compression::CompressionLayer;
23
23
use tower_http::cors::{Any, CorsLayer};
24
-
use tracing::{error, log};
24
+
use tracing::{error};
25
25
use tracing_subscriber::{EnvFilter, fmt, prelude::*};
26
26
27
27
mod middleware;
···
74
74
75
75
let intro = "\n\nThis is a PDS gatekeeper\n\nCode: https://tangled.sh/@baileytownsend.dev/pds-gatekeeper\n";
76
76
77
-
let banner = format!(" {}\n{}", body, intro);
77
+
let banner = format!(" {body}\n{intro}");
78
78
79
79
(
80
80
[(header::CONTENT_TYPE, "text/plain; charset=utf-8")],
···
85
85
#[tokio::main]
86
86
async fn main() -> Result<(), Box<dyn std::error::Error>> {
87
87
setup_tracing();
88
-
//TODO prod
88
+
//TODO may need to change where this reads from? Like an env variable for it's location?
89
89
dotenvy::from_path(Path::new("./pds.env"))?;
90
90
let pds_root = env::var("PDS_DATA_DIRECTORY")?;
91
-
let account_db_url = format!("{}/account.sqlite", pds_root);
92
-
log::info!("accounts_db_url: {}", account_db_url);
91
+
let account_db_url = format!("{pds_root}/account.sqlite");
93
92
94
93
let account_options = SqliteConnectOptions::new()
95
94
.journal_mode(SqliteJournalMode::Wal)
···
100
99
.connect_with(account_options)
101
100
.await?;
102
101
103
-
let bells_db_url = format!("{}/pds_gatekeeper.sqlite", pds_root);
102
+
let bells_db_url = format!("{pds_root}/pds_gatekeeper.sqlite");
104
103
let options = SqliteConnectOptions::new()
105
104
.journal_mode(SqliteJournalMode::Wal)
106
105
.filename(bells_db_url)
···
149
148
.per_second(60)
150
149
.burst_size(5)
151
150
.finish()
152
-
.unwrap();
151
+
.expect("failed to create governor config. this hsould not happen and is a bug");
152
+
153
153
let governor_limiter = governor_conf.limiter().clone();
154
154
let interval = Duration::from_secs(60);
155
155
// a separate background task to clean up
+9
-11
src/middleware.rs
+9
-11
src/middleware.rs
···
23
23
match token {
24
24
Ok(token) => {
25
25
match token {
26
-
None => json_error_response(StatusCode::BAD_REQUEST, "TokenRequired", "").unwrap(),
26
+
None => json_error_response(StatusCode::BAD_REQUEST, "TokenRequired", "").expect("Error creating an error response"),
27
27
Some(token) => {
28
28
let token = UntrustedToken::new(&token);
29
-
//Doing weird unwraps cause I can't do Result for middleware?
30
29
if token.is_err() {
31
30
return json_error_response(StatusCode::BAD_REQUEST, "TokenRequired", "")
32
-
.unwrap();
31
+
.expect("Error creating an error response");
33
32
}
34
-
let parsed_token = token.unwrap();
33
+
let parsed_token = token.expect("Already checked for error");
35
34
let claims: Result<Claims<TokenClaims>, ValidationError> =
36
35
parsed_token.deserialize_claims_unchecked();
37
36
if claims.is_err() {
38
37
return json_error_response(StatusCode::BAD_REQUEST, "TokenRequired", "")
39
-
.unwrap();
38
+
.expect("Error creating an error response");
40
39
}
41
40
42
-
let key = Hs256Key::new(env::var("PDS_JWT_SECRET").unwrap());
41
+
let key = Hs256Key::new(env::var("PDS_JWT_SECRET").expect("PDS_JWT_SECRET not set in the pds.env"));
43
42
let token: Result<Token<TokenClaims>, ValidationError> =
44
43
Hs256.validator(&key).validate(&parsed_token);
45
44
if token.is_err() {
46
45
return json_error_response(StatusCode::BAD_REQUEST, "InvalidToken", "")
47
-
.unwrap();
46
+
.expect("Error creating an error response");
48
47
}
49
-
let token = token.unwrap();
48
+
let token = token.expect("Already checked for error,");
50
49
//Not going to worry about expiration since it still goes to the PDS
51
-
52
50
req.extensions_mut()
53
51
.insert(Did(Some(token.claims().custom.sub.clone())));
54
52
next.run(req).await
···
56
54
}
57
55
}
58
56
Err(err) => {
59
-
log::error!("Error extracting token: {}", err);
60
-
json_error_response(StatusCode::BAD_REQUEST, "InvalidToken", "").unwrap()
57
+
log::error!("Error extracting token: {err}");
58
+
json_error_response(StatusCode::BAD_REQUEST, "InvalidToken", "").expect("Error creating an error response")
61
59
}
62
60
}
63
61
}
+2
-2
src/xrpc/com_atproto_server.rs
+2
-2
src/xrpc/com_atproto_server.rs
···
122
122
},
123
123
Err(err) => {
124
124
log::error!(
125
-
"Error during pre-auth check. This happens on the create_session endpoint when trying to decide if the user has access\n {}",
126
-
err
125
+
"Error during pre-auth check. This happens on the create_session endpoint when trying to decide if the user has access\n {err}"
126
+
127
127
);
128
128
json_error_response(
129
129
StatusCode::INTERNAL_SERVER_ERROR,
+27
-32
src/xrpc/helpers.rs
+27
-32
src/xrpc/helpers.rs
···
1
+
use anyhow::anyhow;
1
2
use crate::AppState;
2
3
use crate::xrpc::helpers::TokenCheckError::InvalidToken;
3
4
use axum::body::{Body, to_bytes};
···
103
104
//Just going a head and doing uppercase here.
104
105
let slice_one = &full_code[0..5].to_ascii_uppercase();
105
106
let slice_two = &full_code[5..10].to_ascii_uppercase();
106
-
format!("{}-{}", slice_one, slice_two)
107
+
format!("{slice_one}-{slice_two}")
107
108
}
108
109
109
110
pub enum TokenCheckError {
···
151
152
let sha = hasher.finalize();
152
153
let salt = hex::encode(&sha[..16]);
153
154
let hash_hex = scrypt_hex(password, &salt)?;
154
-
Ok(format!("{}:{}", salt, hash_hex))
155
+
Ok(format!("{salt}:{hash_hex}"))
155
156
}
156
157
157
-
async fn verify_password(password: &str, password_scrypt: &str) -> Result<bool, StatusCode> {
158
+
async fn verify_password(password: &str, password_scrypt: &str) -> anyhow::Result<bool> {
158
159
// Expected format: "salt:hash" where hash is hex of scrypt(password, salt, 64 bytes)
159
160
let mut parts = password_scrypt.splitn(2, ':');
160
161
let salt = match parts.next() {
···
195
196
)
196
197
.bind(identifier)
197
198
.fetch_optional(&state.account_pool)
198
-
.await
199
-
.map_err(|_| StatusCode::BAD_REQUEST)?,
199
+
.await?,
200
200
IdentifierType::Handle => sqlx::query_as::<_, (String, String, String, String)>(
201
201
"SELECT account.did, account.passwordScrypt, account.email, actor.handle
202
202
FROM actor
···
205
205
)
206
206
.bind(identifier)
207
207
.fetch_optional(&state.account_pool)
208
-
.await
209
-
.map_err(|_| StatusCode::BAD_REQUEST)?,
208
+
.await?,
210
209
IdentifierType::Did => sqlx::query_as::<_, (String, String, String, String)>(
211
210
"SELECT account.did, account.passwordScrypt, account.email, actor.handle
212
211
FROM actor
···
215
214
)
216
215
.bind(identifier)
217
216
.fetch_optional(&state.account_pool)
218
-
.await
219
-
.map_err(|_| StatusCode::BAD_REQUEST)?,
217
+
.await?,
220
218
};
221
219
222
220
if let Some((did, password_scrypt, email, handle)) = account_row {
···
226
224
)
227
225
.bind(did.clone())
228
226
.fetch_optional(&state.pds_gatekeeper_pool)
229
-
.await
230
-
.map_err(|_| StatusCode::BAD_REQUEST)?;
227
+
.await?;
231
228
232
229
let two_factor_required = match required_opt {
233
230
Some(row) => row.0 != 0,
···
249
246
}
250
247
}
251
248
Err(err) => {
252
-
log::error!("Error checking the app password: {}", err);
253
-
Err(StatusCode::BAD_REQUEST)
249
+
log::error!("Error checking the app password: {err}");
250
+
Err(err)
254
251
}
255
252
};
256
253
}
···
266
263
.await
267
264
{
268
265
Ok(_) => {
269
-
let _ = delete_all_email_tokens(&state.account_pool, did.clone()).await;
266
+
let result_of_cleanup = delete_all_email_tokens(&state.account_pool, did.clone()).await;
267
+
if result_of_cleanup.is_err(){
268
+
log::error!("There was an error deleting the email tokens after login: {:?}", result_of_cleanup.err())
269
+
}
270
270
Ok(AuthResult::ProxyThrough)
271
271
}
272
272
Err(err) => Ok(AuthResult::TokenCheckFailed(err)),
···
275
275
}
276
276
277
277
return match create_two_factor_token(&state.account_pool, did).await {
278
-
//TODO replace unwraps with the mythical ?
279
278
Ok(code) => {
280
279
let mut email_data = Map::new();
281
280
email_data.insert("token".to_string(), Value::from(code.clone()));
282
281
email_data.insert("handle".to_string(), Value::from(handle.clone()));
283
-
//TODO bad unwrap
284
282
let email_body = state
285
283
.template_engine
286
-
.render("two_factor_code.hbs", email_data)
287
-
.unwrap();
284
+
.render("two_factor_code.hbs", email_data)?;
288
285
289
286
let email = Message::builder()
290
287
//TODO prob get the proper type in the state
291
-
.from(state.mailer_from.parse().unwrap())
292
-
.to(email.parse().unwrap())
288
+
.from(state.mailer_from.parse()?)
289
+
.to(email.parse()?)
293
290
.subject("Sign in to Bluesky")
294
291
.multipart(
295
292
MultiPart::alternative() // This is composed of two parts.
296
293
.singlepart(
297
294
SinglePart::builder()
298
295
.header(header::ContentType::TEXT_PLAIN)
299
-
.body(format!("We received a sign-in request for the account @{}. Use the code: {} to sign in. If this wasn't you, we recommend taking steps to protect your account by changing your password at https://bsky.app/settings.", handle, code)), // Every message should have a plain text fallback.
296
+
.body(format!("We received a sign-in request for the account @{handle}. Use the code: {code} to sign in. If this wasn't you, we recommend taking steps to protect your account by changing your password at https://bsky.app/settings.")), // Every message should have a plain text fallback.
300
297
)
301
298
.singlepart(
302
299
SinglePart::builder()
303
300
.header(header::ContentType::TEXT_HTML)
304
301
.body(email_body),
305
302
),
306
-
)
307
-
//TODO bad
308
-
.unwrap();
303
+
)?;
309
304
match state.mailer.send(email).await {
310
305
Ok(_) => Ok(AuthResult::TwoFactorRequired),
311
306
Err(err) => {
312
-
log::error!("Error sending the 2FA email: {}", err);
313
-
Err(StatusCode::BAD_REQUEST)
307
+
log::error!("Error sending the 2FA email: {err}");
308
+
Err(anyhow!(err))
314
309
}
315
310
}
316
311
}
317
312
Err(err) => {
318
-
log::error!("error on creating a 2fa token: {}", err);
319
-
Err(StatusCode::BAD_REQUEST)
313
+
log::error!("error on creating a 2fa token: {err}");
314
+
Err(anyhow!(err))
320
315
}
321
316
};
322
317
}
···
351
346
352
347
match res {
353
348
Ok(_) => Ok(token),
354
-
Err(e) => {
355
-
log::error!("Error creating a two factor token: {}", e);
356
-
Err(anyhow::anyhow!(e))
349
+
Err(err) => {
350
+
log::error!("Error creating a two factor token: {err}");
351
+
Err(anyhow::anyhow!(err))
357
352
}
358
353
}
359
354
}
···
383
378
.fetch_optional(account_db)
384
379
.await
385
380
.map_err(|err| {
386
-
log::error!("Error getting the 2fa token: {}", err);
381
+
log::error!("Error getting the 2fa token: {err}");
387
382
InvalidToken
388
383
})?;
389
384