flowsurface_data/config/
proxy.rs1use 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}