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_policy::{
11 enforce::{PolicyTarget, enforce_identity_policy, enforce_session_policy, enforce_write_policies},
12 evaluate::PolicyEvaluator as PolicyEvaluatorTrait,
13};
14use reifydb_rql::expression::Expression;
15use reifydb_transaction::transaction::Transaction;
16use reifydb_type::{Result, params::Params, value::identity::IdentityId};
17
18use crate::{
19 expression::{
20 compile::compile_expression,
21 context::{CompileContext, EvalContext},
22 },
23 vm::{services::Services, stack::SymbolTable},
24};
25
26pub struct PolicyEvaluator<'a> {
31 services: &'a Arc<Services>,
32 symbols: &'a SymbolTable,
33}
34
35impl<'a> PolicyEvaluator<'a> {
36 pub fn new(services: &'a Arc<Services>, symbols: &'a SymbolTable) -> Self {
37 Self {
38 services,
39 symbols,
40 }
41 }
42
43 pub fn enforce_write_policies(
44 &self,
45 tx: &mut Transaction<'_>,
46 target_namespace: &str,
47 target_shape: &str,
48 operation: DataOp,
49 row_columns: &Columns,
50 target_type: PolicyTargetType,
51 ) -> Result<()> {
52 let target = PolicyTarget {
53 namespace: target_namespace,
54 shape: target_shape,
55 operation: operation.as_str(),
56 target_type,
57 };
58 enforce_write_policies(&self.services.catalog, tx, &target, row_columns, self)
59 }
60
61 pub fn enforce_session_policy(
62 &self,
63 tx: &mut Transaction<'_>,
64 session_type: SessionOp,
65 default_deny: bool,
66 ) -> Result<()> {
67 enforce_session_policy(&self.services.catalog, tx, session_type.as_str(), default_deny, self)
68 }
69
70 pub fn enforce_identity_policy(
71 &self,
72 tx: &mut Transaction<'_>,
73 target_namespace: &str,
74 target_shape: &str,
75 operation: CallableOp,
76 target_type: PolicyTargetType,
77 ) -> Result<()> {
78 let target = PolicyTarget {
79 namespace: target_namespace,
80 shape: target_shape,
81 operation: operation.as_str(),
82 target_type,
83 };
84 enforce_identity_policy(&self.services.catalog, tx, &target, self)
85 }
86}
87
88impl PolicyEvaluatorTrait for PolicyEvaluator<'_> {
89 fn evaluate_condition(
90 &self,
91 expr: &Expression,
92 columns: &Columns,
93 row_count: usize,
94 identity: IdentityId,
95 ) -> Result<bool> {
96 let compile_ctx = CompileContext {
97 symbols: self.symbols,
98 };
99 let compiled = compile_expression(&compile_ctx, expr)?;
100
101 let base = EvalContext {
102 params: &Params::None,
103 symbols: self.symbols,
104 routines: &self.services.routines,
105 runtime_context: &self.services.runtime_context,
106 arena: None,
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}