use cedar_policy::Effect;
use cedar_policy_core::ast::{Policy, PolicySet};
use crate::symcc::{
compiler::compile,
env::SymEnv,
factory::{and, any_true, eq, not, some_of},
result::CompileError,
term::Term,
};
pub fn satisfied_with_effect(
effect: Effect,
policy: &Policy,
env: &SymEnv,
) -> Result<Option<Term>, CompileError> {
if policy.effect() == effect {
Ok(Some(compile(&policy.condition(), env)?))
} else {
Ok(None)
}
}
pub fn satisfied_policies(
effect: Effect,
policies: &PolicySet,
env: &SymEnv,
) -> Result<Term, CompileError> {
let terms = policies
.policies()
.filter_map(|p| satisfied_with_effect(effect, p, env).transpose())
.collect::<Result<Vec<Term>, CompileError>>()?;
Ok(any_true(|t: Term| eq(t, some_of(true.into())), terms))
}
pub fn is_authorized(policies: &PolicySet, env: &SymEnv) -> Result<Term, CompileError> {
let forbids = satisfied_policies(Effect::Forbid, policies, env)?;
let permits = satisfied_policies(Effect::Permit, policies, env)?;
Ok(and(permits, not(forbids)))
}