use crate::{
decision::{Decision, Effect},
error::Result,
policy::Policy,
request::Request,
};
#[derive(Debug)]
pub struct PolicyEngine {
policies: Vec<Policy>,
default_effect: Effect,
}
impl PolicyEngine {
pub fn new() -> Self {
Self {
policies: Vec::new(),
default_effect: Effect::Deny,
}
}
pub fn from_policies<I>(policies: I) -> Self
where
I: IntoIterator<Item = Policy>,
{
let mut engine = Self::new();
engine.policies.extend(policies);
engine
}
pub fn with_default_effect(mut self, effect: Effect) -> Self {
self.default_effect = effect;
self
}
pub fn add_policy(&mut self, policy: Policy) {
self.policies.push(policy);
}
pub fn evaluate(&self, request: &Request) -> Result<Decision> {
for policy in &self.policies {
if let Some(effect) = policy.evaluate(request)? {
return Ok(Decision::from_effect(effect));
}
}
Ok(Decision::from_effect(self.default_effect))
}
}
impl Default for PolicyEngine {
fn default() -> Self {
Self::new()
}
}