//! Role and permission model. use std::collections::HashMap; /// A fine-grained permission (e.g., "read", "write", "delete"). #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Permission(pub String); impl Permission { pub fn new(name: impl Into) -> Self { Self(name.into()) } pub fn as_str(&self) -> &str { &self.0 } } impl std::fmt::Display for Permission { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) } } /// A role that grants a set of permissions. #[derive(Debug, Clone)] pub struct Role { pub name: String, pub permissions: Vec, } impl Role { pub fn new(name: impl Into) -> Self { Self { name: name.into(), permissions: Vec::new(), } } pub fn with_permission(mut self, perm: impl Into) -> Self { self.permissions.push(Permission::new(perm)); self } pub fn with_permissions(mut self, perms: Vec>) -> Self { self.permissions.extend(perms.into_iter().map(Permission::new)); self } pub fn has_permission(&self, perm: &str) -> bool { self.permissions.iter().any(|p| p.0 == perm) } } /// The registry of all roles in the application. #[derive(Debug, Default)] pub struct RoleRegistry { roles: HashMap, } impl RoleRegistry { pub fn new() -> Self { Self::default() } /// Register a role. pub fn register(&mut self, role: Role) { self.roles.insert(role.name.clone(), role); } /// Get a role by name. pub fn get(&self, name: &str) -> Option<&Role> { self.roles.get(name) } /// Check if the given role names grant the given permission. pub fn has_permission(&self, role_names: &[String], permission: &str) -> bool { role_names.iter().any(|role_name| { self.roles .get(role_name) .map(|r| r.has_permission(permission)) .unwrap_or(false) }) } /// List all registered role names. pub fn role_names(&self) -> Vec<&str> { self.roles.keys().map(|s| s.as_str()).collect() } }