torrust_tracker_configuration/v2_0_0/
tracker_api.rs

1use std::collections::HashMap;
2use std::net::{IpAddr, Ipv4Addr, SocketAddr};
3
4use serde::{Deserialize, Serialize};
5use serde_with::serde_as;
6
7use crate::TslConfig;
8
9pub type AccessTokens = HashMap<String, String>;
10
11/// Configuration for the HTTP API.
12#[serde_as]
13#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
14pub struct HttpApi {
15    /// The address the tracker will bind to.
16    /// The format is `ip:port`, for example `0.0.0.0:6969`. If you want to
17    /// listen to all interfaces, use `0.0.0.0`. If you want the operating
18    /// system to choose a random port, use port `0`.
19    #[serde(default = "HttpApi::default_bind_address")]
20    pub bind_address: SocketAddr,
21
22    /// TSL config. Only used if `ssl_enabled` is true.
23    #[serde(default = "HttpApi::default_tsl_config")]
24    pub tsl_config: Option<TslConfig>,
25
26    /// Access tokens for the HTTP API. The key is a label identifying the
27    /// token and the value is the token itself. The token is used to
28    /// authenticate the user. All tokens are valid for all endpoints and have
29    /// all permissions.
30    #[serde(default = "HttpApi::default_access_tokens")]
31    pub access_tokens: AccessTokens,
32}
33
34impl Default for HttpApi {
35    fn default() -> Self {
36        Self {
37            bind_address: Self::default_bind_address(),
38            tsl_config: Self::default_tsl_config(),
39            access_tokens: Self::default_access_tokens(),
40        }
41    }
42}
43
44impl HttpApi {
45    fn default_bind_address() -> SocketAddr {
46        SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1212)
47    }
48
49    #[allow(clippy::unnecessary_wraps)]
50    fn default_tsl_config() -> Option<TslConfig> {
51        None
52    }
53
54    fn default_access_tokens() -> AccessTokens {
55        [].iter().cloned().collect()
56    }
57
58    pub fn add_token(&mut self, key: &str, token: &str) {
59        self.access_tokens.insert(key.to_string(), token.to_string());
60    }
61
62    pub fn mask_secrets(&mut self) {
63        for token in self.access_tokens.values_mut() {
64            *token = "***".to_string();
65        }
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use crate::v2_0_0::tracker_api::HttpApi;
72
73    #[test]
74    fn default_http_api_configuration_should_not_contains_any_token() {
75        let configuration = HttpApi::default();
76
77        assert_eq!(configuration.access_tokens.values().len(), 0);
78    }
79
80    #[test]
81    fn http_api_configuration_should_allow_adding_tokens() {
82        let mut configuration = HttpApi::default();
83
84        configuration.add_token("admin", "MyAccessToken");
85
86        assert!(configuration.access_tokens.values().any(|t| t == "MyAccessToken"));
87    }
88}