admin_helper.rs
126 lignes · 4182 octets
/// Admin Helper Functions /// Feature 009: Admin & Settings /// /// Helper functions to extract and validate admin claims from requests. /// These can be used directly in handlers when middleware cannot be applied. use axum::extract::Request; use axum::http::request::Parts; use sea_orm::DatabaseConnection; use crate::auth::jwt::Claims; use crate::auth::jwt::JwtService; use crate::auth::jwt_extractor; use crate::config::auth::AuthConfig; use crate::error::AppError; use crate::middleware::auth_required::extract_user_from_jwt; use crate::services::jwt_blacklist_service::JwtBlacklistService; /// Extract admin claims from request parts and headers /// /// This function extracts and validates admin claims from request parts. /// It can be used directly in handlers when middleware cannot be applied. /// /// # Arguments /// /// * `db` - Database connection /// * `parts` - Request parts (contains headers, URI, etc.) /// /// # Returns /// /// * `Ok(Claims)` if user is authenticated and has admin role /// * `Err(AppError::Unauthorized)` if not authenticated /// * `Err(AppError::Forbidden)` if authenticated but not admin pub async fn extract_admin_claims_from_parts( db: &DatabaseConnection, parts: &Parts, ) -> Result<Claims, AppError> { // Extract JWT from headers/cookies let jwt_token = jwt_extractor::extract_jwt_from_request_parts(parts)?; // Check if token is blacklisted if JwtBlacklistService::is_blacklisted(db, &jwt_token) .await .is_ok_and(|b| b) { tracing::warn!("Blacklisted JWT token used for admin route"); return Err(AppError::Unauthorized); } // Validate JWT token — use the shared AuthConfig from request extensions // when present, otherwise fall back to `AuthConfig::from_env()` (same // regression mitigation as `AuthService`/`AdminService` since commit // `d4d6828`). let auth_config = match parts .extensions .get::<std::sync::Arc<AuthConfig>>() .cloned() { Some(cfg) => cfg, None => match AuthConfig::from_env() { Ok(cfg) => std::sync::Arc::new(cfg), Err(err) => { tracing::error!( "admin_helper: AuthConfig unavailable (no extension and from_env failed): {err}" ); return Err(AppError::Config( "Auth configuration not available".to_string(), )); } }, }; let claims = JwtService::validate_token(&auth_config, &jwt_token).map_err(|_| { tracing::warn!("Invalid JWT token for admin route"); AppError::Unauthorized })?; // Check if user has admin role if !claims.roles.contains(&"admin".to_string()) { tracing::warn!( "Non-admin user {} attempted to access admin route", claims.sub ); return Err(AppError::Forbidden); } tracing::debug!("Admin user {} accessing admin route", claims.sub); Ok(claims) } /// Extract admin claims from request /// /// This function extracts and validates admin claims from a request. /// It can be used directly in handlers when middleware cannot be applied. /// /// # Arguments /// /// * `db` - Database connection /// * `request` - The HTTP request /// /// # Returns /// /// * `Ok(Claims)` if user is authenticated and has admin role /// * `Err(AppError::Unauthorized)` if not authenticated /// * `Err(AppError::Forbidden)` if authenticated but not admin pub async fn extract_admin_claims( db: &DatabaseConnection, request: &Request, ) -> Result<Claims, AppError> { // Extract user from JWT let claims = extract_user_from_jwt(db, request).await.ok_or_else(|| { tracing::warn!("Unauthenticated access attempt to admin route"); AppError::Unauthorized })?; // Check if user has admin role if !claims.roles.contains(&"admin".to_string()) { tracing::warn!( "Non-admin user {} attempted to access admin route", claims.sub ); return Err(AppError::Forbidden); } tracing::debug!("Admin user {} accessing admin route", claims.sub); Ok(claims) }
GitRust