Skip to main content

unifly_api/controller/session_queries/
settings.rs

1use crate::controller::Controller;
2use crate::controller::support::require_session;
3use crate::core_error::CoreError;
4use crate::model::VpnSetting;
5
6use super::common::redact_sensitive_value;
7
8const VPN_SETTING_KEYS: &[&str] = &[
9    "teleport",
10    "magic_site_to_site_vpn",
11    "openvpn",
12    "peer_to_peer",
13];
14
15impl Controller {
16    pub async fn list_vpn_settings(&self) -> Result<Vec<VpnSetting>, CoreError> {
17        let guard = self.inner.session_client.lock().await;
18        let session = require_session(guard.as_ref())?;
19        let raw = session.get_site_settings().await?;
20        let mut settings = raw
21            .iter()
22            .filter_map(vpn_setting_from_raw)
23            .collect::<Vec<_>>();
24        settings.sort_by(|left, right| left.key.cmp(&right.key));
25        Ok(settings)
26    }
27
28    pub async fn get_vpn_setting(&self, key: &str) -> Result<VpnSetting, CoreError> {
29        self.list_vpn_settings()
30            .await?
31            .into_iter()
32            .find(|setting| setting.key == key)
33            .ok_or_else(|| CoreError::NotFound {
34                entity_type: "vpn setting".into(),
35                identifier: key.into(),
36            })
37    }
38
39    pub async fn update_vpn_setting(
40        &self,
41        key: &str,
42        body: &serde_json::Value,
43    ) -> Result<VpnSetting, CoreError> {
44        if !VPN_SETTING_KEYS.contains(&key) {
45            return Err(CoreError::NotFound {
46                entity_type: "vpn setting".into(),
47                identifier: key.into(),
48            });
49        }
50
51        let guard = self.inner.session_client.lock().await;
52        let session = require_session(guard.as_ref())?;
53        session.set_site_setting(key, body).await?;
54        drop(guard);
55
56        self.get_vpn_setting(key).await
57    }
58
59    pub async fn get_all_site_settings(&self) -> Result<Vec<serde_json::Value>, CoreError> {
60        let guard = self.inner.session_client.lock().await;
61        let session = require_session(guard.as_ref())?;
62        Ok(session.get_site_settings().await?)
63    }
64
65    pub async fn get_site_setting(&self, key: &str) -> Result<serde_json::Value, CoreError> {
66        self.get_all_site_settings()
67            .await?
68            .into_iter()
69            .find(|s| s.get("key").and_then(|v| v.as_str()) == Some(key))
70            .ok_or_else(|| CoreError::NotFound {
71                entity_type: "setting".into(),
72                identifier: key.into(),
73            })
74    }
75
76    pub async fn update_site_setting(
77        &self,
78        key: &str,
79        body: &serde_json::Value,
80    ) -> Result<(), CoreError> {
81        let guard = self.inner.session_client.lock().await;
82        let session = require_session(guard.as_ref())?;
83        session.set_site_setting(key, body).await?;
84        Ok(())
85    }
86}
87
88fn vpn_setting_from_raw(raw: &serde_json::Value) -> Option<VpnSetting> {
89    let object = raw.as_object()?;
90    let key = object.get("key")?.as_str()?;
91    if !VPN_SETTING_KEYS.contains(&key) {
92        return None;
93    }
94
95    let mut fields = object.clone();
96    fields.remove("_id");
97    fields.remove("key");
98    fields.remove("site_id");
99    let fields = redact_sensitive_value(&serde_json::Value::Object(fields))
100        .as_object()
101        .cloned()
102        .unwrap_or_default();
103
104    Some(VpnSetting {
105        key: key.to_owned(),
106        enabled: fields.get("enabled").and_then(serde_json::Value::as_bool),
107        fields,
108    })
109}
110
111#[cfg(test)]
112mod tests {
113    use super::vpn_setting_from_raw;
114
115    #[test]
116    fn vpn_setting_from_raw_filters_to_known_keys() {
117        let raw = serde_json::json!({
118            "key": "teleport",
119            "enabled": true,
120            "_id": "abc123",
121            "site_id": "default",
122        });
123        let setting = vpn_setting_from_raw(&raw).expect("teleport should be recognized");
124
125        assert_eq!(setting.key, "teleport");
126        assert_eq!(setting.enabled, Some(true));
127        assert!(!setting.fields.contains_key("_id"));
128        assert!(!setting.fields.contains_key("site_id"));
129    }
130}