50 lines
1.5 KiB
Rust
50 lines
1.5 KiB
Rust
use axum::{
|
|
RequestPartsExt,
|
|
extract::FromRequestParts,
|
|
http::{StatusCode, request::Parts},
|
|
response::{IntoResponse, Response},
|
|
};
|
|
use axum_extra::TypedHeader;
|
|
use axum_extra::headers::{Authorization, authorization::Bearer};
|
|
use libertas_core::error::{CoreError, CoreResult};
|
|
use uuid::Uuid;
|
|
|
|
use crate::{security::TokenGenerator, state::AppState};
|
|
use std::sync::Arc;
|
|
|
|
pub struct UserId(pub Uuid);
|
|
|
|
impl FromRequestParts<AppState> for UserId {
|
|
type Rejection = Response;
|
|
|
|
async fn from_request_parts(
|
|
parts: &mut Parts,
|
|
state: &AppState,
|
|
) -> Result<Self, Self::Rejection> {
|
|
let tokenizer: Arc<dyn TokenGenerator> = state.token_generator.clone();
|
|
|
|
let result = (async || -> CoreResult<Uuid> {
|
|
let TypedHeader(Authorization(bearer)) = parts
|
|
.extract::<TypedHeader<Authorization<Bearer>>>()
|
|
.await
|
|
.map_err(|_| CoreError::Auth("Missing Authorization header".to_string()))?;
|
|
|
|
let user_id = tokenizer.verify_token(bearer.token())?;
|
|
|
|
Ok(user_id)
|
|
})()
|
|
.await;
|
|
|
|
match result {
|
|
Ok(user_id) => Ok(Self(user_id)),
|
|
Err(e) => {
|
|
let status = match e {
|
|
CoreError::Auth(_) => StatusCode::UNAUTHORIZED,
|
|
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
|
};
|
|
Err((status, e.to_string()).into_response())
|
|
}
|
|
}
|
|
}
|
|
}
|