ockam_abac 0.80.0

Attribute based authorization control
use crate::error::{EvalError, MergeError};
use crate::expr::Expr;
use core::fmt::{Display, Formatter};
use ockam_core::compat::collections::BTreeMap;
use ockam_core::compat::format;
use ockam_core::compat::string::{String, ToString};
use ockam_core::compat::vec::vec;

#[derive(Debug, Clone, Default)]
pub struct Env(BTreeMap<String, Expr>);

impl Display for Env {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        let mut values = vec![];
        for (key, value) in self.0.clone() {
            values.push(format!("{key}={value:?}"));
        }
        f.debug_struct("Env")
            .field("values", &values.join(","))
            .finish()
    }
}

impl Env {
    pub fn new() -> Self {
        Env(BTreeMap::new())
    }
    pub fn new_from(v: BTreeMap<&str, Expr>) -> Self {
        Env(v.into_iter().map(|(k, e)| (k.to_string(), e)).collect())
    }

    pub fn get(&self, k: &str) -> Result<&Expr, EvalError> {
        self.0
            .get(k)
            .ok_or_else(|| EvalError::Unbound(k.to_string()))
    }

    pub fn contains(&self, k: &str) -> bool {
        self.0.contains_key(k)
    }

    pub fn put<K: Into<String>, E: Into<Expr>>(&mut self, k: K, v: E) -> &mut Self {
        self.0.insert(k.into(), v.into());
        self
    }

    pub fn del(&mut self, k: &str) {
        self.0.remove(k);
    }

    pub fn entries(&self) -> impl Iterator<Item = (&str, &Expr)> {
        self.0.iter().map(|(k, v)| (k.as_str(), v))
    }

    pub fn clear(&mut self) {
        self.0.clear()
    }

    pub fn merge(&mut self, other: Env) -> Result<(), MergeError> {
        for k in other.0.keys() {
            if self.0.contains_key(k) {
                return Err(MergeError::BindingExists(k.clone()));
            }
        }
        for (k, v) in other.0.into_iter() {
            self.0.insert(k, v);
        }
        Ok(())
    }

    pub fn merge_right(&mut self, other: Env) {
        for (k, v) in other.0.into_iter() {
            self.0.insert(k, v);
        }
    }

    pub fn merge_left(&mut self, other: Env) {
        for (k, v) in other.0.into_iter() {
            self.0.entry(k).or_insert(v);
        }
    }
}