use std::sync::Arc; use axum::{ extract::State, http::{Request, StatusCode}, middleware::Next, response::Response, }; use axum_extra::extract::cookie::CookieJar; use uuid::Uuid; use crate::{ errors::service_error::ServiceError, helpers::constants::JWT_COOKIE_NAME, middlewares::request_info::RequestInfo, routes::AppState, }; pub async fn require_auth( cookies: CookieJar, State(state): State>, req: Request, next: Next, ) -> Result { // get jwt from cookies let auth_service = &state.service.auth_state.authentication; let token = if let Some(cookie) = cookies.get(JWT_COOKIE_NAME) { cookie.value().to_string() } else { return handle_unauthenticated().await; }; // validate jwt let is_valid = auth_service.is_valid_jwt(&token, None).await; let user_id = match is_valid { Ok(Some(claims)) => claims .sub .parse::() .map_err(|_| StatusCode::UNAUTHORIZED)?, Ok(None) => return handle_unauthenticated().await, Err(err) => { tracing::error!("Error validating JWT: {}", err); return Err(StatusCode::INTERNAL_SERVER_ERROR); } }; // ensure user exists if let Err(err) = state.service.user.get_user_by_id(user_id, None).await { match err { ServiceError::NotFound(_) => return handle_unauthenticated().await, _ => { tracing::error!("Error fetching user by ID: {}", err); return Err(StatusCode::INTERNAL_SERVER_ERROR); } } } let mut req = req; let user = req .extensions_mut() .get_or_insert_with(|| RequestInfo { user_id: None }); user.user_id = Some(user_id); Ok(next.run(req).await) } async fn handle_unauthenticated() -> Result { // TODO: log unauthenticated access attempts Err(StatusCode::UNAUTHORIZED) }