diff --git a/src/jobs.rs b/src/jobs.rs index c9806ac..e021cce 100644 --- a/src/jobs.rs +++ b/src/jobs.rs @@ -341,7 +341,10 @@ mod tests { assert!(execution.completed_at.is_some()); assert_eq!(execution.success, Some(0)); - assert_eq!(execution.error_message, Some("Test error message".to_string())); + assert_eq!( + execution.error_message, + Some("Test error message".to_string()) + ); assert!(execution.records_processed.is_none()); } diff --git a/src/jwks.rs b/src/jwks.rs index 590d7d4..e24263c 100644 --- a/src/jwks.rs +++ b/src/jwks.rs @@ -102,8 +102,8 @@ fn random_kid() -> String { #[cfg(test)] mod tests { use super::*; - use tempfile::TempDir; use std::path::PathBuf; + use tempfile::TempDir; /// Helper to create test Keys config fn test_keys_config(temp_dir: &TempDir) -> Keys { @@ -156,10 +156,9 @@ mod tests { assert!(cfg.private_key_path.exists()); // Verify it contains valid JSON JWK - let content = fs::read_to_string(&cfg.private_key_path) - .expect("Failed to read private key"); - let jwk: Jwk = serde_json::from_str(&content) - .expect("Failed to parse private key JSON"); + let content = + fs::read_to_string(&cfg.private_key_path).expect("Failed to read private key"); + let jwk: Jwk = serde_json::from_str(&content).expect("Failed to parse private key JSON"); assert_eq!(jwk.key_type(), "RSA"); assert!(jwk.parameter("d").is_some()); // Private exponent exists @@ -178,10 +177,8 @@ mod tests { assert!(cfg.jwks_path.exists()); // Verify it contains valid JWKS structure - let content = fs::read_to_string(&cfg.jwks_path) - .expect("Failed to read JWKS"); - let jwks: Value = serde_json::from_str(&content) - .expect("Failed to parse JWKS JSON"); + let content = fs::read_to_string(&cfg.jwks_path).expect("Failed to read JWKS"); + let jwks: Value = serde_json::from_str(&content).expect("Failed to parse JWKS JSON"); assert!(jwks.get("keys").is_some()); assert!(jwks["keys"].is_array()); @@ -220,10 +217,7 @@ mod tests { let jwk1 = manager1.private_jwk(); let jwk2 = manager2.private_jwk(); - assert_eq!( - jwk1.parameter("n"), - jwk2.parameter("n") - ); + assert_eq!(jwk1.parameter("n"), jwk2.parameter("n")); } #[tokio::test] @@ -239,11 +233,13 @@ mod tests { let mut payload = JwtPayload::new(); payload.set_issuer("https://example.com"); payload.set_subject("user123"); - let exp_time: std::time::SystemTime = (chrono::Utc::now() + chrono::Duration::hours(1)).into(); + let exp_time: std::time::SystemTime = + (chrono::Utc::now() + chrono::Duration::hours(1)).into(); payload.set_expires_at(&exp_time); // Sign the JWT - let token = manager.sign_jwt_rs256(&payload) + let token = manager + .sign_jwt_rs256(&payload) .expect("Failed to sign JWT"); // Verify token is not empty and has 3 parts (header.payload.signature) @@ -252,10 +248,9 @@ mod tests { assert_eq!(parts.len(), 3); // Decode and verify header contains kid - let header_json = base64ct::Base64UrlUnpadded::decode_vec(parts[0]) - .expect("Failed to decode header"); - let header: Value = serde_json::from_slice(&header_json) - .expect("Failed to parse header"); + let header_json = + base64ct::Base64UrlUnpadded::decode_vec(parts[0]).expect("Failed to decode header"); + let header: Value = serde_json::from_slice(&header_json).expect("Failed to parse header"); assert_eq!(header["alg"], "RS256"); assert_eq!(header["kid"], "test-kid-123"); @@ -311,7 +306,9 @@ mod tests { // Verify all are valid base64url for kid in [kid1, kid2, kid3] { - assert!(kid.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')); + assert!(kid + .chars() + .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')); } } } diff --git a/src/settings.rs b/src/settings.rs index 3f465ae..762e38d 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -160,8 +160,8 @@ mod tests { let config_path = temp_dir.path().join("nonexistent.toml"); // Load settings with nonexistent file - should use defaults - let settings = Settings::load(config_path.to_str().unwrap()) - .expect("Failed to load settings"); + let settings = + Settings::load(config_path.to_str().unwrap()).expect("Failed to load settings"); assert_eq!(settings.server.host, "0.0.0.0"); assert_eq!(settings.server.port, 8080); @@ -194,8 +194,8 @@ private_key_path = "test_private.pem" fs::write(&config_path, config_content).expect("Failed to write config"); // Load settings - let settings = Settings::load(config_path.to_str().unwrap()) - .expect("Failed to load settings"); + let settings = + Settings::load(config_path.to_str().unwrap()).expect("Failed to load settings"); assert_eq!(settings.server.host, "127.0.0.1"); assert_eq!(settings.server.port, 9090); @@ -204,7 +204,10 @@ private_key_path = "test_private.pem" Some("https://idp.example.com".to_string()) ); assert_eq!(settings.server.allow_public_registration, true); - assert_eq!(settings.database.url, "postgresql://user:pass@localhost/testdb"); + assert_eq!( + settings.database.url, + "postgresql://user:pass@localhost/testdb" + ); } #[test] @@ -225,8 +228,8 @@ port = 8080 env::set_var("BARYCENTER__SERVER__HOST", "192.168.1.1"); // Load settings - env should override file - let settings = Settings::load(config_path.to_str().unwrap()) - .expect("Failed to load settings"); + let settings = + Settings::load(config_path.to_str().unwrap()).expect("Failed to load settings"); assert_eq!(settings.server.host, "192.168.1.1"); assert_eq!(settings.server.port, 9999); @@ -287,8 +290,8 @@ private_key_path = "relative/private.pem" "#; fs::write(&config_path, config_content).expect("Failed to write config"); - let settings = Settings::load(config_path.to_str().unwrap()) - .expect("Failed to load settings"); + let settings = + Settings::load(config_path.to_str().unwrap()).expect("Failed to load settings"); // Paths should be normalized to absolute assert!(settings.keys.jwks_path.is_absolute()); @@ -296,7 +299,10 @@ private_key_path = "relative/private.pem" // Should end with the relative path components assert!(settings.keys.jwks_path.ends_with("relative/jwks.json")); - assert!(settings.keys.private_key_path.ends_with("relative/private.pem")); + assert!(settings + .keys + .private_key_path + .ends_with("relative/private.pem")); } #[test] diff --git a/src/storage.rs b/src/storage.rs index 8d70c29..df289ac 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -5,7 +5,8 @@ use base64ct::Encoding; use chrono::Utc; use rand::RngCore; use sea_orm::{ - ActiveModelTrait, ColumnTrait, Database, DatabaseConnection, EntityTrait, QueryFilter, QueryOrder, Set, + ActiveModelTrait, ColumnTrait, Database, DatabaseConnection, EntityTrait, QueryFilter, + QueryOrder, Set, }; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -884,10 +885,7 @@ pub async fn update_passkey_name( Ok(()) } -pub async fn delete_passkey( - db: &DatabaseConnection, - credential_id: &str, -) -> Result<(), CrabError> { +pub async fn delete_passkey(db: &DatabaseConnection, credential_id: &str) -> Result<(), CrabError> { use entities::passkey::{Column, Entity}; Entity::delete_many() @@ -1204,7 +1202,7 @@ mod tests { Some("test_nonce".to_string()), "challenge_string", "S256", - 300, // 5 minutes TTL + 300, // 5 minutes TTL None, // auth_time ) .await @@ -1258,7 +1256,7 @@ mod tests { None, "", "", - 300, // TTL + 300, // TTL None, // auth_time ) .await @@ -1292,7 +1290,7 @@ mod tests { None, "", "", - 300, // TTL + 300, // TTL None, // auth_time ) .await @@ -1306,7 +1304,10 @@ mod tests { let past_timestamp = chrono::Utc::now().timestamp() - 600; // 10 minutes ago Entity::update_many() - .col_expr(Column::ExpiresAt, sea_orm::sea_query::Expr::value(past_timestamp)) + .col_expr( + Column::ExpiresAt, + sea_orm::sea_query::Expr::value(past_timestamp), + ) .filter(Column::Code.eq(&code.code)) .exec(db) .await @@ -1358,11 +1359,15 @@ mod tests { let test_db = TestDb::new().await; let db = test_db.connection(); - let token = issue_access_token(&db, "test_client_id", "test_subject", "openid profile", + let token = issue_access_token( + &db, + "test_client_id", + "test_subject", + "openid profile", 3600, // TTL ) - .await - .expect("Failed to issue access token"); + .await + .expect("Failed to issue access token"); assert!(!token.token.is_empty()); } @@ -1372,11 +1377,15 @@ mod tests { let test_db = TestDb::new().await; let db = test_db.connection(); - let token = issue_access_token(&db, "test_client_id", "test_subject", "openid profile", + let token = issue_access_token( + &db, + "test_client_id", + "test_subject", + "openid profile", 3600, // TTL ) - .await - .expect("Failed to issue access token"); + .await + .expect("Failed to issue access token"); let access_token = get_access_token(&db, &token.token) .await @@ -1393,11 +1402,15 @@ mod tests { let test_db = TestDb::new().await; let db = test_db.connection(); - let token = issue_access_token(&db, "test_client_id", "test_subject", "openid profile", + let token = issue_access_token( + &db, + "test_client_id", + "test_subject", + "openid profile", 3600, // TTL ) - .await - .expect("Failed to issue access token"); + .await + .expect("Failed to issue access token"); // Manually expire the token use entities::access_token::{Column, Entity}; @@ -1406,7 +1419,10 @@ mod tests { let past_timestamp = chrono::Utc::now().timestamp() - 7200; // 2 hours ago Entity::update_many() - .col_expr(Column::ExpiresAt, sea_orm::sea_query::Expr::value(past_timestamp)) + .col_expr( + Column::ExpiresAt, + sea_orm::sea_query::Expr::value(past_timestamp), + ) .filter(Column::Token.eq(&token.token)) .exec(db) .await @@ -1425,11 +1441,15 @@ mod tests { let test_db = TestDb::new().await; let db = test_db.connection(); - let token = issue_access_token(&db, "test_client_id", "test_subject", "openid profile", + let token = issue_access_token( + &db, + "test_client_id", + "test_subject", + "openid profile", 3600, // TTL ) - .await - .expect("Failed to issue access token"); + .await + .expect("Failed to issue access token"); // Manually revoke the token use entities::access_token::{Column, Entity}; @@ -1456,17 +1476,28 @@ mod tests { let db = test_db.connection(); // Create initial refresh token - let token1 = issue_refresh_token(&db, "test_subject", "test_client_id", "openid profile", + let token1 = issue_refresh_token( + &db, + "test_subject", + "test_client_id", + "openid profile", 86400, // TTL - None, // parent_token + None, // parent_token ) - .await - .expect("Failed to issue refresh token"); + .await + .expect("Failed to issue refresh token"); // Rotate to new token - let token2 = issue_refresh_token(&db, "test_client_id", "test_subject", "openid profile", 86400, Some(token1.token.clone())) - .await - .expect("Failed to rotate refresh token"); + let token2 = issue_refresh_token( + &db, + "test_client_id", + "test_subject", + "openid profile", + 86400, + Some(token1.token.clone()), + ) + .await + .expect("Failed to rotate refresh token"); // Verify parent chain let rt2 = get_refresh_token(&db, &token2.token) @@ -1482,12 +1513,16 @@ mod tests { let test_db = TestDb::new().await; let db = test_db.connection(); - let token = issue_refresh_token(&db, "test_subject", "test_client_id", "openid profile", + let token = issue_refresh_token( + &db, + "test_subject", + "test_client_id", + "openid profile", 86400, // TTL - None, // parent_token + None, // parent_token ) - .await - .expect("Failed to issue refresh token"); + .await + .expect("Failed to issue refresh token"); revoke_refresh_token(&db, &token.token) .await @@ -1604,9 +1639,15 @@ mod tests { .await .expect("Failed to create user"); - update_user(&db, &user.subject, false, Some("test@example.com".to_string()), Some(true)) - .await - .expect("Failed to update user"); + update_user( + &db, + &user.subject, + false, + Some("test@example.com".to_string()), + Some(true), + ) + .await + .expect("Failed to update user"); let updated = get_user_by_subject(&db, &user.subject) .await @@ -1627,9 +1668,15 @@ mod tests { .await .expect("Failed to create user"); - update_user(&db, &user.subject, true, Some("new@example.com".to_string()), None) - .await - .expect("Failed to update email"); + update_user( + &db, + &user.subject, + true, + Some("new@example.com".to_string()), + None, + ) + .await + .expect("Failed to update email"); let updated = get_user_by_subject(&db, &user.subject) .await diff --git a/src/user_sync.rs b/src/user_sync.rs index afb9690..6394338 100644 --- a/src/user_sync.rs +++ b/src/user_sync.rs @@ -134,7 +134,11 @@ async fn sync_user(db: &DatabaseConnection, user_def: &UserDefinition) -> Result db, &existing_user.subject, user_def.enabled, - if !email_matches { user_def.email.clone() } else { None }, + if !email_matches { + user_def.email.clone() + } else { + None + }, None, // requires_2fa not set during sync ) .await diff --git a/src/web.rs b/src/web.rs index 2859be7..0c47c00 100644 --- a/src/web.rs +++ b/src/web.rs @@ -1723,15 +1723,16 @@ async fn login_submit( .map(String::from); let now = chrono::Utc::now().timestamp(); - let session = match storage::create_session(&state.db, &subject, now, 3600, user_agent, None).await { - Ok(s) => s, - Err(_) => { - let return_to = urlencoded(&form.return_to.unwrap_or_default()); - let error = urlencoded("Failed to create session"); - return Redirect::temporary(&format!("/login?error={error}&return_to={return_to}")) - .into_response(); - } - }; + let session = + match storage::create_session(&state.db, &subject, now, 3600, user_agent, None).await { + Ok(s) => s, + Err(_) => { + let return_to = urlencoded(&form.return_to.unwrap_or_default()); + let error = urlencoded("Failed to create session"); + return Redirect::temporary(&format!("/login?error={error}&return_to={return_to}")) + .into_response(); + } + }; // Set cookie let cookie = SessionCookie::new(session.session_id); @@ -2126,12 +2127,12 @@ async fn passkey_register_finish( &cred_id_b64, &session.subject, &passkey_json, - counter, // Extracted from passkey - None, // aaguid - backup_eligible, // Extracted from passkey - backup_state, // Extracted from passkey - None, // transports - req.name.as_deref(), // Name from request + counter, // Extracted from passkey + None, // aaguid + backup_eligible, // Extracted from passkey + backup_state, // Extracted from passkey + None, // transports + req.name.as_deref(), // Name from request ) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;