1use crate::session::Session;
2use author_web::user::UserSession;
3use axum::async_trait;
4use axum::extract::FromRequestParts;
5use axum::http::request::Parts;
6use axum::http::StatusCode;
7use std::marker::PhantomData;
8use tracing::trace;
9
10#[derive(Clone)]
11pub struct User<U: Clone, Sess>(pub U, pub PhantomData<Sess>);
12
13#[derive(Clone)]
14pub struct UserWithRole<U: Clone>(pub U);
15
16#[async_trait]
17impl<S, U, Sess> FromRequestParts<S> for User<U, Sess>
18where
19 Sess: UserSession<User = U> + Clone + Send + Sync + 'static,
20 U: Clone,
21{
22 type Rejection = (StatusCode, &'static str);
23
24 async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
25 trace!("Loading user for request");
26
27 let Session(session) = parts
28 .extensions
29 .get::<Session<Sess>>()
30 .cloned()
31 .ok_or((StatusCode::FORBIDDEN, "Forbidden"))?;
32
33 trace!("Loaded session");
34
35 let user = session
36 .current_user()
37 .await
38 .map_err(|_| (StatusCode::FORBIDDEN, "Forbidden"))?
39 .ok_or((StatusCode::FORBIDDEN, "Forbidden"))?;
40
41 trace!("Loaded user");
42
43 Ok(User(user, PhantomData::default()))
44 }
45}