From 1fb1feff560eb71f45a2ca33e48d4f34a2654072 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Wed, 4 Feb 2026 14:10:05 -0300 Subject: [PATCH] Fix: /api/auth/me now returns anonymous user instead of 401 --- src/directory/auth_routes.rs | 133 ++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 58 deletions(-) diff --git a/src/directory/auth_routes.rs b/src/directory/auth_routes.rs index 18223c5d..297a1600 100644 --- a/src/directory/auth_routes.rs +++ b/src/directory/auth_routes.rs @@ -55,15 +55,16 @@ pub struct LoginResponse { #[derive(Debug, Serialize)] pub struct CurrentUserResponse { - pub id: String, - pub username: String, + pub id: Option, + pub username: Option, pub email: Option, pub first_name: Option, pub last_name: Option, pub display_name: Option, - pub roles: Vec, + pub roles: Option>, pub organization_id: Option, pub avatar_url: Option, + pub is_anonymous: bool, } #[derive(Debug, Serialize)] @@ -372,67 +373,83 @@ pub async fn logout( } pub async fn get_current_user( - State(state): State>, + State(_state): State>, headers: axum::http::HeaderMap, -) -> Result, (StatusCode, Json)> { +) -> Json { let session_token = headers .get(header::AUTHORIZATION) .and_then(|v| v.to_str().ok()) - .and_then(|auth| auth.strip_prefix("Bearer ")) - .ok_or_else(|| { - warn!("get_current_user: Missing authorization header"); - ( - StatusCode::UNAUTHORIZED, - Json(ErrorResponse { - error: "Missing authorization token".to_string(), - details: None, - }), - ) - })?; + .and_then(|auth| auth.strip_prefix("Bearer ")); - if session_token.is_empty() { - warn!("get_current_user: Empty authorization token"); - return Err(( - StatusCode::UNAUTHORIZED, - Json(ErrorResponse { - error: "Invalid authorization token".to_string(), - details: None, - }), - )); + match session_token { + None => { + info!("get_current_user: no authorization header - returning anonymous user"); + Json(CurrentUserResponse { + id: None, + username: None, + email: None, + first_name: None, + last_name: None, + display_name: None, + roles: None, + organization_id: None, + avatar_url: None, + is_anonymous: true, + }) + } + Some(token) if token.is_empty() => { + info!("get_current_user: empty authorization token - returning anonymous user"); + Json(CurrentUserResponse { + id: None, + username: None, + email: None, + first_name: None, + last_name: None, + display_name: None, + roles: None, + organization_id: None, + avatar_url: None, + is_anonymous: true, + }) + } + Some(session_token) => { + info!("get_current_user: looking up session token (len={}, prefix={}...)", + session_token.len(), + &session_token[..std::cmp::min(20, session_token.len())]); + + let cache = SESSION_CACHE.read().await; + + if let Some(user_data) = cache.get(session_token) { + info!("get_current_user: found cached session for user: {}", user_data.email); + Json(CurrentUserResponse { + id: Some(user_data.user_id.clone()), + username: Some(user_data.username.clone()), + email: Some(user_data.email.clone()), + first_name: user_data.first_name.clone(), + last_name: user_data.last_name.clone(), + display_name: user_data.display_name.clone(), + roles: Some(user_data.roles.clone()), + organization_id: user_data.organization_id.clone(), + avatar_url: None, + is_anonymous: false, + }) + } else { + info!("get_current_user: session not found in cache - returning anonymous user"); + Json(CurrentUserResponse { + id: None, + username: None, + email: None, + first_name: None, + last_name: None, + display_name: None, + roles: None, + organization_id: None, + avatar_url: None, + is_anonymous: true, + }) + } + } } - - info!("get_current_user: looking up session token (len={}, prefix={}...)", - session_token.len(), - &session_token[..std::cmp::min(20, session_token.len())]); - - let cache = SESSION_CACHE.read().await; - - if let Some(user_data) = cache.get(session_token) { - info!("get_current_user: found cached session for user: {}", user_data.email); - - return Ok(Json(CurrentUserResponse { - id: user_data.user_id.clone(), - username: user_data.username.clone(), - email: Some(user_data.email.clone()), - first_name: user_data.first_name.clone(), - last_name: user_data.last_name.clone(), - display_name: user_data.display_name.clone(), - roles: user_data.roles.clone(), - organization_id: user_data.organization_id.clone(), - avatar_url: None, - })); - } - - drop(cache); - - warn!("get_current_user: session not found in cache"); - Err(( - StatusCode::UNAUTHORIZED, - Json(ErrorResponse { - error: "Session expired or invalid. Please log in again.".to_string(), - details: None, - }), - )) } pub async fn refresh_token(