From 9cb500e7cfa106c7966410512da674b5d69fbd15 Mon Sep 17 00:00:00 2001 From: Ron Waldon-Howe Date: Tue, 12 Nov 2024 20:44:58 +1100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Support=20``=20and=20``?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config.rs | 80 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/src/config.rs b/src/config.rs index 3b250f0..ca2a71c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -300,10 +300,10 @@ pub struct Limits { #[derive(Clone, Debug, PartialEq)] pub enum Policy { - DefaultContext, - Group(String), - MandatoryContext, - User(String), + DefaultContext(Vec), + Group(Vec, String), + MandatoryContext(Vec), + User(Vec, String), } // TODO: implement Cmp/Ord to help stable-sort Policy values: // DefaultContext < Group < User < MandatoryContext @@ -327,26 +327,36 @@ impl TryFrom for OptionalPolicy { at_console: None, context: Some(c), group: None, + rules, user: None, - .. } => Ok(Some(match c { - PolicyContext::Default => Policy::DefaultContext, - PolicyContext::Mandatory => Policy::MandatoryContext, + PolicyContext::Default => { + Policy::DefaultContext(rules_try_from_rule_elements(rules)?) + } + PolicyContext::Mandatory => { + Policy::MandatoryContext(rules_try_from_rule_elements(rules)?) + } })), PolicyElement { at_console: None, context: None, group: Some(group), + rules, user: None, - .. - } => Ok(Some(Policy::Group(group))), + } => Ok(Some(Policy::Group( + rules_try_from_rule_elements(rules)?, + group, + ))), PolicyElement { at_console: None, context: None, group: None, + rules, user: Some(user), - .. - } => Ok(Some(Policy::User(user))), + } => Ok(Some(Policy::User( + rules_try_from_rule_elements(rules)?, + user, + ))), _ => Err(Error::msg(format!( "policy contains conflicting attributes: {value:?}" ))), @@ -369,12 +379,48 @@ struct PolicyElement { context: Option, #[serde(rename = "@group")] group: Option, - // #[serde(rename = "$value", default)] - // rules: Vec, + #[serde(rename = "$value", default)] + rules: Vec, #[serde(rename = "@user")] user: Option, } +type OptionalRule = Option; +impl TryFrom for OptionalRule { + type Error = Error; + + fn try_from(value: RuleElement) -> Result { + match value { + RuleElement::Allow => Ok(Some(Rule::Allow)), + RuleElement::Deny => Ok(Some(Rule::Deny)), + } + } +} + +fn rules_try_from_rule_elements(value: Vec) -> Result> { + let mut rules = vec![]; + for rule in value { + let rule = OptionalRule::try_from(rule)?; + if let Some(some) = rule { + rules.push(some); + } + } + Ok(rules) +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Rule { + Allow, + Deny, +} + +#[derive(Clone, Debug, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] +enum RuleElement { + Allow, + Deny, +} + #[derive(Clone, Debug, Deserialize, PartialEq)] #[serde(rename_all = "lowercase")] pub enum Type { @@ -574,10 +620,10 @@ mod tests { busconfig, BusConfig { policies: vec![ - Policy::DefaultContext, - Policy::User(String::from("root")), - Policy::Group(String::from("network")), - Policy::MandatoryContext, + Policy::DefaultContext(vec![Rule::Allow, Rule::Allow, Rule::Allow,]), + Policy::User(vec![Rule::Allow,], String::from("root")), + Policy::Group(vec![Rule::Allow, Rule::Allow,], String::from("network")), + Policy::MandatoryContext(vec![Rule::Deny]), ], ..Default::default() }