remoteit_api/
credentials.rs

1//! This module is related to loading remote.it credentials from the user's home directory.
2//! This is of course not the most secure way to store credentials, but it is the most convenient and recommended by remote.it.
3//! If you store your credentials in a different way, you can pass them to the functions in this module directly instead of using this module to load them.
4
5use base64::prelude::BASE64_STANDARD;
6use base64::Engine;
7use bon::bon;
8
9/// Credentials for the remote.it API.
10/// Remote.it credentials consist of an access key ID and a base64 encoded secret access key.
11///
12/// # Example
13/// You can directly create a new [`Credentials`] struct using the builder pattern:
14/// ```
15/// # use remoteit_api::Credentials;
16/// let credentials = Credentials::builder()
17///     .r3_access_key_id("foo")
18///     .r3_secret_access_key("YmFy")
19///     .build();
20/// ```
21/// If you enable the `credentials_loader` feature, you can also load the credentials from the default, or a custom file:
22/// ```
23/// # use remoteit_api::Credentials;
24/// let creds_from_default_loc = Credentials::load_from_disk().call().unwrap();
25/// let creds_from_custom_loc = Credentials::load_from_disk().custom_credentials_path(".env.remoteit").call().unwrap();
26/// ```
27#[derive(
28    Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash, serde::Deserialize, serde::Serialize,
29)]
30pub struct Credentials {
31    pub(crate) r3_access_key_id: String,
32    pub(crate) r3_secret_access_key: String,
33    #[serde(skip)] // Don't want to serialize this one
34    pub(crate) key: Vec<u8>,
35}
36
37#[bon]
38impl Credentials {
39    /// Validated the given secret access key and creates a new [`Credentials`] struct.
40    ///
41    /// # Errors
42    /// - [`base64::DecodeError`] if the secret access key is not base64 encoded.
43    ///
44    /// # Example
45    /// ```
46    /// # use remoteit_api::Credentials;
47    /// let credentials = Credentials::builder()
48    ///     .r3_access_key_id("foo")
49    ///     .r3_secret_access_key("YmFy")
50    ///     .build();
51    /// ```
52    #[builder]
53    pub fn new(
54        r3_access_key_id: String,
55        r3_secret_access_key: String,
56    ) -> Result<Self, base64::DecodeError> {
57        let key = BASE64_STANDARD.decode(&r3_secret_access_key)?;
58        Ok(Self {
59            r3_access_key_id,
60            r3_secret_access_key,
61            key,
62        })
63    }
64
65    /// # Returns
66    /// The base64 decoded secret access key.
67    #[must_use]
68    pub fn key(&self) -> &[u8] {
69        &self.key
70    }
71
72    /// # Returns
73    /// A reference to the r3_access_key_id
74    pub fn access_key_id(&self) -> &str {
75        &self.r3_access_key_id
76    }
77
78    /// # Returns
79    /// The base64 encoded r3_secret_access_key
80    pub fn secret_access_key(&self) -> &str {
81        &self.r3_secret_access_key
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_credentials_builder() {
91        let credentials = Credentials::builder()
92            .r3_access_key_id("foo")
93            .r3_secret_access_key("YmFy")
94            .build()
95            .unwrap();
96
97        assert_eq!(credentials.r3_access_key_id, "foo");
98        assert_eq!(credentials.r3_secret_access_key, "YmFy");
99    }
100}