Checkpoint: Migration to axum

This commit is contained in:
Lennart
2025-06-08 14:10:12 +02:00
parent 790c657b08
commit 95889e3df1
60 changed files with 1476 additions and 2205 deletions

View File

@@ -1,103 +1,91 @@
use super::AuthenticationProvider;
use actix_session::Session;
use actix_web::{
FromRequest, HttpMessage,
dev::{Service, ServiceRequest, ServiceResponse, Transform, forward_ready},
http::header::Header,
};
use actix_web_httpauth::headers::authorization::{Authorization, Basic};
use axum::{extract::Request, response::Response};
use futures_core::future::BoxFuture;
use headers::{Authorization, HeaderMapExt, authorization::Basic};
use std::{
future::{Future, Ready, ready},
pin::Pin,
sync::Arc,
task::{Context, Poll},
};
use tower::{Layer, Service};
use tracing::{Instrument, info_span};
pub struct AuthenticationMiddleware<AP: AuthenticationProvider> {
pub struct AuthenticationLayer<AP: AuthenticationProvider> {
auth_provider: Arc<AP>,
}
impl<AP: AuthenticationProvider> AuthenticationMiddleware<AP> {
impl<AP: AuthenticationProvider> Clone for AuthenticationLayer<AP> {
fn clone(&self) -> Self {
Self {
auth_provider: self.auth_provider.clone(),
}
}
}
impl<AP: AuthenticationProvider> AuthenticationLayer<AP> {
pub fn new(auth_provider: Arc<AP>) -> Self {
Self { auth_provider }
}
}
impl<AP: AuthenticationProvider, S, B> Transform<S, ServiceRequest> for AuthenticationMiddleware<AP>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> + 'static,
S::Future: 'static,
B: 'static,
AP: 'static,
{
type Error = actix_web::Error;
type Response = ServiceResponse<B>;
type InitError = ();
type Transform = InnerAuthenticationMiddleware<S, AP>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
impl<S, AP: AuthenticationProvider> Layer<S> for AuthenticationLayer<AP> {
type Service = AuthenticationMiddleware<S, AP>;
fn new_transform(&self, service: S) -> Self::Future {
ready(Ok(InnerAuthenticationMiddleware {
service: Arc::new(service),
auth_provider: Arc::clone(&self.auth_provider),
}))
fn layer(&self, inner: S) -> Self::Service {
Self::Service {
inner,
auth_provider: self.auth_provider.clone(),
}
}
}
pub struct InnerAuthenticationMiddleware<S, AP: AuthenticationProvider> {
service: Arc<S>,
pub struct AuthenticationMiddleware<S, AP: AuthenticationProvider> {
inner: S,
auth_provider: Arc<AP>,
}
impl<S, B, AP> Service<ServiceRequest> for InnerAuthenticationMiddleware<S, AP>
impl<S: Clone, AP: AuthenticationProvider> Clone for AuthenticationMiddleware<S, AP> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
auth_provider: self.auth_provider.clone(),
}
}
}
impl<S: Clone, AP: AuthenticationProvider> Service<Request> for AuthenticationMiddleware<S, AP>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> + 'static,
S::Future: 'static,
AP: AuthenticationProvider,
S: Service<Request, Response = Response> + Send + 'static,
S::Future: Send + 'static,
{
type Response = ServiceResponse<B>;
type Error = actix_web::Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
type Response = S::Response;
type Error = S::Error;
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
forward_ready!(service);
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&self, req: ServiceRequest) -> Self::Future {
let service = Arc::clone(&self.service);
let auth_provider = Arc::clone(&self.auth_provider);
fn call(&mut self, mut request: Request) -> Self::Future {
let auth_header: Option<Authorization<Basic>> = request.headers().typed_get();
let ap = self.auth_provider.clone();
let mut inner = self.inner.clone();
// request.extensions_mut();
Box::pin(async move {
if let Ok(auth) = Authorization::<Basic>::parse(req.request()) {
let user_id = auth.as_ref().user_id();
if let Some(password) = auth.as_ref().password() {
if let Ok(Some(user)) = auth_provider
.validate_app_token(user_id, password)
.instrument(info_span!("validate_user_token"))
.await
{
req.extensions_mut().insert(user);
}
if let Some(auth) = auth_header {
let user_id = auth.username();
let password = auth.password();
if let Ok(Some(user)) = ap
.validate_app_token(user_id, password)
.instrument(info_span!("validate_user_token"))
.await
{
request.extensions_mut().insert(user);
}
}
// Extract user from session cookie
if let Ok(session) = Session::extract(req.request()).await {
match session.get::<String>("user") {
Ok(Some(user_id)) => match auth_provider.get_principal(&user_id).await {
Ok(Some(user)) => {
req.extensions_mut().insert(user);
}
Ok(None) => {}
Err(err) => {
dbg!(err);
}
},
Ok(None) => {}
Err(err) => {
dbg!(err);
}
};
}
service.call(req).await
let response = inner.call(request).await?;
Ok(response)
})
}
}