obscura-server 0.3.9

A server for relaying secure messages using the Signal Protocol
Documentation
use crate::api::AppState;
use crate::core::auth::verify_jwt;
use crate::error::AppError;
use axum::http::HeaderValue;
use axum::{
    extract::FromRequestParts,
    http::{header, request::Parts},
};
use tower_http::request_id::{MakeRequestId, RequestId};
use uuid::Uuid;

pub struct AuthUser {
    pub user_id: Uuid,
}

impl FromRequestParts<AppState> for AuthUser {
    type Rejection = AppError;

    #[tracing::instrument(err, skip(parts, state))]
    async fn from_request_parts(parts: &mut Parts, state: &AppState) -> Result<Self, Self::Rejection> {
        let auth_header = parts.headers.get(header::AUTHORIZATION).ok_or(AppError::AuthError)?;

        let auth_str = auth_header.to_str().map_err(|_| AppError::AuthError)?;

        if !auth_str.starts_with("Bearer ") {
            return Err(AppError::AuthError);
        }

        let token = &auth_str[7..];

        let claims = verify_jwt(token, &state.config.auth.jwt_secret).map_err(|_| AppError::AuthError)?;

        tracing::Span::current().record("user_id", tracing::field::display(claims.sub));

        Ok(AuthUser { user_id: claims.sub })
    }
}

#[derive(Clone, Default)]
pub struct MakeRequestUuidOrHeader;

impl MakeRequestId for MakeRequestUuidOrHeader {
    fn make_request_id<B>(&mut self, request: &axum::http::Request<B>) -> Option<RequestId> {
        let header_value = request.headers().get("x-request-id").cloned().unwrap_or_else(|| {
            let uuid = Uuid::new_v4().to_string();
            HeaderValue::from_str(&uuid).unwrap()
        });

        Some(RequestId::new(header_value))
    }
}