diff --git a/imphnen-iam/src/v1/auth/auth_service.rs b/imphnen-iam/src/v1/auth/auth_service.rs index 96c85ce..2c3f1f3 100644 --- a/imphnen-iam/src/v1/auth/auth_service.rs +++ b/imphnen-iam/src/v1/auth/auth_service.rs @@ -72,10 +72,13 @@ impl AuthServiceTrait for AuthService { let user_repo = UsersRepository::new(&state); let auth_repo = AuthRepository::new(&state); - match user_repo.query_user_by_email(payload.email.clone()).await { + let email = &payload.email; + let password = &payload.password; + + match user_repo.query_user_by_email(email.to_string()).await { Ok(user) => { let is_password_correct = - verify_password(&payload.password, &user.password).unwrap_or(false); + verify_password(password, &user.password).unwrap_or(false); if !is_password_correct { return common_response( @@ -91,13 +94,16 @@ impl AuthServiceTrait for AuthService { ); } - let permissions: Vec = user.role.permissions.iter().map(|p| p.name.clone()).collect(); - let access_token = match encode_access_token(payload.email.clone(), user.id.id.to_raw(), permissions.clone()) { + // Avoid unnecessary clone of user for caching if not needed + let permissions: Vec = user.role.permissions.iter().map(|p| p.name.as_str()).map(str::to_owned).collect(); + let user_id = user.id.id.to_raw(); + + let access_token = match encode_access_token(email.to_string(), user_id.clone(), permissions.clone()) { Ok(token) => token, Err(_e) => { error!( "Failed to generate access token for {}: {}", - payload.email, _e + email, _e ); return common_response( StatusCode::INTERNAL_SERVER_ERROR, @@ -106,13 +112,12 @@ impl AuthServiceTrait for AuthService { } }; - let permissions: Vec = user.role.permissions.iter().map(|p| p.name.clone()).collect(); - let refresh_token = match encode_refresh_token(payload.email.clone(), user.id.id.to_raw(), permissions) { + let refresh_token = match encode_refresh_token(email.to_string(), user_id, permissions) { Ok(token) => token, Err(_e) => { error!( "Failed to generate refresh token for {}: {}", - payload.email, _e + email, _e ); return common_response( StatusCode::INTERNAL_SERVER_ERROR, @@ -131,6 +136,7 @@ impl AuthServiceTrait for AuthService { }, }; + // Only clone user if caching is required if let Err(err_store) = auth_repo.query_store_user(user.clone()).await { error!( "Failed to store user cache for {}: {}", diff --git a/imphnen-libs/src/argon/mod.rs b/imphnen-libs/src/argon/mod.rs index 6367b7b..769159e 100644 --- a/imphnen-libs/src/argon/mod.rs +++ b/imphnen-libs/src/argon/mod.rs @@ -8,7 +8,15 @@ use argon2::{ pub fn hash_password(password: &str) -> Result { let salt = SaltString::generate(&mut OsRng); - let argon2 = Argon2::default(); + let argon2 = if std::env::var("RUST_ENV").unwrap_or_default() == "test" || std::env::var("RUST_ENV").unwrap_or_default() == "development" { + Argon2::new( + argon2::Algorithm::Argon2id, + argon2::Version::V0x13, + argon2::Params::new(8 * 1024, 2, 1, None).unwrap() // 8MB, 2 iterations, 1 thread + ) + } else { + Argon2::default() + }; let password_hash = argon2 .hash_password(password.as_bytes(), &salt)? .to_string(); diff --git a/imphnen-middleware/src/auth_middleware/mod.rs b/imphnen-middleware/src/auth_middleware/mod.rs index 25bd28b..802b5b2 100644 --- a/imphnen-middleware/src/auth_middleware/mod.rs +++ b/imphnen-middleware/src/auth_middleware/mod.rs @@ -3,6 +3,8 @@ use axum::{ response::Response, }; use imphnen_libs::{AppState, jsonwebtoken::decode_access_token}; +use surrealdb::sql::Thing; +use imphnen_iam::v1::users::users_dto::UsersDetailQueryDto; use imphnen_utils::common_response; use axum_extra::headers::{authorization::Bearer, Authorization, HeaderMapExt}; use std::convert::Infallible; @@ -11,7 +13,7 @@ use imphnen_libs::ResourceEnum; use imphnen_utils::make_thing; pub async fn auth_middleware( - Extension(_state): Extension, // state is currently unused in this middleware + Extension(state): Extension, mut req: Request, next: Next, ) -> Result { @@ -37,11 +39,34 @@ pub async fn auth_middleware( let user_id = claims.user_id.clone(); - let repo = UsersService {}; let thing_id = make_thing(&ResourceEnum::Users.to_string(), &user_id); - let user_data = match repo.get_user_by_id_internal(&thing_id, &_state).await { - Ok(user) => user, - Err(_) => return Ok(common_response(StatusCode::UNAUTHORIZED, "User not found")), + + // Try SurrealDB mem first + let mem_db = &state.surrealdb_mem; + let mut user_data: Option = None; + if let Ok(opt_user) = mem_db.select(("users", &user_id)).await { + if let Some(user) = opt_user { + let user: imphnen_iam::v1::users::users_dto::UsersDetailQueryDto = user; + if !user.is_deleted && !user.role.is_deleted { + user_data = Some(user); + } + } + } + + // Fallback to main DB if not found in mem + let user_data = match user_data { + Some(user) => user, + None => { + let repo = UsersService {}; + match repo.get_user_by_id_internal(&thing_id, &state).await { + Ok(user) => { + // Optionally: insert into mem for future requests + let _: Result, _> = mem_db.update(&thing_id.id.to_raw()).content(user.clone()).await; + user + }, + Err(_) => return Ok(common_response(StatusCode::UNAUTHORIZED, "User not found")), + } + } }; req.extensions_mut().insert(user_data);