treetop-core 0.0.24

Core library for Treetop, a Cedar policy engine implementation.
Documentation
use std::collections::HashSet;

use cedar_policy::{EntityTypeName, EntityUid};

use crate::error::PolicyError;
use crate::traits::CedarAtom;
use crate::types::{Action, Principal, Resource, group_entity_uid, user_entity_uid};

#[derive(Debug)]
pub(crate) struct PrincipalQuery {
    pub(crate) uid: EntityUid,
    pub(crate) type_name: EntityTypeName,
    pub(crate) parents: HashSet<EntityUid>,
}

impl PrincipalQuery {
    pub(crate) fn for_user(
        user: &str,
        groups: &[&str],
        namespace: &[&str],
    ) -> Result<Self, PolicyError> {
        let uid = user_entity_uid(user, namespace)?;

        let mut parents = HashSet::with_capacity(groups.len());
        for group in groups {
            parents.insert(group_entity_uid(group, namespace)?);
        }

        Ok(Self {
            type_name: entity_type_name_from_uid(&uid),
            uid,
            parents,
        })
    }

    pub(crate) fn for_group(group: &str, namespace: &[&str]) -> Result<Self, PolicyError> {
        let uid = group_entity_uid(group, namespace)?;
        let mut parents = HashSet::new();
        // Cedar `in` includes equality for entities.
        parents.insert(uid.clone());

        Ok(Self {
            type_name: entity_type_name_from_uid(&uid),
            uid,
            parents,
        })
    }

    pub(crate) fn from_principal(principal: &Principal) -> Self {
        let uid = principal.cedar_entity_uid().clone();
        let type_name = entity_type_name_from_uid(&uid);

        let parents = match principal {
            Principal::User(user) => {
                let mut parents = HashSet::with_capacity(user.groups().len());
                for group in user.groups() {
                    parents.insert(group.cedar_entity_uid().clone());
                }
                parents
            }
            Principal::Group(_) => {
                let mut parents = HashSet::new();
                // Cedar `in` includes equality for entities.
                parents.insert(uid.clone());
                parents
            }
        };

        Self {
            uid,
            type_name,
            parents,
        }
    }
}

#[derive(Debug)]
pub(crate) struct ResourceQuery {
    pub(crate) uid: EntityUid,
    pub(crate) type_name: EntityTypeName,
}

impl ResourceQuery {
    pub(crate) fn from_resource(resource: &Resource) -> Self {
        let uid = resource.cedar_entity_uid().clone();
        let type_name = uid.type_name().clone();
        Self { uid, type_name }
    }
}

#[derive(Debug)]
pub(crate) struct ActionQuery {
    pub(crate) uid: EntityUid,
}

impl ActionQuery {
    pub(crate) fn from_action(action: &Action) -> Self {
        Self {
            uid: action.cedar_entity_uid().clone(),
        }
    }
}

fn entity_type_name_from_uid(uid: &EntityUid) -> EntityTypeName {
    uid.type_name().clone()
}