monzo/client/inner/
refreshable.rs

1use crate::{
2    client,
3    client::{Client, Inner},
4    endpoints::{auth, Endpoint},
5    Result,
6};
7
8/// A full-featured Monzo API client.
9///
10/// This client can refresh it's own access token if it expires
11/// See the individual methods for descriptions of the API endpoints.
12#[derive(Debug, Clone)]
13#[must_use]
14pub struct Refreshable {
15    quick_client: client::inner::Quick,
16
17    client_id: String,
18    client_secret: String,
19    refresh_token: String,
20}
21
22impl Client<Refreshable> {
23    pub(crate) fn from_quick_client(
24        quick_client: client::inner::Quick,
25        client_id: impl Into<String>,
26        client_secret: impl Into<String>,
27        refresh_token: impl Into<String>,
28    ) -> Self {
29        let inner_client = Refreshable {
30            quick_client,
31            client_id: client_id.into(),
32            client_secret: client_secret.into(),
33            refresh_token: refresh_token.into(),
34        };
35
36        Self { inner_client }
37    }
38
39    /// Get a reference to the client id
40    #[must_use]
41    pub const fn client_id(&self) -> &String {
42        &self.inner_client.client_id
43    }
44
45    /// Get a reference to the client secret
46    #[must_use]
47    pub const fn client_secret(&self) -> &String {
48        &self.inner_client.client_secret
49    }
50
51    /// Get a reference to the refresh token
52    #[must_use]
53    pub const fn refresh_token(&self) -> &String {
54        &self.inner_client.refresh_token
55    }
56
57    /// Hit the Monzo auth endpoint and request new access and refresh tokens
58    async fn get_refresh_tokens(&self) -> Result<auth::RefreshResponse> {
59        self.inner_client
60            .handle_request(&auth::Refresh::new(
61                self.client_id(),
62                self.client_secret(),
63                self.refresh_token(),
64            ))
65            .await
66    }
67
68    /// Refresh the access and refresh tokens for this client
69    ///
70    /// Returns the time (in seconds) until the token expires
71    pub async fn refresh_auth(&mut self) -> Result<i64> {
72        let response = self.get_refresh_tokens().await?;
73        let expires_in = response.expires_in;
74
75        self.set_access_token(response.access_token);
76        self.inner_client.refresh_token = response.refresh_token;
77
78        Ok(expires_in)
79    }
80}
81
82impl client::Inner for Refreshable {
83    async fn execute<E>(&self, endpoint: &E) -> reqwest::Result<reqwest::Response>
84    where
85        E: Endpoint,
86    {
87        self.quick_client.execute(endpoint).await
88    }
89
90    fn access_token(&self) -> &String {
91        self.quick_client.access_token()
92    }
93
94    fn set_access_token(&mut self, access_token: String) {
95        self.quick_client.set_access_token(access_token);
96    }
97
98    fn url(&self) -> &str {
99        self.quick_client.url()
100    }
101}