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