Spaces:
Sleeping
Sleeping
| use axum::{ | |
| extract::FromRequestParts, | |
| http::request::Parts, | |
| }; | |
| use jsonwebtoken::{decode, DecodingKey, Validation}; | |
| use serde::{Deserialize, Serialize}; | |
| use uuid::Uuid; | |
| use crate::errors::AppError; | |
| pub struct Claims { | |
| pub sub: Uuid, | |
| pub role: String, | |
| pub exp: u64, | |
| } | |
| pub struct AuthUser { | |
| pub id: Uuid, | |
| pub role: String, | |
| } | |
| impl<S> FromRequestParts<S> for AuthUser | |
| where | |
| S: Send + Sync, | |
| { | |
| type Rejection = AppError; | |
| async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> { | |
| // Retrieve Auth header | |
| let auth_header = parts | |
| .headers | |
| .get("Authorization") | |
| .and_then(|h| h.to_str().ok()) | |
| .ok_or_else(|| AppError::Unauthorized("Missing Authorization header".to_string()))?; | |
| if !auth_header.starts_with("Bearer ") { | |
| return Err(AppError::Unauthorized("Invalid Authorization header format".to_string())); | |
| } | |
| let token = &auth_header[7..]; | |
| // Decode JWT | |
| let jwt_secret = std::env::var("JWT_SECRET") | |
| .unwrap_or_else(|_| "invesa_secret_super_key_12345_secure_key".to_string()); | |
| let token_data = decode::<Claims>( | |
| token, | |
| &DecodingKey::from_secret(jwt_secret.as_bytes()), | |
| &Validation::default(), | |
| ) | |
| .map_err(|err| AppError::Unauthorized(format!("Invalid token: {}", err)))?; | |
| Ok(AuthUser { | |
| id: token_data.claims.sub, | |
| role: token_data.claims.role, | |
| }) | |
| } | |
| } | |