An easy-to-host PDS on the ATProtocol, MacOS. Grandma-approved.

style: format code (Task 3)

+74 -46
+15 -4
crates/relay/src/db/oauth.rs
··· 634 634 .unwrap() 635 635 .expect("token must be found on first use"); 636 636 637 - assert_eq!(row.client_id, "https://app.example.com/client-metadata.json"); 637 + assert_eq!( 638 + row.client_id, 639 + "https://app.example.com/client-metadata.json" 640 + ); 638 641 assert_eq!(row.scope, "com.atproto.refresh"); 639 642 assert_eq!(row.jkt.as_deref(), Some("test-jkt-thumbprint")); 640 643 ··· 642 645 let second = consume_oauth_refresh_token(&pool, "consume-test-token-hash") 643 646 .await 644 647 .unwrap(); 645 - assert!(second.is_none(), "consumed token must not be found again (AC4.2)"); 648 + assert!( 649 + second.is_none(), 650 + "consumed token must not be found again (AC4.2)" 651 + ); 646 652 } 647 653 648 654 #[tokio::test] ··· 674 680 let result = consume_oauth_refresh_token(&pool, "expired-hash") 675 681 .await 676 682 .unwrap(); 677 - assert!(result.is_none(), "expired refresh token must return None (AC4.3)"); 683 + assert!( 684 + result.is_none(), 685 + "expired refresh token must return None (AC4.3)" 686 + ); 678 687 } 679 688 680 689 #[tokio::test] 681 690 async fn consume_oauth_refresh_token_returns_none_for_unknown_token() { 682 691 let pool = test_pool().await; 683 - let result = consume_oauth_refresh_token(&pool, "nonexistent-hash").await.unwrap(); 692 + let result = consume_oauth_refresh_token(&pool, "nonexistent-hash") 693 + .await 694 + .unwrap(); 684 695 assert!(result.is_none()); 685 696 } 686 697 }
+59 -42
crates/relay/src/routes/oauth_token.rs
··· 21 21 use crate::auth::{ 22 22 cleanup_expired_nonces, issue_nonce, validate_dpop_for_token_endpoint, DpopTokenEndpointError, 23 23 }; 24 - use crate::db::oauth::{ 25 - consume_oauth_refresh_token, store_oauth_refresh_token, 26 - }; 24 + use crate::db::oauth::{consume_oauth_refresh_token, store_oauth_refresh_token}; 27 25 use crate::routes::token::generate_token; 28 26 29 27 // ── Request / response types ────────────────────────────────────────────────── ··· 183 181 184 182 match grant_type { 185 183 "authorization_code" => handle_authorization_code(&state, &headers, form).await, 186 - "refresh_token" => { 187 - handle_refresh_token(&state, &headers, form).await 188 - } 184 + "refresh_token" => handle_refresh_token(&state, &headers, form).await, 189 185 _ => OAuthTokenError::new( 190 186 "unsupported_grant_type", 191 187 "grant_type must be authorization_code or refresh_token", ··· 392 388 state.config.public_url.trim_end_matches('/') 393 389 ); 394 390 395 - let jkt = match validate_dpop_for_token_endpoint( 396 - &dpop_token, 397 - "POST", 398 - &token_url, 399 - &state.dpop_nonces, 400 - ) 401 - .await 402 - { 403 - Ok(jkt) => jkt, 404 - Err(DpopTokenEndpointError::MissingHeader) => { 405 - return OAuthTokenError::new("invalid_dpop_proof", "DPoP header required") 391 + let jkt = 392 + match validate_dpop_for_token_endpoint(&dpop_token, "POST", &token_url, &state.dpop_nonces) 393 + .await 394 + { 395 + Ok(jkt) => jkt, 396 + Err(DpopTokenEndpointError::MissingHeader) => { 397 + return OAuthTokenError::new("invalid_dpop_proof", "DPoP header required") 398 + .into_response(); 399 + } 400 + Err(DpopTokenEndpointError::InvalidProof(msg)) => { 401 + return OAuthTokenError::new("invalid_dpop_proof", msg).into_response(); 402 + } 403 + Err(DpopTokenEndpointError::UseNonce(fresh_nonce)) => { 404 + return OAuthTokenError::with_nonce( 405 + "use_dpop_nonce", 406 + "DPoP nonce required", 407 + fresh_nonce, 408 + ) 406 409 .into_response(); 407 - } 408 - Err(DpopTokenEndpointError::InvalidProof(msg)) => { 409 - return OAuthTokenError::new("invalid_dpop_proof", msg).into_response(); 410 - } 411 - Err(DpopTokenEndpointError::UseNonce(fresh_nonce)) => { 412 - return OAuthTokenError::with_nonce( 413 - "use_dpop_nonce", 414 - "DPoP nonce required", 415 - fresh_nonce, 416 - ) 417 - .into_response(); 418 - } 419 - }; 410 + } 411 + }; 420 412 421 413 // Hash the presented refresh token for DB lookup. 422 414 let token_hash = crate::routes::token::sha256_hex( ··· 451 443 } 452 444 453 445 // Issue new ES256 access token. 454 - let access_token = 455 - match issue_access_token(&state.oauth_signing_keypair, &stored.did, &stored.scope, &jkt) { 456 - Ok(t) => t, 457 - Err(e) => return e.into_response(), 458 - }; 446 + let access_token = match issue_access_token( 447 + &state.oauth_signing_keypair, 448 + &stored.did, 449 + &stored.scope, 450 + &jkt, 451 + ) { 452 + Ok(t) => t, 453 + Err(e) => return e.into_response(), 454 + }; 459 455 460 456 // Generate and store new refresh token (rotation: old token already deleted above). 461 457 let new_refresh = generate_token(); ··· 507 503 508 504 use crate::app::{app, test_state, AppState}; 509 505 use crate::auth::issue_nonce; 510 - use crate::db::oauth::{register_oauth_client, store_authorization_code, store_oauth_refresh_token}; 506 + use crate::db::oauth::{ 507 + register_oauth_client, store_authorization_code, store_oauth_refresh_token, 508 + }; 511 509 use crate::routes::token::generate_token; 512 510 513 511 // ── DPoP proof test helpers ─────────────────────────────────────────────── ··· 1218 1216 .await 1219 1217 .unwrap(); 1220 1218 1221 - assert_eq!(resp.status(), StatusCode::OK, "valid rotation must return 200"); 1219 + assert_eq!( 1220 + resp.status(), 1221 + StatusCode::OK, 1222 + "valid rotation must return 200" 1223 + ); 1222 1224 assert!( 1223 1225 resp.headers().contains_key("DPoP-Nonce"), 1224 1226 "success response must include DPoP-Nonce header" 1225 1227 ); 1226 1228 1227 1229 let json = json_body(resp).await; 1228 - assert!(json["access_token"].is_string(), "access_token must be present"); 1230 + assert!( 1231 + json["access_token"].is_string(), 1232 + "access_token must be present" 1233 + ); 1229 1234 assert_eq!(json["token_type"], "DPoP"); 1230 1235 assert_eq!(json["expires_in"], 300); 1231 - assert!(json["refresh_token"].is_string(), "rotated refresh_token must be present"); 1236 + assert!( 1237 + json["refresh_token"].is_string(), 1238 + "rotated refresh_token must be present" 1239 + ); 1232 1240 1233 1241 // Rotated token must differ from the original. 1234 1242 let new_rt = json["refresh_token"].as_str().unwrap(); 1235 1243 assert_ne!( 1236 - new_rt, plaintext.as_str(), 1244 + new_rt, 1245 + plaintext.as_str(), 1237 1246 "rotated refresh token must differ from original" 1238 1247 ); 1239 1248 } ··· 1265 1274 .oneshot(post_token_with_dpop(&body, &dpop1)) 1266 1275 .await 1267 1276 .unwrap(); 1268 - assert_eq!(first_resp.status(), StatusCode::OK, "first use must succeed"); 1277 + assert_eq!( 1278 + first_resp.status(), 1279 + StatusCode::OK, 1280 + "first use must succeed" 1281 + ); 1269 1282 1270 1283 // Second use of the same original token: must return invalid_grant. 1271 1284 let nonce2 = issue_nonce(&state.dpop_nonces).await; ··· 1281 1294 .await 1282 1295 .unwrap(); 1283 1296 1284 - assert_eq!(resp2.status(), StatusCode::BAD_REQUEST, "second use must return 400"); 1297 + assert_eq!( 1298 + resp2.status(), 1299 + StatusCode::BAD_REQUEST, 1300 + "second use must return 400" 1301 + ); 1285 1302 let json = json_body(resp2).await; 1286 1303 assert_eq!( 1287 1304 json["error"], "invalid_grant",