Audience
: string
in package
Audience of a field: who receives it (`read`), who may fill it in when creating (`insert`) and who may change it on an existing record (`update`).
Vocabulary for FieldAccess. The cases are not role codes: who is privileged or an owner
is stored in cms_system_user_roles (privileged, conditional), so a new role needs no
entity change.
All: anyone past the action guard.Authenticated: callers with an identity.Owner:isOwner()decides on the record.Privileged: roles withprivileged = 1.None: only the server sets the value.
NOTE: the audience is monotonic (Privileged sees what Owner sees) and has no inverse case;
masked or shortened values belong in a dedicated action (User:publicProfile).
NOTE: the audience does not replace the action key; the key decides who reaches the action,
the audience what the response contains.
Table of Contents
Cases
- All = 'all'
- Everyone who passed the action guard, as for an unannotated field.
- Authenticated = 'authenticated'
- Only callers with an identity (`userId > 0`); anonymous callers do not get the field.
- Internal = 'internal'
- IMPORTANT: valid on the `read` axis only. Only server code of the same process ({@see \App\Core\Bridge\ApiBridge}, front end and admin) receives the value; external HTTP never does, even for a privileged caller with a JWT.
- None = 'none'
- Nobody; the server alone sets the value, not even an admin sends it over the wire.
- Owner = 'owner'
- Only the record owner, decided by `isOwner()` (a SELECT), never by the payload.
- Privileged = 'privileged'
- Only a privileged caller (`cms_system_user_roles.privileged = 1`, currently `admin`).
Methods
- isRestricted() : bool
- Returns whether the audience is stricter than `All`; the emit path skips `All`.
Cases
All
Everyone who passed the action guard, as for an unannotated field.
Authenticated
Only callers with an identity (`userId > 0`); anonymous callers do not get the field.
Owner
Only the record owner, decided by `isOwner()` (a SELECT), never by the payload.
Privileged
Only a privileged caller (`cms_system_user_roles.privileged = 1`, currently `admin`).
None
Nobody; the server alone sets the value, not even an admin sends it over the wire.
On insert/update it equals ExternalReadonly (insertUserId, views, approvedAt).
On read the value never leaves the Api layer, for fields even an admin does not need
(password, salt: an admin sets the password but never reads the hash).
Internal
IMPORTANT: valid on the `read` axis only. Only server code of the same process ({@see \App\Core\Bridge\ApiBridge}, front end and admin) receives the value; external HTTP never does, even for a privileged caller with a JWT.
It differs from None because front-end code needs values such as Advert::$password,
the activation key or read_key, and a front-end save of the whole entity would
otherwise overwrite the DB value with an empty one.
NOTE: it is the only case outside the monotonic role axis. The transport decides, from
framework state (see ApiPermissionGuardTrait).
FieldAccessCoverageTest rejects it on insert/update.
Methods
isRestricted()
Returns whether the audience is stricter than `All`; the emit path skips `All`.
public
isRestricted() : bool