Skip to main content

purwa_auth/
extract.rs

1//! Extractors built on [`axum_login::AuthSession`].
2
3use axum::extract::FromRequestParts;
4use axum::http::request::Parts;
5use axum_login::{AuthSession, AuthnBackend};
6use purwa_core::PurwaError;
7
8/// Authenticated user: fails with **401** if the session has no user.
9///
10/// Use with routes that already use [`crate::session::AuthManagerLayerBuilder`] / auth layer.
11#[derive(Debug, Clone)]
12pub struct CurrentUser<B>(pub B::User)
13where
14    B: AuthnBackend + Clone + Send + Sync + 'static,
15    B::User: std::fmt::Debug + Clone + Send + Sync + 'static;
16
17impl<S, B> FromRequestParts<S> for CurrentUser<B>
18where
19    B: AuthnBackend + Clone + Send + Sync + 'static,
20    B::User: std::fmt::Debug + Clone + Send + Sync + 'static,
21    S: Send + Sync,
22{
23    type Rejection = PurwaError;
24
25    async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
26        let auth = AuthSession::<B>::from_request_parts(parts, state)
27            .await
28            .map_err(|_| PurwaError::internal("auth session unavailable"))?;
29
30        let Some(user) = auth.user.clone() else {
31            return Err(PurwaError::unauthorized("login required"));
32        };
33
34        Ok(CurrentUser(user))
35    }
36}