Skip to main content

pib_client/
authenticated_client.rs

1// SPDX-FileCopyrightText: Politik im Blick developers
2// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2
5
6use bytes::Bytes;
7use http::{HeaderValue, Method, Request, Response, header::AUTHORIZATION};
8use http_request_derive::{Error, HttpRequest};
9use url::Url;
10
11use crate::Authorization;
12
13/// A client authenticated to the OIDC provider.
14#[derive(Debug)]
15pub struct AuthenticatedClient<C, A> {
16    inner: C,
17    authorization: A,
18}
19
20impl<C, A> AuthenticatedClient<C, A> {
21    /// Create a new [AuthenticatedClient] with a valid authorization.
22    pub fn new(inner: C, authorization: A) -> Self {
23        Self {
24            inner,
25            authorization,
26        }
27    }
28}
29
30#[async_trait::async_trait(?Send)]
31impl<C: http_request_derive_client::Client, A: Authorization + Sync>
32    http_request_derive_client::Client for AuthenticatedClient<C, A>
33{
34    /// An error that can be returned during request execution by the [`AuthenticatedClient`].
35    type ClientError = C::ClientError;
36
37    /// Execute a [`http_request_derive::HttpRequest`], and read the typed response.
38    async fn execute<R: HttpRequest + Send>(
39        &self,
40        request: R,
41    ) -> Result<R::Response, Self::ClientError> {
42        let bearer_token = self.authorization.get_access_token().await.unwrap();
43
44        let request = AuthenticatedRequest {
45            request,
46            bearer_token,
47        };
48        self.inner.execute(request).await
49    }
50}
51
52struct AuthenticatedRequest<R> {
53    request: R,
54    bearer_token: String,
55}
56
57impl<R: HttpRequest> HttpRequest for AuthenticatedRequest<R> {
58    type Response = R::Response;
59    type Query = R::Query;
60    type Body = R::Body;
61
62    const METHOD: Method = R::METHOD;
63
64    fn path(&self) -> String {
65        self.request.path()
66    }
67
68    fn query(&self) -> Option<&Self::Query> {
69        self.request.query()
70    }
71
72    fn body(&self) -> Option<&Self::Body> {
73        self.request.body()
74    }
75
76    fn to_http_request(&self, base_url: &Url) -> Result<Request<Vec<u8>>, Error> {
77        let mut request = self.request.to_http_request(base_url)?;
78        _ = request.headers_mut().insert(
79            AUTHORIZATION,
80            HeaderValue::from_str(&format!("Bearer {}", self.bearer_token)).unwrap(),
81        );
82        Ok(request)
83    }
84
85    fn read_response(response: Response<Bytes>) -> Result<Self::Response, Error> {
86        R::read_response(response)
87    }
88}