auth_policy/
engine.rs

1use crate::{
2    decision::{Decision, Effect},
3    error::Result,
4    policy::Policy,
5    request::Request,
6};
7
8#[derive(Debug)]
9pub struct PolicyEngine {
10    policies: Vec<Policy>,
11    default_effect: Effect,
12}
13
14impl PolicyEngine {
15    /// Create an empty engine that defaults to denying requests when no policy applies.
16    pub fn new() -> Self {
17        Self {
18            policies: Vec::new(),
19            default_effect: Effect::Deny,
20        }
21    }
22
23    /// Build an engine from an iterator of policies.
24    pub fn from_policies<I>(policies: I) -> Self
25    where
26        I: IntoIterator<Item = Policy>,
27    {
28        let mut engine = Self::new();
29        engine.policies.extend(policies);
30        engine
31    }
32
33    /// Set the default effect returned when no policy matches.
34    pub fn with_default_effect(mut self, effect: Effect) -> Self {
35        self.default_effect = effect;
36        self
37    }
38
39    /// Add a policy to the engine.
40    pub fn add_policy(&mut self, policy: Policy) {
41        self.policies.push(policy);
42    }
43
44    /// Evaluate the request against the configured policies.
45    pub fn evaluate(&self, request: &Request) -> Result<Decision> {
46        for policy in &self.policies {
47            if let Some(effect) = policy.evaluate(request)? {
48                return Ok(Decision::from_effect(effect));
49            }
50        }
51
52        Ok(Decision::from_effect(self.default_effect))
53    }
54}
55
56impl Default for PolicyEngine {
57    fn default() -> Self {
58        Self::new()
59    }
60}