1use 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, EvalContext},
22 },
23 vm::{services::Services, stack::SymbolTable},
24};
25
26pub struct PolicyEvaluator<'a> {
31 services: &'a Arc<Services>,
32 symbol_table: &'a SymbolTable,
33}
34
35impl<'a> PolicyEvaluator<'a> {
36 pub fn new(services: &'a Arc<Services>, symbol_table: &'a SymbolTable) -> Self {
37 Self {
38 services,
39 symbol_table,
40 }
41 }
42
43 pub fn enforce_write_policies(
44 &self,
45 tx: &mut Transaction<'_>,
46 identity: IdentityId,
47 target_namespace: &str,
48 target_object: &str,
49 operation: &str,
50 row_columns: &Columns,
51 target_type: PolicyTargetType,
52 ) -> Result<()> {
53 enforce_write_policies(
54 &self.services.catalog,
55 tx,
56 identity,
57 target_namespace,
58 target_object,
59 operation,
60 row_columns,
61 target_type,
62 self,
63 )
64 }
65
66 pub fn enforce_session_policy(
67 &self,
68 tx: &mut Transaction<'_>,
69 identity: IdentityId,
70 session_type: &str,
71 default_deny: bool,
72 ) -> Result<()> {
73 enforce_session_policy(&self.services.catalog, tx, identity, session_type, default_deny, self)
74 }
75
76 pub fn enforce_identity_policy(
77 &self,
78 tx: &mut Transaction<'_>,
79 identity: IdentityId,
80 target_namespace: &str,
81 target_object: &str,
82 operation: &str,
83 target_type: PolicyTargetType,
84 ) -> Result<()> {
85 enforce_identity_policy(
86 &self.services.catalog,
87 tx,
88 identity,
89 target_namespace,
90 target_object,
91 operation,
92 target_type,
93 self,
94 )
95 }
96}
97
98impl PolicyEvaluatorTrait for PolicyEvaluator<'_> {
99 fn evaluate_condition(
100 &self,
101 expr: &Expression,
102 columns: &Columns,
103 row_count: usize,
104 identity: IdentityId,
105 ) -> Result<bool> {
106 let compile_ctx = CompileContext {
107 functions: &self.services.functions,
108 symbol_table: self.symbol_table,
109 };
110 let compiled = compile_expression(&compile_ctx, expr)?;
111
112 let eval_ctx = EvalContext {
113 target: None,
114 columns: columns.clone(),
115 row_count,
116 take: None,
117 params: &Params::None,
118 symbol_table: self.symbol_table,
119 is_aggregate_context: false,
120 functions: &self.services.functions,
121 clock: &self.services.clock,
122 arena: None,
123 identity,
124 };
125
126 let result = compiled.execute(&eval_ctx)?;
127
128 let denied = match result.data() {
129 ColumnData::Bool(container) => {
130 (0..row_count).any(|i| !container.is_defined(i) || !container.data().get(i))
131 }
132 ColumnData::Option {
133 inner,
134 bitvec,
135 } => match inner.as_ref() {
136 ColumnData::Bool(container) => (0..row_count).any(|i| {
137 let defined = i < bitvec.len() && bitvec.get(i);
138 let valid = defined && container.is_defined(i);
139 !(valid && container.data().get(i))
140 }),
141 _ => true,
142 },
143 _ => true,
144 };
145
146 Ok(!denied)
147 }
148}