sea_orm/rbac/engine/
snapshot.rs

1use super::*;
2
3#[derive(Debug, Default)]
4pub struct RbacSnapshot {
5    pub(super) resources: Vec<Resource>,
6    pub(super) permissions: Vec<Permission>,
7    pub(super) roles: Vec<Role>,
8    pub(super) user_roles: Vec<UserRole>,
9    pub(super) role_permissions: Vec<RolePermission>,
10    pub(super) user_overrides: Vec<UserOverride>,
11    pub(super) role_hierarchy: Vec<RoleHierarchy>,
12}
13
14impl RbacSnapshot {
15    /// Create an unrestricted system where `UserId(0)` can perform any action on any resource.
16    /// This is intended to be an escape hatch to bypass RBAC restrictions.
17    /// Use at your own risk.
18    pub fn danger_unrestricted() -> Self {
19        let mut snapshot = Self::default();
20
21        snapshot.set_resources(vec![Resource {
22            id: ResourceId(0),
23            schema: None,
24            table: WILDCARD.to_owned(),
25        }]);
26        snapshot.set_permissions(vec![Permission {
27            id: PermissionId(0),
28            action: WILDCARD.to_owned(),
29        }]);
30        snapshot.set_roles(vec![Role {
31            id: RoleId(0),
32            role: "unrestricted".to_owned(),
33        }]);
34        snapshot.set_user_role(UserId(0), "unrestricted");
35        snapshot.add_role_permission("unrestricted", Action("*"), Table("*"));
36
37        snapshot
38    }
39
40    pub(super) fn set_resources(&mut self, mut resources: Vec<Resource>) {
41        for (i, r) in resources.iter_mut().enumerate() {
42            r.id = ResourceId(i as i64 + 1);
43        }
44        self.resources = resources;
45    }
46
47    pub(super) fn set_permissions(&mut self, mut permissions: Vec<Permission>) {
48        for (i, r) in permissions.iter_mut().enumerate() {
49            r.id = PermissionId(i as i64 + 1);
50        }
51        self.permissions = permissions;
52    }
53
54    pub(super) fn set_roles(&mut self, mut roles: Vec<Role>) {
55        for (i, r) in roles.iter_mut().enumerate() {
56            r.id = RoleId(i as i64 + 1);
57        }
58        self.roles = roles;
59    }
60
61    pub(super) fn set_user_role(&mut self, user_id: UserId, role: &str) {
62        self.user_roles.push(UserRole {
63            user_id,
64            role_id: self.find_role(role),
65        });
66    }
67
68    pub(super) fn add_role_permission<P, R>(&mut self, role: &str, permission: P, resource: R)
69    where
70        P: Into<PermissionRequest>,
71        R: Into<ResourceRequest>,
72    {
73        let permission = permission.into();
74        let resource = resource.into();
75        let role_id = self.find_role(role);
76        self.role_permissions.push(RolePermission {
77            role_id,
78            permission_id: self.find_permission(&permission),
79            resource_id: self.find_resource(&resource),
80        });
81    }
82
83    #[cfg(test)]
84    pub(super) fn add_user_override<P, R>(
85        &mut self,
86        user_id: UserId,
87        permission: P,
88        resource: R,
89        grant: bool,
90    ) where
91        P: Into<PermissionRequest>,
92        R: Into<ResourceRequest>,
93    {
94        let permission = permission.into();
95        let resource = resource.into();
96        self.user_overrides.push(UserOverride {
97            user_id,
98            permission_id: self.find_permission(&permission),
99            resource_id: self.find_resource(&resource),
100            grant,
101        });
102    }
103
104    #[cfg(test)]
105    pub(super) fn add_role_hierarchy(&mut self, role: &str, super_role: &str) {
106        self.role_hierarchy.push(RoleHierarchy {
107            role_id: self.find_role(role),
108            super_role_id: self.find_role(super_role),
109        })
110    }
111
112    pub(super) fn find_role(&self, role: &str) -> RoleId {
113        self.roles.iter().find(|r| r.role == role).unwrap().id
114    }
115
116    pub(super) fn find_permission(&self, permission: &PermissionRequest) -> PermissionId {
117        self.permissions
118            .iter()
119            .find(|r| r.action == permission.action)
120            .unwrap()
121            .id
122    }
123
124    pub(super) fn find_resource(&self, resource: &ResourceRequest) -> ResourceId {
125        self.resources
126            .iter()
127            .find(|r| r.schema == resource.schema && r.table == resource.table)
128            .unwrap()
129            .id
130    }
131}