Oihana PHP Arango

isPathAuthorized.php

Table of Contents

Functions

isPathAuthorized()  : bool
Decides whether a *dotted* query attribute (a filter / facet / group path) is allowed for the current request, by inheriting the projection permission of the **exact sub-field** it targets — not only its root.

Functions

isPathAuthorized()

Decides whether a *dotted* query attribute (a filter / facet / group path) is allowed for the current request, by inheriting the projection permission of the **exact sub-field** it targets — not only its root.

isPathAuthorized(string $path, array<string|int, mixed>|null $fields[, array<string|int, mixed> $init = [] ]) : bool

This is the depth-aware counterpart of isAttributeAuthorized(): instead of gating explode('.', $path)[0] (the root only), it walks the whole path segment by segment, descending through the sub-fields of the structural fields (Field::FIELDS, or the per-skin buckets AQL::SKIN_FIELDS) and reading the optional Field::REQUIRES at every level. A single locked level anywhere on the path denies the whole path — « what you cannot read, you cannot query on ».

The decision at each level is deferred to the shared isAuthorized() gate (backend-agnostic closure injected through $init[Arango::AUTHORIZER]), so the semantics (OR over the subjects list, fail-open when no authorizer is injected) match the field-level gate exactly.

Resolution rules (aligned on isAttributeAuthorized(), extended in depth) :

  • $fields is not an array → true (nothing to inherit, no gating).
  • A segment is absent from the current field map(s), or only declared as a scalar / bool definition → true (no Field::REQUIRES to inherit here).
  • A segment carries a Field::REQUIRES refused by the authorizer → false.
  • Otherwise the walk descends into the sub-fields and continues; a path with no deeper declared sub-fields resolves to true.

Sub-fields resolution (fail-closed union). A structural field can declare its sub-fields under Field::FIELDS and / or under per-skin buckets AQL::SKIN_FIELDS. Because a Field::REQUIRES is a permission (independent of the projection skin), the descent gathers the sub-field from every source and treats it as locked as soon as it is locked in any one of them — a sub-field hidden in a single skin bucket stays gated on every path.

A single-segment path behaves exactly like isAttributeAuthorized() — it is its degenerate case. Each segment is stripped of the [*] array-expansion marker, so the same helper serves the hierarchical filter leaves.

Parameters
$path : string

The dotted public attribute path (e.g. address.city, employee[*].salary).

$fields : array<string|int, mixed>|null

The model projection map ($this->fields), keyed by field name.

$init : array<string|int, mixed> = []

The request-level init array. Reads Arango::AUTHORIZER.

Tags
example
$fields =
[
    'address' =>
    [
        Field::FILTER => Filter::DOCUMENT ,
        Field::FIELDS => [ 'city' => [ Field::REQUIRES => 'geo:read' ] ] ,
    ] ,
] ;
isPathAuthorized( 'address.city' , $fields , [ Arango::AUTHORIZER => fn() => false ] ) ; // false
isPathAuthorized( 'address.zip'  , $fields , [ Arango::AUTHORIZER => fn() => false ] ) ; // true (undeclared → ungated)
author

Marc Alcaraz (eKameleon)

since
1.0.0
Return values
bool

true when every level of the path is authorized, false as soon as one level is refused.

On this page

Search results