use axum::{ extract::Request, middleware::Next, response::{IntoResponse, Response}, }; use reqwest::StatusCode; use tower_sessions::Session; use crate::infrastructure::auth::LOGGED_IN_USER_SESS_KEY; use crate::infrastructure::state::UserStateInner; /// Server function endpoints that are allowed without authentication. /// /// `check-auth` must be public so the frontend can determine login state. const PUBLIC_API_ENDPOINTS: &[&str] = &["/api/check-auth"]; /// Axum middleware that enforces authentication on `/api/` server /// function endpoints. /// /// Requests whose path starts with `/api/` (except those listed in /// [`PUBLIC_API_ENDPOINTS`]) are rejected with `401 Unauthorized` when /// no valid session exists. All other paths pass through untouched. pub async fn require_auth(session: Session, request: Request, next: Next) -> Response { let path = request.uri().path(); // Only gate /api/ server function routes. if path.starts_with("/api/") && !PUBLIC_API_ENDPOINTS.contains(&path) { let is_authed = session .get::(LOGGED_IN_USER_SESS_KEY) .await .ok() .flatten() .is_some(); if !is_authed { return (StatusCode::UNAUTHORIZED, "Authentication required").into_response(); } } next.run(request).await }