use axum::{ extract::Request, http::StatusCode, middleware::Next, response::{IntoResponse, Response}, Json, }; use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; use serde_json::json; use crate::models::Claims; pub fn create_jwt(secret: &str, username: &str) -> anyhow::Result { let exp = jsonwebtoken::get_current_timestamp() + 24 * 3600; let claims = Claims { sub: username.to_string(), exp: exp as usize, }; let token = encode( &Header::default(), &claims, &EncodingKey::from_secret(secret.as_bytes()), )?; Ok(token) } pub fn decode_jwt(secret: &str, token: &str) -> anyhow::Result { let token_data = decode::( token, &DecodingKey::from_secret(secret.as_bytes()), &Validation::default(), )?; Ok(token_data.claims) } pub async fn auth_middleware( request: Request, next: Next, ) -> Result { let auth_header = request .headers() .get("authorization") .and_then(|value| value.to_str().ok()); let token = match auth_header { Some(value) if value.starts_with("Bearer ") => &value[7..], _ => { return Ok(( StatusCode::UNAUTHORIZED, Json(json!({"error": "Missing or invalid authorization header"})), ) .into_response()); } }; let secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "secret".to_string()); match decode_jwt(&secret, token) { Ok(_claims) => Ok(next.run(request).await), Err(_) => Ok(( StatusCode::UNAUTHORIZED, Json(json!({"error": "Invalid token"})), ) .into_response()), } }