rustium 0.1.4

A Rust application framework that values concurrency, performance, and scalability
Documentation
use axum::{async_trait, extract::FromRequestParts, http::request::Parts, RequestPartsExt};
use axum_extra::{
    headers::{authorization::Bearer, Authorization},
    TypedHeader,
};
use di_axum::Inject;
use std::sync::Arc;

use crate::{
    authentication::{
        auth_service::IAuthService,
        auth_user::AuthUser,
        token::{decode_auth_token, TokenUser},
    },
    context::AppContext,
    error::AuthenticateError,
    prelude::*,
};

#[async_trait]
impl FromRequestParts<Arc<AppContext>> for TokenUser {
    type Rejection = RustiumError;

    async fn from_request_parts(
        parts: &mut Parts,
        state: &Arc<AppContext>,
    ) -> Result<Self, Self::Rejection> {
        let TypedHeader(Authorization(bearer)) = parts
            .extract::<TypedHeader<Authorization<Bearer>>>()
            .await
            .map_err(|_| AuthenticateError::InvalidToken)?;

        let Inject(auth_service) =
            parts
                .extract::<Inject<dyn IAuthService>>()
                .await
                .map_err(|_| {
                    RustiumError::NotFound("Authentication service was not initialized".into())
                })?;

        let token_data = decode_auth_token(bearer.token(), &state.settings.server.secret)
            .map_err(|_| AuthenticateError::InvalidToken)?;

        let user: Box<dyn AuthUser> = auth_service.get_claim_user(token_data.claims).await?;

        Ok(user.into())
    }
}