drogue_bazaar/actix/auth/authorization/
middleware.rs1use super::{AuthZ, Context};
2use crate::auth::{UserInformation, ANONYMOUS};
3use actix_http::body::EitherBody;
4use actix_service::{Service, Transform};
5use actix_web::{
6 dev::{ServiceRequest, ServiceResponse},
7 Error, HttpMessage,
8};
9use futures_util::future::{ok, LocalBoxFuture, Ready};
10use std::rc::Rc;
11
12pub struct AuthMiddleware<S> {
13 service: Rc<S>,
14 authorizer: AuthZ,
15}
16
17impl<S, B> Transform<S, ServiceRequest> for AuthZ
22where
23 S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
24 S::Future: 'static,
25 B: 'static,
26{
27 type Response = ServiceResponse<EitherBody<B>>;
28 type Error = S::Error;
29 type Transform = AuthMiddleware<S>;
30 type InitError = ();
31 type Future = Ready<Result<Self::Transform, Self::InitError>>;
32
33 fn new_transform(&self, service: S) -> Self::Future {
34 ok(AuthMiddleware {
35 service: Rc::new(service),
36 authorizer: self.clone(),
37 })
38 }
39}
40
41impl<S, B> Service<ServiceRequest> for AuthMiddleware<S>
43where
44 S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
45 S::Future: 'static,
46 B: 'static,
47{
48 type Response = ServiceResponse<EitherBody<B>>;
49 type Error = Error;
50 type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
51
52 actix_service::forward_ready!(service);
53
54 fn call(&self, req: ServiceRequest) -> Self::Future {
55 let srv = Rc::clone(&self.service);
56 let auth = self.authorizer.clone();
57
58 Box::pin(async move {
59 let result = {
60 let ext = req.extensions();
62 let identity = ext.get::<UserInformation>().unwrap_or(&ANONYMOUS);
63
64 let context = Context {
65 identity,
66 request: &req,
67 };
68
69 auth.authorize(context).await
70 };
71
72 match result {
73 Ok(()) => {
74 srv.call(req).await.map(|res| res.map_into_left_body())
76 }
77 Err(err) => {
78 log::debug!("Authorization error: {err}");
79 Ok(req.error_response(err).map_into_right_body())
80 }
81 }
82 })
83 }
84}