actix_permissions/
service.rs1use std::convert::Infallible;
3use std::future::Future;
4use std::marker::PhantomData;
5use std::pin::Pin;
6use std::sync::atomic::{AtomicBool, Ordering};
7use std::sync::Arc;
8use std::task::{Context, Poll};
9
10use actix_web::dev::*;
11use actix_web::web::{Buf, Bytes, BytesMut};
12use actix_web::*;
13use futures_util::stream::StreamExt as _;
14
15use crate::permission::Permission;
16
17pub struct PermissionService<F, Args, P1, P1Args>
29where
30 F: Handler<Args>,
31 Args: FromRequest,
32 F::Output: Responder,
33 P1: Permission<P1Args>,
34 P1Args: FromRequest,
35{
36 handler: F,
37 pd_handler: PhantomData<Args>,
38 deny_handler: fn(HttpRequest) -> HttpResponse,
39 permission: P1,
40 pd_permission: PhantomData<P1Args>,
41 ready: Arc<AtomicBool>,
42}
43
44impl<F, Args, P1, P1Args> PermissionService<F, Args, P1, P1Args>
45where
46 F: Handler<Args>,
47 Args: FromRequest,
48 P1: Permission<P1Args>,
49 P1Args: FromRequest,
50 F::Output: Responder,
51{
52 pub fn new(permission: P1, handler: F, deny_handler: fn(HttpRequest) -> HttpResponse) -> Self {
54 Self {
55 handler,
56 pd_handler: Default::default(),
57 deny_handler,
58 permission,
59 pd_permission: Default::default(),
60 ready: Arc::new(AtomicBool::new(false)),
61 }
62 }
63}
64
65pub fn get_payload(bytes: Bytes) -> Payload {
67 let mut repack_payload = actix_http::h1::Payload::create(true);
68 repack_payload.1.unread_data(bytes);
69 repack_payload.1.into()
70}
71
72impl<F, Args, P1, P1Args> Service<ServiceRequest> for PermissionService<F, Args, P1, P1Args>
73where
74 F: Handler<Args>,
75 Args: FromRequest,
76 P1: Permission<P1Args>,
77 P1Args: FromRequest,
78 F::Output: Responder,
79{
80 type Response = ServiceResponse;
81 type Error = Infallible;
82 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
83
84 fn poll_ready(&self, _: &mut Context<'_>) -> Poll<std::result::Result<(), Self::Error>> {
85 if self.ready.load(Ordering::Relaxed) {
86 Poll::Ready(Ok(()))
87 } else {
88 Poll::Pending
89 }
90 }
91
92 fn call(&self, args: ServiceRequest) -> Self::Future {
93 let handler = self.handler.clone();
94 let deny_handler = self.deny_handler;
95 let permission = self.permission.clone();
96 let ready = self.ready.clone();
97 Box::pin(async move {
98 let (req, mut payload) = args.into_parts();
99
100 let mut body = BytesMut::new();
103 while let Some(chunk) = payload.next().await {
104 body.extend_from_slice(chunk.unwrap().chunk())
105 }
106
107 let handler_body = body.clone();
108
109 let mut p1_payload = get_payload(body.freeze());
110
111 let service_response = match P1Args::from_request(&req, &mut p1_payload).await {
112 Err(err) => ServiceResponse::new(req, HttpResponse::from_error(err)),
113 Ok(data) => {
114 let permission_check_result = permission.call(req.clone(), data).await;
115 let mut handler_payload = get_payload(handler_body.freeze());
116 match permission_check_result {
117 Ok(true) => match Args::from_request(&req, &mut handler_payload).await {
118 Err(err) => ServiceResponse::new(req, HttpResponse::from_error(err)),
119 Ok(data) => {
120 let handler_response = handler
121 .call(data)
122 .await
123 .respond_to(&req)
124 .map_into_boxed_body();
125 ServiceResponse::new(req, handler_response)
126 }
127 },
128 Ok(false) => {
129 let response = deny_handler(req.clone());
130 ServiceResponse::new(req, response)
131 }
132 Err(err) => ServiceResponse::from_err(err, req),
133 }
134 }
135 };
136
137 ready.store(true, Ordering::Relaxed);
138 Ok(service_response)
139 })
140 }
141}