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::{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, 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_shape: &str,
48 operation: &str,
49 row_columns: &Columns,
50 target_type: PolicyTargetType,
51 ) -> Result<()> {
52 let target = PolicyTarget {
53 namespace: target_namespace,
54 shape: target_shape,
55 operation,
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: &str,
65 default_deny: bool,
66 ) -> Result<()> {
67 enforce_session_policy(&self.services.catalog, tx, session_type, 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: &str,
76 target_type: PolicyTargetType,
77 ) -> Result<()> {
78 let target = PolicyTarget {
79 namespace: target_namespace,
80 shape: target_shape,
81 operation,
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 functions: &self.services.functions,
98 symbols: self.symbols,
99 };
100 let compiled = compile_expression(&compile_ctx, expr)?;
101
102 let session = EvalSession {
103 params: &Params::None,
104 symbols: self.symbols,
105 functions: &self.services.functions,
106 runtime_context: &self.services.runtime_context,
107 arena: None,
108 identity,
109 is_aggregate_context: false,
110 };
111 let eval_ctx = session.eval(columns.clone(), row_count);
112
113 let result = compiled.execute(&eval_ctx)?;
114
115 let denied = match result.data() {
116 ColumnData::Bool(container) => {
117 (0..row_count).any(|i| !container.is_defined(i) || !container.data().get(i))
118 }
119 ColumnData::Option {
120 inner,
121 bitvec,
122 } => match inner.as_ref() {
123 ColumnData::Bool(container) => (0..row_count).any(|i| {
124 let defined = i < bitvec.len() && bitvec.get(i);
125 let valid = defined && container.is_defined(i);
126 !(valid && container.data().get(i))
127 }),
128 _ => true,
129 },
130 _ => true,
131 };
132
133 Ok(!denied)
134 }
135}