Skip to main content

flowsurface_data/config/
proxy.rs

1use exchange::proxy::{Proxy, ProxyAuth};
2
3const KEYCHAIN_SERVICE: &str = "flowsurface.proxy";
4
5fn entry_for(proxy: &Proxy) -> Result<keyring::Entry, keyring::Error> {
6    let key = proxy.to_url_string_no_auth();
7    keyring::Entry::new(KEYCHAIN_SERVICE, &key)
8}
9
10pub fn load_proxy_auth(proxy: &Proxy) -> Option<ProxyAuth> {
11    let key = proxy.to_url_string_no_auth();
12
13    let entry = match entry_for(proxy) {
14        Ok(e) => e,
15        Err(err) => {
16            log::warn!(
17                "Keychain entry init failed for service={KEYCHAIN_SERVICE} key={key}: {err}"
18            );
19            return None;
20        }
21    };
22
23    let secret = match entry.get_password() {
24        Ok(s) => s,
25        Err(err) => {
26            log::info!("No proxy auth in keychain for service={KEYCHAIN_SERVICE} key={key}: {err}");
27            return None;
28        }
29    };
30
31    match serde_json::from_str::<ProxyAuth>(&secret) {
32        Ok(auth) => Some(auth),
33        Err(err) => {
34            log::warn!(
35                "Proxy auth in keychain is invalid JSON for service={KEYCHAIN_SERVICE} key={key}: {err}"
36            );
37            None
38        }
39    }
40}
41
42pub fn save_proxy_auth(proxy: &Proxy) {
43    let key = proxy.to_url_string_no_auth();
44
45    let Some(auth) = &proxy.auth else {
46        log::info!("Not saving proxy auth: auth is None (service={KEYCHAIN_SERVICE} key={key})");
47        return;
48    };
49
50    let entry = match entry_for(proxy) {
51        Ok(e) => e,
52        Err(err) => {
53            log::warn!(
54                "Keychain entry init failed for service={KEYCHAIN_SERVICE} key={key}: {err}"
55            );
56            return;
57        }
58    };
59
60    let secret = match serde_json::to_string(auth) {
61        Ok(s) => s,
62        Err(err) => {
63            log::warn!(
64                "Failed to serialize proxy auth for service={KEYCHAIN_SERVICE} key={key}: {err}"
65            );
66            return;
67        }
68    };
69
70    match entry.set_password(&secret) {
71        Ok(()) => {
72            log::info!("Stored proxy auth in keychain (service={KEYCHAIN_SERVICE} key={key})")
73        }
74        Err(err) => {
75            log::warn!(
76                "Failed to store proxy auth in keychain (service={KEYCHAIN_SERVICE} key={key}): {err}"
77            );
78            return;
79        }
80    }
81
82    match entry.get_password() {
83        Ok(roundtrip) => {
84            if roundtrip == secret {
85                log::info!("Keychain roundtrip OK (service={KEYCHAIN_SERVICE} key={key})");
86            } else {
87                log::warn!("Keychain roundtrip MISMATCH (service={KEYCHAIN_SERVICE} key={key})");
88            }
89        }
90        Err(err) => log::warn!(
91            "Keychain roundtrip read FAILED (service={KEYCHAIN_SERVICE} key={key}): {err}"
92        ),
93    }
94}