use redfish_codegen::models::privileges::PrivilegeType;
use std::marker::PhantomData;
#[derive(Clone, Copy, PartialEq, Eq, Hash, strum::EnumIter, strum::Display, strum::EnumString)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Privilege {
Login,
ConfigureComponents,
ConfigureManager,
ConfigureSelf,
ConfigureUsers,
}
impl From<Privilege> for PrivilegeType {
fn from(value: Privilege) -> Self {
match value {
Privilege::Login => PrivilegeType::Login,
Privilege::ConfigureComponents => PrivilegeType::ConfigureComponents,
Privilege::ConfigureManager => PrivilegeType::ConfigureManager,
Privilege::ConfigureSelf => PrivilegeType::ConfigureSelf,
Privilege::ConfigureUsers => PrivilegeType::ConfigureUsers,
}
}
}
pub trait SatisfiesPrivilege {
fn is_satisfied(privileges: &[Privilege]) -> bool;
}
#[derive(Clone, Default)]
pub struct Login;
impl SatisfiesPrivilege for Login {
fn is_satisfied(privileges: &[Privilege]) -> bool {
privileges.contains(&Privilege::Login)
}
}
#[derive(Clone, Default)]
pub struct ConfigureManager;
impl SatisfiesPrivilege for ConfigureManager {
fn is_satisfied(privileges: &[Privilege]) -> bool {
privileges.contains(&Privilege::ConfigureManager)
}
}
#[derive(Clone, Default)]
pub struct ConfigureUsers;
impl SatisfiesPrivilege for ConfigureUsers {
fn is_satisfied(privileges: &[Privilege]) -> bool {
privileges.contains(&Privilege::ConfigureUsers)
}
}
#[derive(Clone, Default)]
pub struct ConfigureComponents;
impl SatisfiesPrivilege for ConfigureComponents {
fn is_satisfied(privileges: &[Privilege]) -> bool {
privileges.contains(&Privilege::ConfigureComponents)
}
}
#[derive(Clone, Default)]
pub struct ConfigureSelf;
impl SatisfiesPrivilege for ConfigureSelf {
fn is_satisfied(privileges: &[Privilege]) -> bool {
privileges.contains(&Privilege::ConfigureSelf)
}
}
#[derive(Clone, Default)]
pub struct NoAuth;
impl SatisfiesPrivilege for NoAuth {
fn is_satisfied(_privileges: &[Privilege]) -> bool {
true
}
}
#[derive(Clone)]
pub struct And<P, R>(PhantomData<fn() -> (P, R)>)
where
P: SatisfiesPrivilege + Clone,
R: SatisfiesPrivilege + Clone;
impl<P, R> SatisfiesPrivilege for And<P, R>
where
P: SatisfiesPrivilege + Clone,
R: SatisfiesPrivilege + Clone,
{
fn is_satisfied(privileges: &[Privilege]) -> bool {
P::is_satisfied(privileges) && R::is_satisfied(privileges)
}
}
#[derive(Clone)]
pub struct Or<P, R>(PhantomData<fn() -> (P, R)>)
where
P: SatisfiesPrivilege + Clone,
R: SatisfiesPrivilege + Clone;
impl<P, R> SatisfiesPrivilege for Or<P, R>
where
P: SatisfiesPrivilege + Clone,
R: SatisfiesPrivilege + Clone,
{
fn is_satisfied(privileges: &[Privilege]) -> bool {
P::is_satisfied(privileges) || R::is_satisfied(privileges)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, strum::EnumIter, strum::Display, strum::EnumString)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Role {
Administrator,
Operator,
ReadOnly,
}
impl Role {
pub fn privileges(&self) -> Vec<Privilege> {
match &self {
Self::Administrator => vec![
Privilege::Login,
Privilege::ConfigureManager,
Privilege::ConfigureUsers,
Privilege::ConfigureComponents,
Privilege::ConfigureSelf,
],
Self::Operator => vec![
Privilege::Login,
Privilege::ConfigureComponents,
Privilege::ConfigureSelf,
],
Self::ReadOnly => vec![Privilege::Login, Privilege::ConfigureSelf],
}
}
}
pub trait OperationPrivilegeMapping {
type Get: SatisfiesPrivilege;
type Head: SatisfiesPrivilege;
type Post: SatisfiesPrivilege;
type Put: SatisfiesPrivilege;
type Patch: SatisfiesPrivilege;
type Delete: SatisfiesPrivilege;
}