invesa / src /middleware.rs
gowtham851's picture
feat: Add self-contained Rust backend with local PostgreSQL database
6c93417
use axum::{
extract::FromRequestParts,
http::request::Parts,
};
use jsonwebtoken::{decode, DecodingKey, Validation};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::errors::AppError;
#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
pub sub: Uuid,
pub role: String,
pub exp: u64,
}
#[derive(Debug, Clone)]
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,
})
}
}