telegram_authorizer/
layer.rs

1use 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}