use evorule_reactor::IoCallContext;
use evorule_tcb::domain::evaluate_domain;
use evorule_tcb::JsonValue;
use super::entry::PermissionError;
#[derive(Debug, Clone, Copy, Default)]
pub struct ConditionEvaluator;
impl ConditionEvaluator {
pub fn evaluate(
&self,
conditions: &serde_json::Value,
ctx: &IoCallContext,
payload: &JsonValue,
) -> Result<bool, PermissionError> {
if conditions.is_null()
|| (conditions.is_object()
&& conditions.as_object().is_some_and(|o| o.is_empty()))
{
return Ok(true);
}
let domain = super::serde_to_tcb(conditions);
let exec_state = build_conditions_exec_state(ctx, payload);
evaluate_domain(&domain, &exec_state).map_err(|e| PermissionError::Condition(e.to_string()))
}
}
fn build_conditions_exec_state(ctx: &IoCallContext, payload: &JsonValue) -> JsonValue {
let mut exec = JsonValue::empty_object();
let mut exec_inner = JsonValue::empty_object();
let mut ctx_obj = JsonValue::empty_object();
if let Some(c) = ctx_obj.as_object_mut() {
c.insert("cause".to_string(), JsonValue::Integer(ctx.cause.0 as i64));
c.insert(
"v_trigger".to_string(),
JsonValue::Integer(ctx.v_trigger as i64),
);
c.insert(
"caller_role".to_string(),
JsonValue::string(ctx.caller_role.as_str()),
);
if let Some(tenant) = &ctx.tenant_id {
c.insert("tenant_id".to_string(), JsonValue::string(tenant.clone()));
}
}
if let Some(inner) = exec_inner.as_object_mut() {
inner.insert("ctx".to_string(), ctx_obj);
inner.insert("payload".to_string(), payload.clone());
}
if let Some(root) = exec.as_object_mut() {
root.insert("__exec__".to_string(), exec_inner);
}
exec
}