Skip to main content

users/
manager.rs

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