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