treetop-core 0.0.16

Core library for Treetop, a Cedar policy engine implementation.
Documentation
use cedar_policy::{Effect, PrincipalConstraint, ResourceConstraint};

use crate::query::{PrincipalQuery, ResourceQuery};
use crate::types::{PolicyEffectFilter, PolicyMatchReason};

pub(crate) fn principal_match_reason(
    constraint: PrincipalConstraint,
    principal: &PrincipalQuery,
) -> Option<PolicyMatchReason> {
    match constraint {
        PrincipalConstraint::Eq(uid) if uid == principal.uid => {
            Some(PolicyMatchReason::PrincipalEq)
        }
        PrincipalConstraint::In(uid)
            if uid == principal.uid || principal.parents.contains(&uid) =>
        {
            Some(PolicyMatchReason::PrincipalIn)
        }
        PrincipalConstraint::Any => Some(PolicyMatchReason::PrincipalAny),
        PrincipalConstraint::Is(entity_type) if entity_type.to_string() == principal.type_name => {
            Some(PolicyMatchReason::PrincipalIs)
        }
        PrincipalConstraint::IsIn(entity_type, parent)
            if entity_type.to_string() == principal.type_name
                && (parent == principal.uid || principal.parents.contains(&parent)) =>
        {
            Some(PolicyMatchReason::PrincipalIsIn)
        }
        _ => None,
    }
}

pub(crate) fn resource_match_reason(
    constraint: ResourceConstraint,
    resource: Option<&ResourceQuery>,
) -> Option<Option<PolicyMatchReason>> {
    let Some(resource) = resource else {
        return Some(None);
    };

    match constraint {
        ResourceConstraint::Eq(uid) if uid == resource.uid => {
            Some(Some(PolicyMatchReason::ResourceEq))
        }
        ResourceConstraint::In(uid) if uid == resource.uid => {
            Some(Some(PolicyMatchReason::ResourceIn))
        }
        ResourceConstraint::Any => Some(Some(PolicyMatchReason::ResourceAny)),
        ResourceConstraint::Is(entity_type) if entity_type.to_string() == resource.type_name => {
            Some(Some(PolicyMatchReason::ResourceIs))
        }
        ResourceConstraint::IsIn(entity_type, parent)
            if entity_type.to_string() == resource.type_name && parent == resource.uid =>
        {
            Some(Some(PolicyMatchReason::ResourceIsIn))
        }
        _ => None,
    }
}

pub(crate) fn matches_effect(effect: Effect, filter: PolicyEffectFilter) -> bool {
    match filter {
        PolicyEffectFilter::Any => true,
        PolicyEffectFilter::Permit => effect == Effect::Permit,
        PolicyEffectFilter::Forbid => effect == Effect::Forbid,
    }
}