use std::sync::Arc;
use anyhow::{Result, bail};
use typesec_core::policy::{PolicyEngine, PolicyResult, RequestContext};
pub fn detect_format(explicit: &Option<String>, yaml: &str) -> Option<String> {
if let Some(f) = explicit {
return Some(f.clone());
}
if yaml.contains("graph_policy:") || yaml.contains("\"graph_policy\"") {
Some("graph".into())
} else if yaml.contains("roles:") {
Some("rbac".into())
} else if yaml.contains("policies:") {
Some("odrl".into())
} else {
None
}
}
pub fn load_engine(format: Option<&str>, yaml: &str) -> Result<Arc<dyn PolicyEngine>> {
match format {
Some("rbac") => Ok(Arc::new(
typesec_rbac::RbacEngine::from_yaml(yaml).map_err(|e| anyhow::anyhow!(e))?,
)),
Some("odrl") => Ok(Arc::new(
typesec_odrl::OdrlEngine::from_yaml(yaml).map_err(|e| anyhow::anyhow!(e))?,
)),
Some("graph") => Ok(Arc::new(
typesec_rbac::GraphPolicyEngine::from_yaml(yaml).map_err(|e| anyhow::anyhow!(e))?,
)),
_ => bail!(
"Could not detect policy format. Use --format rbac, --format odrl, or --format graph"
),
}
}
pub fn request_context(purpose: Option<&str>) -> RequestContext {
purpose.map_or_else(RequestContext::default, |p| {
RequestContext::default().with_purpose(p)
})
}
pub fn code_for_result(result: &PolicyResult) -> i32 {
match result {
PolicyResult::Allow => 0,
PolicyResult::Deny(_) => 1,
PolicyResult::Delegate(_) => 2,
_ => 1,
}
}
pub fn exit_for_result(result: &PolicyResult) -> ! {
std::process::exit(code_for_result(result))
}
#[cfg(test)]
mod tests;