Skip to main content

unifly_api/
config.rs

1// ── Runtime connection configuration ──
2//
3// These types describe *how* to connect to a UniFi controller.
4// They carry credential data and connection tuning, but never touch disk.
5// The CLI/TUI constructs a `ControllerConfig` and hands it in.
6
7use secrecy::SecretString;
8use url::Url;
9
10/// How to authenticate with a controller.
11///
12/// Named `AuthCredentials` (not `AuthMethod`) to avoid collision with
13/// `unifly_api::AuthStrategy` which is a zero-data marker enum.
14/// This type carries the actual credential data.
15#[derive(Debug, Clone)]
16pub enum AuthCredentials {
17    /// Integration API key (preferred).
18    ApiKey(SecretString),
19    /// Legacy cookie-based auth.
20    Credentials {
21        username: String,
22        password: SecretString,
23    },
24    /// Hybrid: API key for Integration API + credentials for Legacy API.
25    ///
26    /// Gives full access to both APIs in a single session — Integration API
27    /// for CRUD and reads, Legacy API for stats, events, alarms, and admin.
28    Hybrid {
29        api_key: SecretString,
30        username: String,
31        password: SecretString,
32    },
33    /// Cloud connector via api.ui.com.
34    Cloud {
35        api_key: SecretString,
36        host_id: String,
37    },
38}
39
40/// TLS verification strategy.
41#[derive(Debug, Clone, Default)]
42pub enum TlsVerification {
43    /// System CA store (strict).
44    SystemDefaults,
45    /// Custom CA certificate file.
46    CustomCa(std::path::PathBuf),
47    /// Skip verification (self-signed certs). Default for local controllers.
48    #[default]
49    DangerAcceptInvalid,
50}
51
52impl PartialEq for TlsVerification {
53    fn eq(&self, other: &Self) -> bool {
54        match (self, other) {
55            (Self::CustomCa(a), Self::CustomCa(b)) => a == b,
56            (Self::SystemDefaults, Self::SystemDefaults)
57            | (Self::DangerAcceptInvalid, Self::DangerAcceptInvalid) => true,
58            _ => false,
59        }
60    }
61}
62
63impl Eq for TlsVerification {}
64
65/// Configuration for connecting to a single controller.
66///
67/// Built by CLI/TUI, passed to `Controller` -- core never reads config files.
68#[derive(Debug, Clone)]
69pub struct ControllerConfig {
70    /// Controller URL (e.g., `https://192.168.1.1`).
71    pub url: Url,
72    /// Authentication method and credentials.
73    pub auth: AuthCredentials,
74    /// Site to operate on (defaults to "default").
75    pub site: String,
76    /// TLS verification strategy.
77    pub tls: TlsVerification,
78    /// Request timeout.
79    pub timeout: std::time::Duration,
80    /// How often to perform a full refresh (seconds). 0 = never.
81    pub refresh_interval_secs: u64,
82    /// Enable WebSocket event stream.
83    pub websocket_enabled: bool,
84    /// Polling interval when WebSocket is unavailable (seconds).
85    pub polling_interval_secs: u64,
86}
87
88impl Default for ControllerConfig {
89    fn default() -> Self {
90        Self {
91            url: "https://192.168.1.1:8443"
92                .parse()
93                .expect("default controller URL is valid"),
94            auth: AuthCredentials::Credentials {
95                username: "admin".into(),
96                password: SecretString::from(String::new()),
97            },
98            site: "default".into(),
99            tls: TlsVerification::default(),
100            timeout: std::time::Duration::from_secs(30),
101            refresh_interval_secs: 300,
102            websocket_enabled: true,
103            polling_interval_secs: 10,
104        }
105    }
106}