reifydb_engine/policy/
mod.rs1use std::sync::Arc;
5
6use reifydb_core::{
7 interface::catalog::policy::PolicyTargetType,
8 value::column::{columns::Columns, data::ColumnData},
9};
10use reifydb_policy::{
11 enforce::{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, EvalSession},
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_object: &str,
48 operation: &str,
49 row_columns: &Columns,
50 target_type: PolicyTargetType,
51 ) -> Result<()> {
52 enforce_write_policies(
53 &self.services.catalog,
54 tx,
55 target_namespace,
56 target_object,
57 operation,
58 row_columns,
59 target_type,
60 self,
61 )
62 }
63
64 pub fn enforce_session_policy(
65 &self,
66 tx: &mut Transaction<'_>,
67 session_type: &str,
68 default_deny: bool,
69 ) -> Result<()> {
70 enforce_session_policy(&self.services.catalog, tx, session_type, default_deny, self)
71 }
72
73 pub fn enforce_identity_policy(
74 &self,
75 tx: &mut Transaction<'_>,
76 target_namespace: &str,
77 target_object: &str,
78 operation: &str,
79 target_type: PolicyTargetType,
80 ) -> Result<()> {
81 enforce_identity_policy(
82 &self.services.catalog,
83 tx,
84 target_namespace,
85 target_object,
86 operation,
87 target_type,
88 self,
89 )
90 }
91}
92
93impl PolicyEvaluatorTrait for PolicyEvaluator<'_> {
94 fn evaluate_condition(
95 &self,
96 expr: &Expression,
97 columns: &Columns,
98 row_count: usize,
99 identity: IdentityId,
100 ) -> Result<bool> {
101 let compile_ctx = CompileContext {
102 functions: &self.services.functions,
103 symbols: self.symbols,
104 };
105 let compiled = compile_expression(&compile_ctx, expr)?;
106
107 let session = EvalSession {
108 params: &Params::None,
109 symbols: self.symbols,
110 functions: &self.services.functions,
111 runtime_context: &self.services.runtime_context,
112 arena: None,
113 identity,
114 is_aggregate_context: false,
115 };
116 let eval_ctx = session.eval(columns.clone(), row_count);
117
118 let result = compiled.execute(&eval_ctx)?;
119
120 let denied = match result.data() {
121 ColumnData::Bool(container) => {
122 (0..row_count).any(|i| !container.is_defined(i) || !container.data().get(i))
123 }
124 ColumnData::Option {
125 inner,
126 bitvec,
127 } => match inner.as_ref() {
128 ColumnData::Bool(container) => (0..row_count).any(|i| {
129 let defined = i < bitvec.len() && bitvec.get(i);
130 let valid = defined && container.is_defined(i);
131 !(valid && container.data().get(i))
132 }),
133 _ => true,
134 },
135 _ => true,
136 };
137
138 Ok(!denied)
139 }
140}