From 812c81104a4cccc30dba1dd728f87015ac5ce8ab Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 23 Mar 2026 07:50:32 +0000 Subject: [PATCH] fix: prevent infinite redirect loop for non-admin users on admin UI When a non-admin user with a valid session cookie visited an admin-protected route, auth_middleware redirected them to /login?next=, and login_page immediately redirected them back because they were "logged in", causing an infinite redirect loop. Fix: only skip the login page when the logged-in user is also an admin. https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH --- server/src/auth.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/server/src/auth.rs b/server/src/auth.rs index 25743bc..838e4f2 100644 --- a/server/src/auth.rs +++ b/server/src/auth.rs @@ -243,10 +243,23 @@ pub async fn login_page( headers: HeaderMap, Query(params): Query, ) -> Response { - // Already logged in → redirect. - if current_user_id(&state, &headers).await.is_some() { - let next = params.next.as_deref().map(|n| safe_redirect(n, &state.domain_suffix)).unwrap_or_else(|| "/".into()); - return Redirect::to(&next).into_response(); + // Already logged in as an admin → redirect. + if let Some(uid) = current_user_id(&state, &headers).await { + let is_admin = if uid == "bootstrap" { + true + } else { + sqlx::query_scalar::<_, i64>("SELECT is_admin FROM users WHERE id = ?") + .bind(&uid) + .fetch_optional(&state.db) + .await + .unwrap_or(None) + .map(|v| v != 0) + .unwrap_or(false) + }; + if is_admin { + let next = params.next.as_deref().map(|n| safe_redirect(n, &state.domain_suffix)).unwrap_or_else(|| "/".into()); + return Redirect::to(&next).into_response(); + } } let next = params.next.map(|s| safe_redirect(&s, &state.domain_suffix)).unwrap_or_else(|| "/".into()); Html(login_html(&next, None)).into_response()