(
left: &PredicateValue,
right: &PredicateValue,
auth: &AuthContext,
)
| 262 | } |
| 263 | |
| 264 | fn substitute_intersects( |
| 265 | left: &PredicateValue, |
| 266 | right: &PredicateValue, |
| 267 | auth: &AuthContext, |
| 268 | ) -> Option<Vec<ScanFilter>> { |
| 269 | match (left, right) { |
| 270 | // doc_field INTERSECTS $auth.groups → "any_in" operator. |
| 271 | (PredicateValue::Field(doc_field), PredicateValue::AuthRef(auth_field)) |
| 272 | | (PredicateValue::AuthRef(auth_field), PredicateValue::Field(doc_field)) => { |
| 273 | let auth_val = auth.resolve_variable(auth_field)?; |
| 274 | Some(vec![ScanFilter { |
| 275 | field: doc_field.clone(), |
| 276 | op: "any_in".into(), |
| 277 | value: nodedb_types::Value::from(auth_val), |
| 278 | clauses: Vec::new(), |
| 279 | expr: None, |
| 280 | }]) |
| 281 | } |
| 282 | |
| 283 | // doc_field INTERSECTS $auth.scope_status('pro:all') → "any_in" operator. |
| 284 | (PredicateValue::Field(doc_field), PredicateValue::AuthFunc { .. }) => { |
| 285 | let auth_val = right.resolve(auth)?; |
| 286 | Some(vec![ScanFilter { |
| 287 | field: doc_field.clone(), |
| 288 | op: "any_in".into(), |
| 289 | value: nodedb_types::Value::from(auth_val), |
| 290 | clauses: Vec::new(), |
| 291 | expr: None, |
| 292 | }]) |
| 293 | } |
| 294 | (PredicateValue::AuthFunc { .. }, PredicateValue::Field(doc_field)) => { |
| 295 | let auth_val = left.resolve(auth)?; |
| 296 | Some(vec![ScanFilter { |
| 297 | field: doc_field.clone(), |
| 298 | op: "any_in".into(), |
| 299 | value: nodedb_types::Value::from(auth_val), |
| 300 | clauses: Vec::new(), |
| 301 | expr: None, |
| 302 | }]) |
| 303 | } |
| 304 | |
| 305 | // $auth.groups INTERSECTS $auth.allowed → plan-time evaluation. |
| 306 | (PredicateValue::AuthRef(left_field), PredicateValue::AuthRef(right_field)) => { |
| 307 | let left_val = auth.resolve_variable(left_field)?; |
| 308 | let right_val = auth.resolve_variable(right_field)?; |
| 309 | let intersects = if let (Some(l), Some(r)) = (left_val.as_array(), right_val.as_array()) |
| 310 | { |
| 311 | l.iter().any(|v| r.contains(v)) |
| 312 | } else { |
| 313 | false |
| 314 | }; |
| 315 | |
| 316 | if intersects { |
| 317 | Some(vec![ScanFilter { |
| 318 | field: String::new(), |
| 319 | op: "match_all".into(), |
| 320 | value: nodedb_types::Value::Null, |
| 321 | clauses: Vec::new(), |
no test coverage detected