reifydb_engine/policy/
mod.rs1use std::sync::Arc;
9
10use reifydb_core::{
11 interface::catalog::policy::{CallableOp, DataOp, PolicyTargetType, SessionOp},
12 value::column::{buffer::ColumnBuffer, columns::Columns},
13};
14use reifydb_evaluate::{
15 expression::{
16 compile::compile_expression,
17 context::{CompileContext, EvalContext},
18 },
19 stack::SymbolTable,
20};
21use reifydb_policy::{
22 enforce::{PolicyTarget, enforce_identity_policy, enforce_session_policy, enforce_write_policies},
23 evaluate::PolicyEvaluator as PolicyEvaluatorTrait,
24};
25use reifydb_rql::expression::Expression;
26use reifydb_transaction::transaction::Transaction;
27use reifydb_value::{Result, params::Params, value::identity::IdentityId};
28
29use crate::vm::services::Services;
30
31pub struct PolicyEvaluator<'a> {
32 services: &'a Arc<Services>,
33 symbols: &'a SymbolTable,
34}
35
36impl<'a> PolicyEvaluator<'a> {
37 pub fn new(services: &'a Arc<Services>, symbols: &'a SymbolTable) -> Self {
38 Self {
39 services,
40 symbols,
41 }
42 }
43
44 pub fn enforce_write_policies(
45 &self,
46 tx: &mut Transaction<'_>,
47 target_namespace: &str,
48 target_object: &str,
49 operation: DataOp,
50 row_columns: &Columns,
51 target_type: PolicyTargetType,
52 ) -> Result<()> {
53 let target = PolicyTarget {
54 namespace: target_namespace,
55 object: target_object,
56 operation: operation.as_str(),
57 target_type,
58 };
59 enforce_write_policies(&self.services.catalog, tx, &target, row_columns, self)
60 }
61
62 pub fn enforce_session_policy(
63 &self,
64 tx: &mut Transaction<'_>,
65 session_type: SessionOp,
66 default_deny: bool,
67 ) -> Result<()> {
68 enforce_session_policy(&self.services.catalog, tx, session_type.as_str(), default_deny, self)
69 }
70
71 pub fn enforce_identity_policy(
72 &self,
73 tx: &mut Transaction<'_>,
74 target_namespace: &str,
75 target_object: &str,
76 operation: CallableOp,
77 target_type: PolicyTargetType,
78 ) -> Result<()> {
79 let target = PolicyTarget {
80 namespace: target_namespace,
81 object: target_object,
82 operation: operation.as_str(),
83 target_type,
84 };
85 enforce_identity_policy(&self.services.catalog, tx, &target, self)
86 }
87}
88
89impl PolicyEvaluatorTrait for PolicyEvaluator<'_> {
90 fn evaluate_condition(
91 &self,
92 expr: &Expression,
93 columns: &Columns,
94 row_count: usize,
95 identity: IdentityId,
96 ) -> Result<bool> {
97 let compile_ctx = CompileContext {
98 symbols: self.symbols,
99 };
100 let compiled = compile_expression(&compile_ctx, expr)?;
101
102 let base = EvalContext {
103 params: &Params::None,
104 symbols: self.symbols,
105 routines: &self.services.routines,
106 runtime_context: &self.services.runtime_context,
107 identity,
108 is_aggregate_context: false,
109 columns: Columns::empty(),
110 row_count: 1,
111 target: None,
112 take: None,
113 };
114 let eval_ctx = base.with_eval(columns.clone(), row_count);
115
116 let result = compiled.execute(&eval_ctx)?;
117
118 let denied = match result.data() {
119 ColumnBuffer::Bool(container) => {
120 (0..row_count).any(|i| !container.is_defined(i) || !container.data().get(i))
121 }
122 ColumnBuffer::Option {
123 inner,
124 bitvec,
125 } => match inner.as_ref() {
126 ColumnBuffer::Bool(container) => (0..row_count).any(|i| {
127 let defined = i < bitvec.len() && bitvec.get(i);
128 let valid = defined && container.is_defined(i);
129 !(valid && container.data().get(i))
130 }),
131 _ => true,
132 },
133 _ => true,
134 };
135
136 Ok(!denied)
137 }
138}