use std::collections::HashMap;
use std::sync::Arc;
use rpki::ca::idexchange::MyHandle;
use serde::Deserialize;
use super::{Permission, PermissionSet};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
#[serde(from = "RoleConf")]
pub struct Role {
none: PermissionSet,
any: PermissionSet,
resources: HashMap<MyHandle, PermissionSet>,
}
impl Role {
pub fn admin() -> Self {
Self::simple(PermissionSet::ANY)
}
pub fn readwrite() -> Self {
Self::simple(PermissionSet::READWRITE)
}
pub fn readonly() -> Self {
Self::simple(PermissionSet::READONLY)
}
pub fn testbed() -> Self {
Self::simple(PermissionSet::TESTBED)
}
pub fn anonymous() -> Self {
Self::simple(PermissionSet::NONE)
}
pub fn simple(permissions: PermissionSet) -> Self {
Self {
none: permissions,
any: permissions,
resources: Default::default()
}
}
pub fn with_resources(
permissions: PermissionSet,
resources: impl IntoIterator<Item = MyHandle>
) -> Self {
Self {
none: permissions,
any: PermissionSet::NONE,
resources: resources.into_iter().map(|handle| {
(handle, permissions)
}).collect()
}
}
pub fn complex(
none: PermissionSet,
any: PermissionSet,
resources: HashMap<MyHandle, PermissionSet>
) -> Self {
Self { none, any, resources }
}
pub fn is_allowed(
&self,
permission: Permission,
resource: Option<&MyHandle>
) -> bool {
match resource {
Some(resource) => {
match self.resources.get(resource) {
Some(permissions) => permissions.has(permission),
None => self.any.has(permission),
}
}
None => {
self.none.has(permission)
}
}
}
}
impl From<RoleConf> for Role {
fn from(src: RoleConf) -> Self {
match src.cas {
Some(cas) => Self::with_resources(src.permissions, cas),
None => Self::simple(src.permissions)
}
}
}
#[derive(Clone, Debug, Deserialize)]
struct RoleConf {
permissions: PermissionSet,
cas: Option<Vec<MyHandle>>,
}
#[derive(Clone, Debug, Default, Deserialize)]
pub struct RoleMap(HashMap<String, Arc<Role>>);
impl RoleMap {
pub fn new() -> Self {
Self::default()
}
pub fn add(
&mut self, name: impl Into<String>, role: impl Into<Arc<Role>>
) {
self.0.insert(name.into(), role.into());
}
pub fn contains(&self, name: &str) -> bool {
self.0.contains_key(name)
}
pub fn get(&self, name: &str) -> Option<Arc<Role>> {
self.0.get(name).cloned()
}
}