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        inner
179            .groups
180            .get(&group_identifier)
181            .unwrap()
182            .users
183            .contains(&user_identifier)
184    }
185
186    pub async fn get_user_groups(
187        &self,
188        identifier: UserIdentifier,
189    ) -> Result<BTreeSet<GroupIdentifier>> {
190        let inner = self.0.read().await;
191
192        let mut user_groups: BTreeSet<GroupIdentifier> = BTreeSet::new();
193
194        user_groups.extend(
195            inner
196                .groups
197                .iter()
198                .filter(|(_, group)| group.users.contains(&identifier))
199                .map(|(identifier, _)| *identifier),
200        );
201
202        Ok(user_groups)
203    }
204
205    pub async fn exists_group(&self, identifier: GroupIdentifier) -> Result<bool> {
206        Ok(self.0.read().await.groups.contains_key(&identifier))
207    }
208
209    pub async fn exists_user(&self, identifier: UserIdentifier) -> Result<bool> {
210        Ok(self.0.read().await.users.contains_key(&identifier))
211    }
212
213    pub async fn add_to_group(
214        &self,
215        user_identifier: UserIdentifier,
216        group_identifier: GroupIdentifier,
217    ) -> Result<()> {
218        if !self.exists_group(group_identifier).await? {
219            return Err(Error::InvalidGroupIdentifier);
220        }
221        let mut inner = self.0.write().await;
222        if !inner
223            .groups
224            .get_mut(&group_identifier)
225            .unwrap()
226            .users
227            .insert(user_identifier)
228        {
229            return Err(Error::DuplicateGroupIdentifier);
230        }
231        Ok(())
232    }
233
234    pub async fn get_group_name(&self, identifier: GroupIdentifier) -> Result<String> {
235        Ok(self
236            .0
237            .read()
238            .await
239            .groups
240            .get(&identifier)
241            .unwrap()
242            .name
243            .clone())
244    }
245
246    pub async fn get_user_identifier(&self, name: &str) -> Result<UserIdentifier> {
247        Ok(*self
248            .0
249            .read()
250            .await
251            .users
252            .iter()
253            .find(|(_, user)| user.name == name)
254            .ok_or(Error::InvalidUserIdentifier)?
255            .0)
256    }
257
258    pub async fn get_group_users(
259        &self,
260        identifier: GroupIdentifier,
261    ) -> Result<Vec<UserIdentifier>> {
262        Ok(self
263            .0
264            .read()
265            .await
266            .groups
267            .get(&identifier)
268            .ok_or(Error::InvalidGroupIdentifier)?
269            .users
270            .clone()
271            .into_iter()
272            .collect())
273    }
274
275    pub async fn get_user_name(&self, identifier: UserIdentifier) -> Result<String> {
276        Ok(self
277            .0
278            .read()
279            .await
280            .users
281            .get(&identifier)
282            .ok_or(Error::InvalidUserIdentifier)?
283            .name
284            .clone())
285    }
286
287    pub async fn get_user_primary_group(
288        &self,
289        identifier: UserIdentifier,
290    ) -> Result<GroupIdentifier> {
291        Ok(self
292            .0
293            .read()
294            .await
295            .users
296            .get(&identifier)
297            .ok_or(Error::InvalidUserIdentifier)?
298            .primary_group)
299    }
300
301    pub fn check_credentials(&self, _user_name: &str, _password: &str) -> bool {
302        true
303    }
304}
305
306#[cfg(test)]
307mod tests {
308    extern crate std;
309
310    use super::*;
311
312    use task::test;
313
314    #[test]
315    async fn create_user() {
316        let manager = Manager::new();
317        let user_name = "Alice";
318        let identifier = UserIdentifier::new(1000);
319        manager
320            .add_user(identifier, user_name, GroupIdentifier::ROOT)
321            .await
322            .unwrap();
323        assert!(manager.exists_user(identifier).await.unwrap());
324    }
325
326    #[test]
327    async fn create_user_duplicate() {
328        let user_name_1 = "Alice";
329        let user_name_2 = "Bob";
330
331        let identifier_1 = UserIdentifier::new(1000);
332        let identifier_2 = UserIdentifier::new(1001);
333
334        // Same identifier
335        let manager = Manager::new();
336
337        manager
338            .add_user(identifier_1, user_name_1, GroupIdentifier::ROOT)
339            .await
340            .unwrap();
341
342        let result = manager
343            .add_user(identifier_1, user_name_2, GroupIdentifier::ROOT)
344            .await;
345        assert_eq!(result, Err(Error::DuplicateUserIdentifier));
346
347        // Same name
348        let manager = Manager::new();
349
350        manager
351            .add_user(identifier_1, user_name_1, GroupIdentifier::ROOT)
352            .await
353            .unwrap();
354
355        let result = manager
356            .add_user(identifier_2, user_name_1, GroupIdentifier::ROOT)
357            .await;
358        assert_eq!(result, Err(Error::DuplicateUserName));
359
360        // Same name and identifier
361        let manager = Manager::new();
362
363        manager
364            .add_user(identifier_1, user_name_1, GroupIdentifier::ROOT)
365            .await
366            .unwrap();
367
368        manager
369            .add_user(identifier_1, user_name_1, GroupIdentifier::ROOT)
370            .await
371            .unwrap_err();
372    }
373
374    #[test]
375    async fn create_group() {
376        let manager = Manager::new();
377        let group_name = "Developers";
378        let group_id = GroupIdentifier::new(1000);
379        let result = manager.add_group(group_id, group_name, &[]).await;
380        assert!(result.is_ok());
381        assert!(manager.exists_group(group_id).await.unwrap());
382    }
383
384    #[test]
385    async fn create_group_duplicate() {
386        let group_name_1 = "Developers";
387        let group_name_2 = "Testers";
388
389        let group_id_1 = GroupIdentifier::new(1000);
390        let group_id_2 = GroupIdentifier::new(1001);
391
392        // Same identifier
393        let manager = Manager::new();
394
395        manager
396            .add_group(group_id_1, group_name_1, &[])
397            .await
398            .unwrap();
399
400        let result = manager.add_group(group_id_1, group_name_2, &[]).await;
401        assert_eq!(result, Err(Error::DuplicateGroupIdentifier));
402
403        // Same name
404        let manager = Manager::new();
405
406        manager
407            .add_group(group_id_1, group_name_1, &[])
408            .await
409            .unwrap();
410
411        let result = manager.add_group(group_id_2, group_name_1, &[]).await;
412        assert_eq!(result, Err(Error::DuplicateGroupName));
413
414        // Same name and identifier
415        let manager = Manager::new();
416
417        manager
418            .add_group(group_id_1, group_name_1, &[])
419            .await
420            .unwrap();
421
422        manager
423            .add_group(group_id_1, group_name_1, &[])
424            .await
425            .unwrap_err();
426    }
427
428    #[test]
429    async fn is_root() {
430        let root_id = UserIdentifier::ROOT;
431        assert!(Manager::is_root(root_id));
432    }
433
434    #[test]
435    async fn is_in_group() {
436        let manager = Manager::new();
437        let user_name = "Bob";
438        let identifier = UserIdentifier::new(1000);
439        manager
440            .add_user(identifier, user_name, GroupIdentifier::ROOT)
441            .await
442            .unwrap();
443        let group_name = "Admins";
444        let group_id = GroupIdentifier::new(1000);
445
446        manager.add_group(group_id, group_name, &[]).await.unwrap();
447        manager.add_to_group(identifier, group_id).await.unwrap();
448        assert!(manager.is_in_group(identifier, group_id).await);
449    }
450
451    #[test]
452    async fn get_user_groups() {
453        let manager = Manager::new();
454
455        let user_name = "Charlie";
456        let identifier = UserIdentifier::new(1000);
457        manager
458            .add_user(identifier, user_name, GroupIdentifier::ROOT)
459            .await
460            .unwrap();
461        let group_name1 = "TeamA";
462        let group_id1 = GroupIdentifier::new(1000);
463
464        manager
465            .add_group(group_id1, group_name1, &[])
466            .await
467            .unwrap();
468        let group_name2 = "TeamB";
469        let group_id2 = GroupIdentifier::new(1001);
470
471        manager
472            .add_group(group_id2, group_name2, &[])
473            .await
474            .unwrap();
475        manager.add_to_group(identifier, group_id1).await.unwrap();
476        manager.add_to_group(identifier, group_id2).await.unwrap();
477        let groups = manager.get_user_groups(identifier).await.unwrap();
478
479        assert_eq!(groups.len(), 3);
480        assert!(
481            groups.contains(&group_id1)
482                && groups.contains(&group_id2)
483                && groups.contains(&GroupIdentifier::ROOT)
484        );
485    }
486
487    #[test]
488    async fn get_group_name() {
489        let manager = Manager::new();
490        let group_name = "QA";
491        let group_id = GroupIdentifier::new(1000);
492        manager.add_group(group_id, group_name, &[]).await.unwrap();
493        let retrieved_name = manager.get_group_name(group_id).await.unwrap();
494        assert_eq!(group_name, retrieved_name);
495    }
496
497    #[test]
498    async fn get_group_users() {
499        let manager = Manager::new();
500        let user_name = "Dave";
501        let identifier = UserIdentifier::new(1000);
502        manager
503            .add_user(identifier, user_name, GroupIdentifier::ROOT)
504            .await
505            .unwrap();
506        let group_name = "Engineers";
507        let group_id = GroupIdentifier::new(1000);
508        manager.add_group(group_id, group_name, &[]).await.unwrap();
509        manager.add_to_group(identifier, group_id).await.unwrap();
510        let users = manager.get_group_users(group_id).await.unwrap();
511        assert_eq!(users.len(), 1);
512        assert!(users.contains(&identifier));
513    }
514
515    #[test]
516    async fn get_user_name() {
517        let manager = Manager::new();
518        let user_name = "Eve";
519        let identifier = UserIdentifier::new(1000);
520        manager
521            .add_user(identifier, user_name, GroupIdentifier::ROOT)
522            .await
523            .unwrap();
524        let retrieved_name = manager.get_user_name(identifier).await.unwrap();
525        assert_eq!(user_name, retrieved_name);
526    }
527
528    #[test]
529    async fn check_credentials() {
530        let manager = Manager::new();
531        let user_name = "Frank";
532        let password = "password123";
533        assert!(manager.check_credentials(user_name, password));
534    }
535}