Skip to main content

uqa_sql/catalog/roles/
restoration.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Validation of persisted role keys and membership identities.
8use super::{RoleDefinition, RoleMembership, RoleMembershipKey};
9use std::collections::{BTreeMap, BTreeSet};
10
11pub fn restore_role_definitions(
12    roles: &mut BTreeMap<String, RoleDefinition>,
13) -> Result<(), String> {
14    roles
15        .entry("uqa".into())
16        .or_insert_with(RoleDefinition::bootstrap);
17    for (name, role) in roles.iter() {
18        if role.name != *name {
19            return Err(format!(
20                "persisted role key `{name}` does not match role name `{}`",
21                role.name
22            ));
23        }
24    }
25    Ok(())
26}
27
28pub fn restore_role_memberships(
29    roles: &BTreeMap<String, RoleDefinition>,
30    memberships: Vec<RoleMembership>,
31) -> Result<BTreeMap<RoleMembershipKey, RoleMembership>, String> {
32    let mut membership_map = BTreeMap::new();
33    let mut membership_oids = BTreeSet::new();
34    for membership in memberships {
35        if !roles.contains_key(&membership.role)
36            || !roles.contains_key(&membership.member)
37            || !roles.contains_key(&membership.grantor)
38        {
39            return Err(format!(
40                "persisted role membership `{}` -> `{}` has a missing role or grantor",
41                membership.member, membership.role
42            ));
43        }
44        if !membership_oids.insert(membership.oid) {
45            return Err(format!(
46                "persisted role membership OID {} is duplicated",
47                membership.oid
48            ));
49        }
50        let key = membership.key();
51        if membership_map.insert(key, membership).is_some() {
52            return Err("persisted role membership identity is duplicated".into());
53        }
54    }
55    Ok(membership_map)
56}
57
58#[cfg(test)]
59mod tests;