fix: address Phase 1-2 audit findings
- CORS: replace permissive() with configurable whitelist (default.toml) - Auth store: synchronously restore state at creation to eliminate flash-of-login-page on refresh - MainLayout: menu highlight now tracks current route via useLocation - Add extractErrorMessage() utility to reduce repeated error parsing - Fix all clippy warnings across 4 crates (erp-auth, erp-config, erp-workflow, erp-message): remove unnecessary casts, use div_ceil, collapse nested ifs, reduce function arguments with DTOs
This commit is contained in:
@@ -12,6 +12,13 @@ use crate::error::AuthResult;
|
||||
use super::password;
|
||||
use super::token_service::TokenService;
|
||||
|
||||
/// JWT configuration needed for token signing.
|
||||
pub struct JwtConfig<'a> {
|
||||
pub secret: &'a str,
|
||||
pub access_ttl_secs: i64,
|
||||
pub refresh_ttl_secs: i64,
|
||||
}
|
||||
|
||||
/// Authentication service handling login, token refresh, and logout.
|
||||
pub struct AuthService;
|
||||
|
||||
@@ -32,9 +39,7 @@ impl AuthService {
|
||||
username: &str,
|
||||
password_plain: &str,
|
||||
db: &sea_orm::DatabaseConnection,
|
||||
jwt_secret: &str,
|
||||
access_ttl_secs: i64,
|
||||
refresh_ttl_secs: i64,
|
||||
jwt: &JwtConfig<'_>,
|
||||
event_bus: &EventBus,
|
||||
) -> AuthResult<LoginResp> {
|
||||
// 1. Find user by tenant_id + username
|
||||
@@ -85,15 +90,15 @@ impl AuthService {
|
||||
tenant_id,
|
||||
roles.clone(),
|
||||
permissions,
|
||||
jwt_secret,
|
||||
access_ttl_secs,
|
||||
jwt.secret,
|
||||
jwt.access_ttl_secs,
|
||||
)?;
|
||||
let (refresh_token, _) = TokenService::sign_refresh_token(
|
||||
user_model.id,
|
||||
tenant_id,
|
||||
db,
|
||||
jwt_secret,
|
||||
refresh_ttl_secs,
|
||||
jwt.secret,
|
||||
jwt.refresh_ttl_secs,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -129,7 +134,7 @@ impl AuthService {
|
||||
Ok(LoginResp {
|
||||
access_token,
|
||||
refresh_token,
|
||||
expires_in: access_ttl_secs as u64,
|
||||
expires_in: jwt.access_ttl_secs as u64,
|
||||
user: user_resp,
|
||||
})
|
||||
}
|
||||
@@ -138,13 +143,11 @@ impl AuthService {
|
||||
pub async fn refresh(
|
||||
refresh_token_str: &str,
|
||||
db: &sea_orm::DatabaseConnection,
|
||||
jwt_secret: &str,
|
||||
access_ttl_secs: i64,
|
||||
refresh_ttl_secs: i64,
|
||||
jwt: &JwtConfig<'_>,
|
||||
) -> AuthResult<LoginResp> {
|
||||
// Validate existing refresh token
|
||||
let (old_token_id, claims) =
|
||||
TokenService::validate_refresh_token(refresh_token_str, db, jwt_secret).await?;
|
||||
TokenService::validate_refresh_token(refresh_token_str, db, jwt.secret).await?;
|
||||
|
||||
// Revoke the old token (rotation)
|
||||
TokenService::revoke_token(old_token_id, db).await?;
|
||||
@@ -161,15 +164,15 @@ impl AuthService {
|
||||
claims.tid,
|
||||
roles.clone(),
|
||||
permissions,
|
||||
jwt_secret,
|
||||
access_ttl_secs,
|
||||
jwt.secret,
|
||||
jwt.access_ttl_secs,
|
||||
)?;
|
||||
let (new_refresh_token, _) = TokenService::sign_refresh_token(
|
||||
claims.sub,
|
||||
claims.tid,
|
||||
db,
|
||||
jwt_secret,
|
||||
refresh_ttl_secs,
|
||||
jwt.secret,
|
||||
jwt.refresh_ttl_secs,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -195,7 +198,7 @@ impl AuthService {
|
||||
Ok(LoginResp {
|
||||
access_token,
|
||||
refresh_token: new_refresh_token,
|
||||
expires_in: access_ttl_secs as u64,
|
||||
expires_in: jwt.access_ttl_secs as u64,
|
||||
user: user_resp,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user