diff options
Diffstat (limited to 'src/access')
| -rw-r--r-- | src/access/registry.rs | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/access/registry.rs b/src/access/registry.rs index 4b4304a..948e0de 100644 --- a/src/access/registry.rs +++ b/src/access/registry.rs @@ -108,6 +108,14 @@ pub(crate) fn user(doc: &impl ReadDoc, name: &str) -> Option<User> { value.is_object().then(|| User::from_json(&value)) } +/// The users who may manage users: enabled, with `write` on `_continuum/users`. +pub(crate) fn managers(doc: &impl ReadDoc) -> Vec<String> { + names(doc) + .into_iter() + .filter(|name| caps_of(doc, name).allows(Right::Write, &users_dir())) + .collect() +} + /// What user `name` may do: none if it isn't registered (or is disabled). pub(crate) fn caps_of(doc: &impl ReadDoc, name: &str) -> Caps { user(doc, name).map(|user| user.caps()).unwrap_or_default() @@ -301,6 +309,24 @@ mod tests { } #[test] + fn who_may_manage_users() { + let mut doc = Document::new(); + for (name, admin) in [("alice", true), ("bob", false)] { + let entry = entry("x", 0, &first_caps(admin)); + change(&mut doc, |tx| { + store::write_path(tx, &user_path(name), &entry).unwrap() + }); + } + assert_eq!(managers(&doc), vec!["alice"]); + let mut disabled = user_path("alice"); + disabled.push("disabled".to_owned()); + change(&mut doc, |tx| { + store::write_path(tx, &disabled, &json!(true)).unwrap() + }); + assert!(managers(&doc).is_empty()); + } + + #[test] fn concurrent_grants_both_hold() { let mut ours = Document::new(); let entry = entry("x", 0, &[]); |
