-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathauth_middleware.rs
84 lines (74 loc) · 2.45 KB
/
auth_middleware.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use actix_session::SessionExt;
use actix_web::dev::forward_ready;
use actix_web::dev::Service;
use actix_web::dev::ServiceRequest;
use actix_web::dev::ServiceResponse;
use actix_web::dev::Transform;
use actix_web::Error;
use actix_web::HttpMessage;
use std::future::ready;
use std::future::Ready;
use std::rc::Rc;
use crate::AuthContext;
use crate::RequestAuth;
/// The MandatoryIdentityMiddleware does not directly process requests.
/// When actix starts, new_transform is called once per worker to create
/// MandatoryIdentityService instances.
#[derive(Clone)]
pub struct AuthMiddleware {
ctx: Rc<AuthContext>,
}
impl AuthMiddleware {
pub fn new(ctx: Rc<AuthContext>) -> Self {
AuthMiddleware { ctx }
}
}
impl<S, B> Transform<S, ServiceRequest> for AuthMiddleware
where
// type of the next service
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
S::Future: 'static,
// type of the body
B: 'static,
{
type Response = ServiceResponse<B>;
type Error = S::Error;
type InitError = ();
type Transform = AuthService<S>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
// when actix starts workers, new services are created per worker.
// this function wraps a service into the middleware
fn new_transform(&self, service: S) -> Self::Future {
ready(Ok(AuthService::new(service, self.ctx.clone())))
}
}
// The middleware service processes and forwards requests to a backend service
pub struct AuthService<S> {
// The backend service is behind an Rc so the async move closure can keep a reference
backend_service: Rc<S>,
ctx: Rc<AuthContext>,
}
impl<S> AuthService<S> {
fn new(service: S, ctx: Rc<AuthContext>) -> AuthService<S> {
AuthService {
backend_service: Rc::new(service),
ctx,
}
}
}
impl<S, B> Service<ServiceRequest> for AuthService<S>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
{
type Response = S::Response;
type Error = S::Error;
type Future = S::Future;
forward_ready!(backend_service);
fn call(&self, req: ServiceRequest) -> Self::Future {
let backend_service = Rc::clone(&self.backend_service);
let status = self.ctx.get_auth_status(req.request(), req.get_session());
req.extensions_mut()
.insert(RequestAuth::new(self.ctx.clone(), status));
backend_service.call(req)
}
}