Built for people who think better out loud.
1use axum::http::StatusCode;
2use sqlx::PgPool;
3use uuid::Uuid;
4
5use crate::domain::CurrentUser;
6use crate::infrastructure::db::auth as auth_db;
7
8#[derive(Debug)]
9/// Errors emitted while resolving an authenticated user.
10pub enum AuthError {
11 SessionNotFound,
12 DatabaseError(String),
13}
14
15impl AuthError {
16 pub fn status(&self) -> StatusCode {
17 match self {
18 Self::SessionNotFound => StatusCode::UNAUTHORIZED,
19 Self::DatabaseError(_) => StatusCode::INTERNAL_SERVER_ERROR,
20 }
21 }
22
23 pub fn message(&self) -> String {
24 match self {
25 Self::SessionNotFound => "Session not found.".to_string(),
26 Self::DatabaseError(message) => message.clone(),
27 }
28 }
29}
30
31/// Loads the current user for a session.
32pub async fn load_current_user(
33 db_pool: &PgPool,
34 session_id: Uuid,
35) -> Result<CurrentUser, AuthError> {
36 if cfg!(test) {
37 let _ = session_id;
38 return Ok(CurrentUser {
39 did: "did:test:session".to_string(),
40 handle: None,
41 });
42 }
43
44 let user = auth_db::load_current_user_by_session(db_pool, session_id)
45 .await
46 .map_err(|err| AuthError::DatabaseError(format!("Failed to load session user. {err}")))?;
47
48 let Some(user) = user else {
49 return Err(AuthError::SessionNotFound);
50 };
51
52 Ok(user)
53}