opentalk_client/
authenticated_client.rs

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