telegram_authorizer/
layer.rs1use std::{
2 future::{ready, Future},
3 pin::Pin,
4 task::{Context, Poll},
5};
6
7use axum::{extract::Request, response::Response};
8use tower_layer::Layer;
9use tower_service::Service;
10
11use crate::{
12 authorizer::{Authorizer, User},
13 error::AuthError,
14 Embedded, External,
15};
16
17#[derive(Clone)]
18pub struct AuthorizationLayer<A: Authorizer> {
19 authorizer: A,
20}
21
22impl AuthorizationLayer<Embedded> {
23 pub fn new_embedded(bot_token: &str) -> Self {
24 Self {
25 authorizer: Embedded::new(bot_token),
26 }
27 }
28}
29
30impl AuthorizationLayer<External> {
31 pub fn new_external(bot_token: &str) -> Self {
32 Self {
33 authorizer: External::new(bot_token),
34 }
35 }
36}
37
38impl<S, A: Authorizer> Layer<S> for AuthorizationLayer<A> {
39 type Service = AuthorizationService<S, A>;
40
41 fn layer(&self, inner: S) -> Self::Service {
42 AuthorizationService {
43 inner,
44 authorizer: self.authorizer.clone(),
45 }
46 }
47}
48
49#[derive(Clone)]
50pub struct AuthorizationService<S, A: Authorizer> {
51 inner: S,
52 authorizer: A,
53}
54
55impl<S, A: Authorizer> AuthorizationService<S, A> {
56 fn authorize(&self, query_string: Option<&str>) -> Result<User, AuthError> {
57 self.authorizer.authorize(query_string)
58 }
59}
60
61impl<S, A: Authorizer> Service<Request> for AuthorizationService<S, A>
62where
63 S: Service<Request, Response = Response> + Send + 'static,
64 S::Response: From<AuthError> + Send,
65 S::Future: Send,
66 S::Error: Send,
67{
68 type Response = S::Response;
69 type Error = S::Error;
70 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, S::Error>> + Send>>;
71
72 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
73 self.inner.poll_ready(cx)
74 }
75
76 fn call(&mut self, mut req: Request) -> Self::Future {
77 let query_string = req.uri().query();
78 let user = self.authorize(query_string);
79 match user {
80 Ok(user) => {
81 req.extensions_mut().insert(user);
82 Box::pin(self.inner.call(req))
83 }
84 Err(e) => Box::pin(ready(Ok(e.into()))),
85 }
86 }
87}