Skip to main content

android_sms_gateway/
config.rs

1use crate::BASE_URL;
2
3/// Configuration builder for creating a [`Client`](crate::Client).
4///
5/// Supports two authentication modes:
6/// - **Bearer token**: JWT authentication via [`with_token`](ClientConfig::with_token)
7/// - **Basic auth**: username/password via [`with_basic_auth`](ClientConfig::with_basic_auth)
8///
9/// ## Examples
10///
11/// ```no_run
12/// use android_sms_gateway::ClientConfig;
13///
14/// // JWT authentication
15/// let config = ClientConfig::new()
16///     .with_token("your-jwt-token");
17///
18/// // Basic authentication
19/// let config = ClientConfig::new()
20///     .with_basic_auth("username", "password");
21/// ```
22#[derive(Clone)]
23pub struct ClientConfig {
24    pub(crate) base_url: String,
25    pub(crate) token: Option<String>,
26    pub(crate) username: Option<String>,
27    pub(crate) password: Option<String>,
28    pub(crate) http_client: Option<reqwest::Client>,
29}
30
31impl Default for ClientConfig {
32    fn default() -> Self {
33        Self {
34            base_url: BASE_URL.to_string(),
35            token: None,
36            username: None,
37            password: None,
38            http_client: None,
39        }
40    }
41}
42
43impl ClientConfig {
44    /// Creates a new configuration with default values.
45    ///
46    /// The default base URL is `https://api.sms-gate.app/3rdparty/v1`.
47    pub fn new() -> Self {
48        Self::default()
49    }
50
51    /// Sets a custom base URL for the API.
52    ///
53    /// Useful for private server deployments.
54    pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
55        self.base_url = base_url.into();
56        self
57    }
58
59    /// Configures JWT bearer token authentication.
60    pub fn with_token(mut self, token: impl Into<String>) -> Self {
61        self.token = Some(token.into());
62        self
63    }
64
65    /// Configures HTTP Basic authentication.
66    pub fn with_basic_auth(
67        mut self,
68        username: impl Into<String>,
69        password: impl Into<String>,
70    ) -> Self {
71        self.username = Some(username.into());
72        self.password = Some(password.into());
73        self
74    }
75
76    /// Provides a custom [`reqwest::Client`] for advanced HTTP configuration.
77    ///
78    /// By default, a client with default settings is used.
79    pub fn with_http_client(mut self, client: reqwest::Client) -> Self {
80        self.http_client = Some(client);
81        self
82    }
83
84    /// Validates that authentication credentials are configured.
85    ///
86    /// Returns an error if neither a token nor username/password is set.
87    pub fn validate(&self) -> Result<(), crate::Error> {
88        match (&self.username, &self.password, &self.token) {
89            (None, None, None) => Err(crate::Error::InvalidConfig(
90                "missing auth credentials".to_string(),
91            )),
92            (Some(_), None, None) | (Some(_), None, Some(_)) => Err(crate::Error::InvalidConfig(
93                "password is required when username is set".to_string(),
94            )),
95            (None, Some(_), None) | (None, Some(_), Some(_)) => Err(crate::Error::InvalidConfig(
96                "username is required when password is set".to_string(),
97            )),
98            _ => Ok(()),
99        }
100    }
101}