#![deny(clippy::wildcard_enum_match_arm)]
use nodedb_types::id::DatabaseId;
use crate::types::TenantId;
use super::role::Role;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Permission {
Read,
Write,
Create,
Drop,
Alter,
Admin,
Monitor,
Execute,
Backup,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PermissionTarget {
Cluster,
Tenant(TenantId),
Database(DatabaseId),
Collection {
tenant_id: TenantId,
database_id: DatabaseId,
collection: String,
},
SystemCatalog,
}
pub fn role_grants_permission(role: &Role, permission: Permission) -> bool {
match role {
Role::Superuser => true,
Role::ClusterAdmin => false,
Role::TenantAdmin => true,
Role::ReadWrite => matches!(
permission,
Permission::Read | Permission::Write | Permission::Execute
),
Role::ReadOnly => matches!(permission, Permission::Read | Permission::Execute),
Role::Monitor => matches!(permission, Permission::Monitor | Permission::Read),
Role::DatabaseOwner(_) => true,
Role::DatabaseEditor(_) => matches!(
permission,
Permission::Read | Permission::Write | Permission::Create | Permission::Execute
),
Role::DatabaseReader(_) => matches!(permission, Permission::Read | Permission::Execute),
Role::Custom(_) => false, }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn role_permission_mapping() {
assert!(role_grants_permission(&Role::ReadOnly, Permission::Read));
assert!(!role_grants_permission(&Role::ReadOnly, Permission::Write));
assert!(role_grants_permission(&Role::ReadWrite, Permission::Read));
assert!(role_grants_permission(&Role::ReadWrite, Permission::Write));
assert!(!role_grants_permission(&Role::ReadWrite, Permission::Drop));
assert!(role_grants_permission(
&Role::TenantAdmin,
Permission::Admin
));
assert!(role_grants_permission(&Role::TenantAdmin, Permission::Drop));
}
#[test]
fn database_scoped_roles_grant_within_their_tier() {
let db = DatabaseId::new(7);
assert!(role_grants_permission(
&Role::DatabaseOwner(db),
Permission::Drop
));
assert!(role_grants_permission(
&Role::DatabaseEditor(db),
Permission::Write
));
assert!(!role_grants_permission(
&Role::DatabaseEditor(db),
Permission::Drop
));
assert!(role_grants_permission(
&Role::DatabaseReader(db),
Permission::Read
));
assert!(!role_grants_permission(
&Role::DatabaseReader(db),
Permission::Write
));
}
#[test]
fn custom_role_grants_nothing_by_default() {
let role = Role::Custom("data_scientist".into());
for perm in [
Permission::Read,
Permission::Write,
Permission::Create,
Permission::Drop,
Permission::Alter,
Permission::Admin,
Permission::Monitor,
Permission::Execute,
] {
assert!(
!role_grants_permission(&role, perm),
"custom role unexpectedly granted {perm:?}"
);
}
}
}