bitwarden_managed_settings/
managed_settings_client.rs1use std::sync::{Arc, RwLock};
2
3use bitwarden_managed_settings_types::ManagementProfile;
4
5#[derive(Clone)]
10pub struct ManagedSettingsClient {
11 profile: Arc<RwLock<Option<ManagementProfile>>>,
12}
13
14impl Default for ManagedSettingsClient {
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl ManagedSettingsClient {
21 pub fn new() -> Self {
23 Self {
24 profile: Arc::new(RwLock::new(None)),
25 }
26 }
27
28 pub fn cell(&self) -> Arc<RwLock<Option<ManagementProfile>>> {
31 self.profile.clone()
32 }
33
34 pub fn current_profile(&self) -> Option<ManagementProfile> {
36 self.profile
37 .read()
38 .expect("managed-settings cell poisoned")
39 .clone()
40 }
41
42 pub fn update_profile(&self, profile: Option<ManagementProfile>) {
44 *self
45 .profile
46 .write()
47 .expect("managed-settings cell poisoned") = profile;
48 }
49
50 pub fn is_managed(&self, key: String) -> bool {
52 self.profile
53 .read()
54 .expect("managed-settings cell poisoned")
55 .as_ref()
56 .is_some_and(|p| p.is_managed(&key))
57 }
58
59 pub fn get(&self, key: String) -> Option<String> {
61 self.profile
62 .read()
63 .expect("managed-settings cell poisoned")
64 .as_ref()
65 .and_then(|p| p.get(&key))
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use std::collections::HashMap;
72
73 use super::*;
74
75 fn profile_with(key: &str, json_value: &str) -> ManagementProfile {
76 ManagementProfile {
77 version: 1,
78 updated_at: 1_750_000_000,
79 settings: HashMap::from([(key.to_string(), json_value.to_string())]),
80 }
81 }
82
83 #[test]
84 fn a_new_client_manages_nothing() {
85 let client = ManagedSettingsClient::new();
86
87 assert_eq!(client.get("environment.base".to_string()), None);
88 assert!(!client.is_managed("environment.base".to_string()));
89 assert_eq!(client.current_profile(), None);
90 }
91
92 #[test]
93 fn get_reflects_an_updated_profile() {
94 let client = ManagedSettingsClient::new();
95 let profile = profile_with("environment.base", "\"https://vault.example.com\"");
96
97 client.update_profile(Some(profile.clone()));
98
99 assert_eq!(
100 client.get("environment.base".to_string()),
101 Some("\"https://vault.example.com\"".to_string())
102 );
103 assert!(client.is_managed("environment.base".to_string()));
104 assert_eq!(client.current_profile(), Some(profile));
105 }
106
107 #[test]
108 fn updating_with_none_clears_the_profile() {
109 let client = ManagedSettingsClient::new();
110 client.update_profile(Some(profile_with("environment.base", "\"https://a\"")));
111
112 client.update_profile(None);
113
114 assert_eq!(client.get("environment.base".to_string()), None);
115 assert!(!client.is_managed("environment.base".to_string()));
116 assert_eq!(client.current_profile(), None);
117 }
118
119 #[test]
120 fn a_clone_observes_an_update_made_on_the_original() {
121 let client = ManagedSettingsClient::new();
122 let clone = client.clone();
123 let profile = profile_with("environment.base", "\"https://vault.example.com\"");
124
125 client.update_profile(Some(profile.clone()));
126
127 assert_eq!(
128 clone.get("environment.base".to_string()),
129 Some("\"https://vault.example.com\"".to_string())
130 );
131 assert_eq!(clone.current_profile(), Some(profile));
132 }
133
134 #[test]
135 fn the_shared_cell_observes_an_update_made_through_the_handle() {
136 let client = ManagedSettingsClient::new();
137 let cell = client.cell();
138 let profile = profile_with("environment.base", "\"https://vault.example.com\"");
139
140 client.update_profile(Some(profile.clone()));
141
142 assert_eq!(
143 *cell.read().expect("managed-settings cell poisoned"),
144 Some(profile)
145 );
146 }
147}