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, 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: &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 base = EvalContext {
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 columns: Columns::empty(),
111 row_count: 1,
112 target: None,
113 take: None,
114 };
115 let eval_ctx = base.with_eval(columns.clone(), row_count);
116
117 let result = compiled.execute(&eval_ctx)?;
118
119 let denied = match result.data() {
120 ColumnData::Bool(container) => {
121 (0..row_count).any(|i| !container.is_defined(i) || !container.data().get(i))
122 }
123 ColumnData::Option {
124 inner,
125 bitvec,
126 } => match inner.as_ref() {
127 ColumnData::Bool(container) => (0..row_count).any(|i| {
128 let defined = i < bitvec.len() && bitvec.get(i);
129 let valid = defined && container.is_defined(i);
130 !(valid && container.data().get(i))
131 }),
132 _ => true,
133 },
134 _ => true,
135 };
136
137 Ok(!denied)
138 }
139}