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