strm_privacy_driver/
strm_privacy_client.rs

1use reqwest::{Client, Error, StatusCode};
2
3use crate::auth::auth_service::AuthService;
4use crate::client::sender_service::SenderService;
5use crate::strm_privacy_value::StrmPrivacyValue;
6
7pub const AUTH_URL: &str = "https://accounts.strmprivacy.io/auth/realms/streams/protocol/openid-connect/token";
8pub const API_URL: &str = "https://events.strmprivacy.io/event";
9
10/// Container type to easily return backend responses from `send_event` function
11pub type StrmPrivacyResponse = (StrmStatusCode, String);
12
13const MAX_RETRIES: usize = 3;
14
15/// type alias for match status codes after `send_events` function
16pub type StrmStatusCode = StatusCode;
17
18pub struct StrmPrivacyClient {
19    sender_service: SenderService,
20    auth_service: AuthService,
21    client: Client,
22}
23
24impl StrmPrivacyClient {
25    /// Creates a new `StrmPrivacyClient` with custom endpoints
26    pub async fn new(
27        client_id: String,
28        client_secret: String,
29        auth_url: &'static str,
30        api_url: &'static str,
31    ) -> Result<Self, Error> {
32        let client = Client::new();
33        let mut auth_service = AuthService::new(client_id, client_secret, auth_url);
34        let sender_service = SenderService::new(api_url);
35        auth_service.authenticate(&client).await?;
36        Ok(Self {
37            sender_service,
38            auth_service,
39            client,
40        })
41    }
42
43    /// Creates a new `StrmPrivacyClient` with default endpoints
44    pub async fn default(
45        client_id: String,
46        client_secret: String,
47    ) -> Result<Self, Error> {
48        let client = Client::new();
49        let mut auth_service = AuthService::new(client_id, client_secret, AUTH_URL);
50        let sender_service = SenderService::new(API_URL);
51        auth_service.authenticate(&client).await?;
52        Ok(Self {
53            sender_service,
54            auth_service,
55            client,
56        })
57    }
58
59    /// Send a `StrmPrivacyValue` to the backend en return the corresponding response
60    pub async fn send_event<T>(&mut self, event: T) -> Result<StrmPrivacyResponse, Error>
61    where
62        T: StrmPrivacyValue,
63    {
64        let mut response: StrmPrivacyResponse = (StrmStatusCode::NO_CONTENT, "".to_string());
65        for i in 0..MAX_RETRIES {
66            let resp = self
67                .sender_service
68                .send_event(&self.client, &self.auth_service.token, event.clone())
69                .await?;
70
71            let status_code = resp.status();
72            let message = resp.text().await?;
73            response = (status_code, message);
74
75            // refresh the token otherwise break out of the loop
76            match status_code {
77                // for the last refresh possibility it doesn't make sense
78                // to try to refresh again as we can't catch it to redo the
79                // request
80                StrmStatusCode::UNAUTHORIZED if i + 1 < MAX_RETRIES => {
81                    self.refresh().await?;
82                }
83                _ => {
84                    break;
85                }
86            }
87        }
88
89        Ok(response)
90    }
91
92    async fn refresh(&mut self) -> Result<(), Error> {
93        self.auth_service.refresh(&self.client).await
94    }
95}