diff --git a/imphnen-iam/src/v1/auth/auth_service.rs b/imphnen-iam/src/v1/auth/auth_service.rs index 85a1fc5..14334cf 100644 --- a/imphnen-iam/src/v1/auth/auth_service.rs +++ b/imphnen-iam/src/v1/auth/auth_service.rs @@ -98,11 +98,9 @@ impl AuthServiceTrait for AuthService { ); } - // 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()) { + let access_token = match encode_access_token(email.to_string(), user_id.clone()) { Ok(token) => token, Err(_e) => { error!( @@ -116,7 +114,7 @@ impl AuthServiceTrait for AuthService { } }; - let refresh_token = match encode_refresh_token(email.to_string(), user_id, permissions) { + let refresh_token = match encode_refresh_token(email.to_string(), user_id) { Ok(token) => token, Err(_e) => { error!( @@ -205,8 +203,7 @@ 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()) { + let access_token = match encode_access_token(payload.email.clone(), user.id.id.to_raw()) { Ok(token) => token, Err(_e) => { error!( @@ -220,8 +217,7 @@ 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(payload.email.clone(), user.id.id.to_raw()) { Ok(token) => token, Err(_e) => { error!( @@ -432,8 +428,7 @@ impl AuthServiceTrait for AuthService { } }; - let permissions: Vec = user.role.permissions.iter().map(|p| p.name.clone()).collect(); - let access_token = match encode_access_token(user.email.clone(), user.id.id.to_raw(), permissions.clone()) { + let access_token = match encode_access_token(user.email.clone(), user.id.id.to_raw()) { Ok(token) => token, Err(_e) => { error!("Failed to generate access token for {}: {}", user.email, _e); @@ -443,7 +438,7 @@ impl AuthServiceTrait for AuthService { ); } }; - let refresh_token = match encode_refresh_token(user.email.clone(), user.id.id.to_raw(), permissions) { + let refresh_token = match encode_refresh_token(user.email.clone(), user.id.id.to_raw()) { Ok(token) => token, Err(_e) => { error!("Failed to generate refresh token for {}: {}", user.email, _e); @@ -477,8 +472,7 @@ impl AuthServiceTrait for AuthService { tokio::spawn(async move { let user_repo = UsersRepository::new(&state); if let Ok(user) = user_repo.query_user_by_email(payload.email.clone()).await { - let permissions: Vec = user.role.permissions.iter().map(|p| p.name.clone()).collect(); - let token = match encode_reset_password_token(user.email.clone(), user.id.id.to_raw(), permissions) { + let token = match encode_reset_password_token(user.email.clone(), user.id.id.to_raw()) { Ok(token) => token, Err(_e) => { error!("Failed to generate reset password token for {}: {}", user.email, _e); diff --git a/imphnen-iam/src/v1/auth/google/google_oauth_service.rs b/imphnen-iam/src/v1/auth/google/google_oauth_service.rs index 94d5593..3abd334 100644 --- a/imphnen-iam/src/v1/auth/google/google_oauth_service.rs +++ b/imphnen-iam/src/v1/auth/google/google_oauth_service.rs @@ -338,15 +338,13 @@ where } }; - let permissions: Vec = user.role.permissions.iter().map(|p| p.name.clone()).collect(); -let access_token = encode_access_token(user.email.clone(), user.id.clone(), permissions.clone()) +let access_token = encode_access_token(user.email.clone(), user.id.clone()) .map_err(|e| { error!("Failed to generate access token for {}: {:?}", user.email, e); Error::Auth("Failed to generate access token".to_string()) })?; - let permissions: Vec = user.role.permissions.iter().map(|p| p.name.clone()).collect(); -let refresh_token = encode_refresh_token(user.email.clone(), user.id.clone(), permissions) +let refresh_token = encode_refresh_token(user.email.clone(), user.id.clone()) .map_err(|e| { error!("Failed to generate refresh token for {}: {:?}", user.email, e); Error::Auth("Failed to generate refresh token".to_string()) diff --git a/imphnen-iam/src/v1/permissions/permissions_guard.rs b/imphnen-iam/src/v1/permissions/permissions_guard.rs index 1bd231f..78df855 100644 --- a/imphnen-iam/src/v1/permissions/permissions_guard.rs +++ b/imphnen-iam/src/v1/permissions/permissions_guard.rs @@ -1,11 +1,10 @@ use super::PermissionsEnum; -use crate::{AppState, common_response, decode_access_token}; +use crate::{AppState, common_response, decode_access_token, UsersRepository}; use axum::{ http::{HeaderMap, StatusCode}, response::Response, Extension, }; use axum_extra::headers::{authorization::Bearer, Authorization, HeaderMapExt}; -// Removed imphnen_utils::make_thing as it's no longer needed here pub async fn permissions_guard( headers: HeaderMap, @@ -32,10 +31,23 @@ pub async fn permissions_guard( })? .claims; - // Use permissions from JWT for the check + // Fetch user from database to get permissions + let user_repo = UsersRepository::new(&state); + let user = match user_repo.query_user_by_email(claims.sub.clone()).await { + Ok(user) => user, + Err(_) => { + return Err(common_response( + StatusCode::UNAUTHORIZED, + "User not found", + )); + } + }; + + // Check permissions from database + let user_permissions: Vec = user.role.permissions.iter().map(|p| p.name.clone()).collect(); for required in &required_permissions { let required_str = required.to_string(); - if !claims.permissions.contains(&required_str) { + if !user_permissions.contains(&required_str) { eprintln!(" MISSING REQUIRED PERMISSION: {required_str}"); return Err(common_response( StatusCode::FORBIDDEN, diff --git a/imphnen-libs/src/jsonwebtoken/mod.rs b/imphnen-libs/src/jsonwebtoken/mod.rs index 111420c..3f8f106 100644 --- a/imphnen-libs/src/jsonwebtoken/mod.rs +++ b/imphnen-libs/src/jsonwebtoken/mod.rs @@ -12,19 +12,18 @@ pub struct Claims { pub iat: usize, pub sub: String, pub user_id: String, - pub permissions: Vec, } static ACCESS_HEADER: once_cell::sync::Lazy
= once_cell::sync::Lazy::new(Header::default); static ACCESS_KEY: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { EncodingKey::from_secret(ENV.access_token_secret.as_ref()) }); -pub fn encode_access_token(sub: String, user_id: String, permissions: Vec) -> Result { +pub fn encode_access_token(sub: String, user_id: String) -> Result { let now = Utc::now(); let expire: TimeDelta = Duration::minutes(15); let exp: usize = (now + expire).timestamp() as usize; let iat: usize = now.timestamp() as usize; - let claim = Claims { iat, exp, sub, user_id, permissions }; + let claim = Claims { iat, exp, sub, user_id }; encode( &ACCESS_HEADER, &claim, @@ -33,14 +32,14 @@ pub fn encode_access_token(sub: String, user_id: String, permissions: Vec) -> Result { +pub fn encode_reset_password_token(sub: String, user_id: String) -> Result { let env = &ENV; let secret: String = env.access_token_secret.clone(); let now = Utc::now(); let expire: TimeDelta = Duration::minutes(5); let exp: usize = (now + expire).timestamp() as usize; let iat: usize = now.timestamp() as usize; - let claim = Claims { iat, exp, sub, user_id, permissions }; + let claim = Claims { iat, exp, sub, user_id }; encode( &Header::default(), &claim, @@ -67,12 +66,12 @@ static REFRESH_HEADER: once_cell::sync::Lazy
= once_cell::sync::Lazy::ne static REFRESH_KEY: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { EncodingKey::from_secret(ENV.refresh_token_secret.as_ref()) }); -pub fn encode_refresh_token(sub: String, user_id: String, permissions: Vec) -> Result { +pub fn encode_refresh_token(sub: String, user_id: String) -> Result { let now = Utc::now(); let expire: TimeDelta = Duration::days(1); let exp: usize = (now + expire).timestamp() as usize; let iat: usize = now.timestamp() as usize; - let claim = Claims { iat, exp, sub, user_id, permissions }; + let claim = Claims { iat, exp, sub, user_id }; encode( &REFRESH_HEADER, &claim, @@ -95,6 +94,6 @@ pub fn decode_refresh_token( result // Explicitly return result } -pub fn generate_jwt(user_id: &str, permissions: Vec) -> Result { - encode_access_token(user_id.to_string(), user_id.to_string(), permissions) +pub fn generate_jwt(user_id: &str) -> Result { + encode_access_token(user_id.to_string(), user_id.to_string()) }