Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com> Reviewed-on: #5
42 lines
1.3 KiB
Rust
42 lines
1.3 KiB
Rust
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::<UserStateInner>(LOGGED_IN_USER_SESS_KEY)
|
|
.await
|
|
.ok()
|
|
.flatten()
|
|
.is_some();
|
|
|
|
if !is_authed {
|
|
return (StatusCode::UNAUTHORIZED, "Authentication required").into_response();
|
|
}
|
|
}
|
|
|
|
next.run(request).await
|
|
}
|