users/
manager.rs

1use alloc::{
2    collections::{BTreeMap, BTreeSet},
3    string::{String, ToString},
4    vec::Vec,
5};
6use synchronization::{
7    blocking_mutex::raw::CriticalSectionRawMutex, once_lock::OnceLock, rwlock::RwLock,
8};
9
10use super::*;
11
12static MANAGER_INSTANCE: OnceLock<Manager> = OnceLock::new();
13
14pub fn initialize() -> &'static Manager {
15    MANAGER_INSTANCE.get_or_init(Manager::new)
16}
17
18pub fn get_instance() -> &'static Manager {
19    MANAGER_INSTANCE
20        .try_get()
21        .expect("User manager instance not initialized")
22}
23
24struct InternalUser {
25    pub name: String,
26    pub primary_group: GroupIdentifier,
27}
28
29struct InternalGroup {
30    pub name: String,
31    pub users: BTreeSet<UserIdentifier>,
32}
33
34struct InternalManager {
35    pub users: BTreeMap<UserIdentifier, InternalUser>,
36    pub groups: BTreeMap<GroupIdentifier, InternalGroup>,
37}
38
39pub struct Manager(RwLock<CriticalSectionRawMutex, InternalManager>);
40
41impl Manager {
42    fn new() -> Self {
43        let mut groups = BTreeMap::new();
44        groups.insert(
45            GroupIdentifier::ROOT,
46            InternalGroup {
47                name: "root".to_string(),
48                users: BTreeSet::new(),
49            },
50        );
51
52        let mut users = BTreeMap::new();
53        users.insert(
54            UserIdentifier::ROOT,
55            InternalUser {
56                name: "root".to_string(),
57                primary_group: GroupIdentifier::ROOT,
58            },
59        );
60
61        Self(RwLock::new(InternalManager { users, groups }))
62    }
63
64    pub async fn get_new_group_identifier(&self) -> Result<GroupIdentifier> {
65        let inner = self.0.read().await;
66
67        let mut identifier = GroupIdentifier::MINIMUM;
68
69        while inner.groups.contains_key(&identifier) {
70            identifier += 1;
71
72            if identifier == GroupIdentifier::MAXIMUM {
73                return Err(Error::TooManyGroups);
74            }
75        }
76
77        Ok(identifier)
78    }
79
80    pub async fn get_new_user_identifier(&self) -> Result<UserIdentifier> {
81        let inner = self.0.read().await;
82
83        let mut identifier = UserIdentifier::MINIMUM;
84
85        while inner.users.contains_key(&identifier) {
86            identifier += 1;
87
88            if identifier == UserIdentifier::MAXIMUM {
89                return Err(Error::TooManyUsers);
90            }
91        }
92
93        Ok(identifier)
94    }
95
96    pub async fn add_user(
97        &self,
98        identifier: UserIdentifier,
99        name: &str,
100        primary_group: GroupIdentifier,
101    ) -> Result<()> {
102        let mut inner = self.0.write().await;
103
104        // - Check if user identifier is unique
105        if inner.users.contains_key(&identifier) {
106            return Err(Error::DuplicateUserIdentifier);
107        }
108
109        // - Check if user name is unique
110        if inner.users.values().any(|user| user.name == name) {
111            return Err(Error::DuplicateUserName);
112        }
113
114        // - Add user to the users map
115        let user = InternalUser {
116            name: name.to_string(),
117            primary_group,
118        };
119
120        if inner.users.insert(identifier, user).is_some() {
121            return Err(Error::DuplicateUserIdentifier); // Shouldn't happen
122        }
123
124        // - Add user to the primary group
125        if !inner
126            .groups
127            .get_mut(&primary_group)
128            .ok_or(Error::InvalidGroupIdentifier)?
129            .users
130            .insert(identifier)
131        {
132            return Err(Error::DuplicateUserIdentifier); // Shouldn't happen
133        }
134
135        Ok(())
136    }
137
138    pub async fn add_group(
139        &self,
140        identifier: GroupIdentifier,
141        name: &str,
142        users: &[UserIdentifier],
143    ) -> Result<()> {
144        let mut inner = self.0.write().await;
145
146        // - Check if group identifier is unique
147        if inner.groups.contains_key(&identifier) {
148            return Err(Error::DuplicateGroupIdentifier);
149        }
150
151        // - Check if group name is unique
152        if inner.groups.values().any(|group| group.name == name) {
153            return Err(Error::DuplicateGroupName);
154        }
155
156        let group = InternalGroup {
157            name: name.to_string(),
158            users: BTreeSet::from_iter(users.iter().cloned()),
159        };
160
161        if inner.groups.insert(identifier, group).is_some() {
162            return Err(Error::DuplicateGroupIdentifier); // Shouldn't happen
163        }
164
165        Ok(())
166    }
167
168    pub fn is_root(identifier: UserIdentifier) -> bool {
169        UserIdentifier::ROOT == identifier
170    }
171
172    pub async fn is_in_group(
173        &self,
174        user_identifier: UserIdentifier,
175        group_identifier: GroupIdentifier,
176    ) -> bool {
177        let inner = self.0.read().await;
178
179        if let Some(group) = inner.groups.get(&group_identifier)
180            && group.users.contains(&user_identifier)
181        {
182            return true;
183        }
184
185        false
186    }
187
188    pub async fn get_user_groups(
189        &self,
190        identifier: UserIdentifier,
191    ) -> Result<BTreeSet<GroupIdentifier>> {
192        let inner = self.0.read().await;
193
194        let mut user_groups: BTreeSet<GroupIdentifier> = BTreeSet::new();
195
196        user_groups.extend(
197            inner
198                .groups
199                .iter()
200                .filter(|(_, group)| group.users.contains(&identifier))
201                .map(|(identifier, _)| *identifier),
202        );
203
204        Ok(user_groups)
205    }
206
207    pub async fn exists_group(&self, identifier: GroupIdentifier) -> Result<bool> {
208        Ok(self.0.read().await.groups.contains_key(&identifier))
209    }
210
211    pub async fn exists_user(&self, identifier: UserIdentifier) -> Result<bool> {
212        Ok(self.0.read().await.users.contains_key(&identifier))
213    }
214
215    pub async fn add_to_group(
216        &self,
217        user_identifier: UserIdentifier,
218        group_identifier: GroupIdentifier,
219    ) -> Result<()> {
220        if !self.exists_group(group_identifier).await? {
221            return Err(Error::InvalidGroupIdentifier);
222        }
223        let mut inner = self.0.write().await;
224        if !inner
225            .groups
226            .get_mut(&group_identifier)
227            .ok_or(Error::InvalidGroupIdentifier)?
228            .users
229            .insert(user_identifier)
230        {
231            return Err(Error::DuplicateGroupIdentifier);
232        }
233        Ok(())
234    }
235
236    pub async fn get_group_name(&self, identifier: GroupIdentifier) -> Result<String> {
237        Ok(self
238            .0
239            .read()
240            .await
241            .groups
242            .get(&identifier)
243            .ok_or(Error::InvalidGroupIdentifier)?
244            .name
245            .clone())
246    }
247
248    pub async fn get_user_identifier(&self, name: &str) -> Result<UserIdentifier> {
249        Ok(*self
250            .0
251            .read()
252            .await
253            .users
254            .iter()
255            .find(|(_, user)| user.name == name)
256            .ok_or(Error::InvalidUserIdentifier)?
257            .0)
258    }
259
260    pub async fn get_group_users(
261        &self,
262        identifier: GroupIdentifier,
263    ) -> Result<Vec<UserIdentifier>> {
264        Ok(self
265            .0
266            .read()
267            .await
268            .groups
269            .get(&identifier)
270            .ok_or(Error::InvalidGroupIdentifier)?
271            .users
272            .clone()
273            .into_iter()
274            .collect())
275    }
276
277    pub async fn get_user_name(&self, identifier: UserIdentifier) -> Result<String> {
278        Ok(self
279            .0
280            .read()
281            .await
282            .users
283            .get(&identifier)
284            .ok_or(Error::InvalidUserIdentifier)?
285            .name
286            .clone())
287    }
288
289    pub async fn get_user_primary_group(
290        &self,
291        identifier: UserIdentifier,
292    ) -> Result<GroupIdentifier> {
293        Ok(self
294            .0
295            .read()
296            .await
297            .users
298            .get(&identifier)
299            .ok_or(Error::InvalidUserIdentifier)?
300            .primary_group)
301    }
302
303    pub fn check_credentials(&self, _user_name: &str, _password: &str) -> bool {
304        true
305    }
306}
307
308#[cfg(test)]
309mod tests {
310    extern crate std;
311
312    use super::*;
313
314    use task::test;
315
316    #[test]
317    async fn create_user() {
318        let manager = Manager::new();
319        let user_name = "Alice";
320        let identifier = UserIdentifier::new(1000);
321        manager
322            .add_user(identifier, user_name, GroupIdentifier::ROOT)
323            .await
324            .unwrap();
325        assert!(manager.exists_user(identifier).await.unwrap());
326    }
327
328    #[test]
329    async fn create_user_duplicate() {
330        let user_name_1 = "Alice";
331        let user_name_2 = "Bob";
332
333        let identifier_1 = UserIdentifier::new(1000);
334        let identifier_2 = UserIdentifier::new(1001);
335
336        // Same identifier
337        let manager = Manager::new();
338
339        manager
340            .add_user(identifier_1, user_name_1, GroupIdentifier::ROOT)
341            .await
342            .unwrap();
343
344        let result = manager
345            .add_user(identifier_1, user_name_2, GroupIdentifier::ROOT)
346            .await;
347        assert_eq!(result, Err(Error::DuplicateUserIdentifier));
348
349        // Same name
350        let manager = Manager::new();
351
352        manager
353            .add_user(identifier_1, user_name_1, GroupIdentifier::ROOT)
354            .await
355            .unwrap();
356
357        let result = manager
358            .add_user(identifier_2, user_name_1, GroupIdentifier::ROOT)
359            .await;
360        assert_eq!(result, Err(Error::DuplicateUserName));
361
362        // Same name and identifier
363        let manager = Manager::new();
364
365        manager
366            .add_user(identifier_1, user_name_1, GroupIdentifier::ROOT)
367            .await
368            .unwrap();
369
370        manager
371            .add_user(identifier_1, user_name_1, GroupIdentifier::ROOT)
372            .await
373            .unwrap_err();
374    }
375
376    #[test]
377    async fn create_group() {
378        let manager = Manager::new();
379        let group_name = "Developers";
380        let group_id = GroupIdentifier::new(1000);
381        let result = manager.add_group(group_id, group_name, &[]).await;
382        assert!(result.is_ok());
383        assert!(manager.exists_group(group_id).await.unwrap());
384    }
385
386    #[test]
387    async fn create_group_duplicate() {
388        let group_name_1 = "Developers";
389        let group_name_2 = "Testers";
390
391        let group_id_1 = GroupIdentifier::new(1000);
392        let group_id_2 = GroupIdentifier::new(1001);
393
394        // Same identifier
395        let manager = Manager::new();
396
397        manager
398            .add_group(group_id_1, group_name_1, &[])
399            .await
400            .unwrap();
401
402        let result = manager.add_group(group_id_1, group_name_2, &[]).await;
403        assert_eq!(result, Err(Error::DuplicateGroupIdentifier));
404
405        // Same name
406        let manager = Manager::new();
407
408        manager
409            .add_group(group_id_1, group_name_1, &[])
410            .await
411            .unwrap();
412
413        let result = manager.add_group(group_id_2, group_name_1, &[]).await;
414        assert_eq!(result, Err(Error::DuplicateGroupName));
415
416        // Same name and identifier
417        let manager = Manager::new();
418
419        manager
420            .add_group(group_id_1, group_name_1, &[])
421            .await
422            .unwrap();
423
424        manager
425            .add_group(group_id_1, group_name_1, &[])
426            .await
427            .unwrap_err();
428    }
429
430    #[test]
431    async fn is_root() {
432        let root_id = UserIdentifier::ROOT;
433        assert!(Manager::is_root(root_id));
434    }
435
436    #[test]
437    async fn is_in_group() {
438        let manager = Manager::new();
439        let user_name = "Bob";
440        let identifier = UserIdentifier::new(1000);
441        manager
442            .add_user(identifier, user_name, GroupIdentifier::ROOT)
443            .await
444            .unwrap();
445        let group_name = "Admins";
446        let group_id = GroupIdentifier::new(1000);
447
448        manager.add_group(group_id, group_name, &[]).await.unwrap();
449        manager.add_to_group(identifier, group_id).await.unwrap();
450        assert!(manager.is_in_group(identifier, group_id).await);
451    }
452
453    #[test]
454    async fn get_user_groups() {
455        let manager = Manager::new();
456
457        let user_name = "Charlie";
458        let identifier = UserIdentifier::new(1000);
459        manager
460            .add_user(identifier, user_name, GroupIdentifier::ROOT)
461            .await
462            .unwrap();
463        let group_name1 = "TeamA";
464        let group_id1 = GroupIdentifier::new(1000);
465
466        manager
467            .add_group(group_id1, group_name1, &[])
468            .await
469            .unwrap();
470        let group_name2 = "TeamB";
471        let group_id2 = GroupIdentifier::new(1001);
472
473        manager
474            .add_group(group_id2, group_name2, &[])
475            .await
476            .unwrap();
477        manager.add_to_group(identifier, group_id1).await.unwrap();
478        manager.add_to_group(identifier, group_id2).await.unwrap();
479        let groups = manager.get_user_groups(identifier).await.unwrap();
480
481        assert_eq!(groups.len(), 3);
482        assert!(
483            groups.contains(&group_id1)
484                && groups.contains(&group_id2)
485                && groups.contains(&GroupIdentifier::ROOT)
486        );
487    }
488
489    #[test]
490    async fn get_group_name() {
491        let manager = Manager::new();
492        let group_name = "QA";
493        let group_id = GroupIdentifier::new(1000);
494        manager.add_group(group_id, group_name, &[]).await.unwrap();
495        let retrieved_name = manager.get_group_name(group_id).await.unwrap();
496        assert_eq!(group_name, retrieved_name);
497    }
498
499    #[test]
500    async fn get_group_users() {
501        let manager = Manager::new();
502        let user_name = "Dave";
503        let identifier = UserIdentifier::new(1000);
504        manager
505            .add_user(identifier, user_name, GroupIdentifier::ROOT)
506            .await
507            .unwrap();
508        let group_name = "Engineers";
509        let group_id = GroupIdentifier::new(1000);
510        manager.add_group(group_id, group_name, &[]).await.unwrap();
511        manager.add_to_group(identifier, group_id).await.unwrap();
512        let users = manager.get_group_users(group_id).await.unwrap();
513        assert_eq!(users.len(), 1);
514        assert!(users.contains(&identifier));
515    }
516
517    #[test]
518    async fn get_user_name() {
519        let manager = Manager::new();
520        let user_name = "Eve";
521        let identifier = UserIdentifier::new(1000);
522        manager
523            .add_user(identifier, user_name, GroupIdentifier::ROOT)
524            .await
525            .unwrap();
526        let retrieved_name = manager.get_user_name(identifier).await.unwrap();
527        assert_eq!(user_name, retrieved_name);
528    }
529
530    #[test]
531    async fn check_credentials() {
532        let manager = Manager::new();
533        let user_name = "Frank";
534        let password = "password123";
535        assert!(manager.check_credentials(user_name, password));
536    }
537}