AdvertScopedListTrait uses trait:short
Dedicated `myList` collection action for collections bound to one advert.
Sibling of OwnedListTrait, but "mine" here means "belonging to the advert the
caller proved access to", not "userId matches". The advert edit page is also available
anonymously with a password, so a userId-scoped myList could not serve it.
The decision is made solely by AdvertScopeGuardTrait::advertScopeAllows().
$advertId from the request only says which advert, it is not proof.
Modes:
advertIdgiven and allowed: the server injectsadvertId = <verified>(response and statistics tabs on the advert edit page);advertIdmissing andadvertScopeOwnerField()set: the server injects<field> = jwt.userId(responses to all of my adverts);- anything else: an empty collection, without a DB query.
AdvertStatistics has no second mode: AdvertStatistic carries only a scalar
advertId, no association to the advert, so the filter cannot express it.
IMPORTANT: never add an actionMyList(). Without it Nette rejects an external request
with 404; the guest = 1 grant this action needs for the anonymous editor would
otherwise open it externally. Guarded by
FrontApiSurfacePolicyTest::testInternalOnlyKeysHaveNoActionCounterpart().
Table of Contents
Methods
- internalActionMyList() : array<string, mixed>
- advertScopeAllows() : bool
- Returns true when the caller may see the data of advert `$advertId`.
- advertScopeCapability() : string
- Capability scope of this module (`bazaar.advert.edit` or `comcat.advert.edit`).
- advertScopeOwnerField() : string|null
- Field to filter by when the caller did not send `advertId`, typically `advert.insertUserId`. `null` disables the second mode (fail-closed).
- advertScopePrivilegeKey() : string
- Privilege key to ask the privileged role about: always `getAll` of this presenter, i.e. "may the caller read this collection without restriction?".
- loadScopedAdvert() : object|null
- Loads the advert from the DB by id; returns `null` when it does not exist.
- resolveScopeFilter() : EqualFilter|null
- Returns the server-side scope filter, or `null` meaning "return nothing".
Methods
internalActionMyList()
public
internalActionMyList([int|null $advertId = null ][, array<string|int, Filter|array<string, mixed>> $filters = [] ][, array<string, mixed>|null $orderBys = null ][, int|null $offset = null ][, int|null $limit = null ][, array<int, string>|null $columns = null ][, bool $computeTotalCount = false ][, string|array<int, string> $includes = [] ]) : array<string, mixed>
Parameters
- $advertId : int|null = null
-
the caller's claim of which advert, never proof of ownership
- $filters : array<string|int, Filter|array<string, mixed>> = []
-
the caller's filters; they may only narrow the result
- $orderBys : array<string, mixed>|null = null
- $offset : int|null = null
- $limit : int|null = null
- $columns : array<int, string>|null = null
- $computeTotalCount : bool = false
- $includes : string|array<int, string> = []
Return values
array<string, mixed> —extractAll payload, or the guard's rejection
advertScopeAllows()
Returns true when the caller may see the data of advert `$advertId`.
protected
advertScopeAllows(int|null $advertId) : bool
Fail-closed on every axis: a missing or non-positive id, a nonexistent advert, a
foreign owner and an invalid capability all end in false.
Parameters
- $advertId : int|null
Return values
booladvertScopeCapability()
Capability scope of this module (`bazaar.advert.edit` or `comcat.advert.edit`).
protected
abstract advertScopeCapability() : string
Without the distinction a capability for Bazaar advert 5 would unlock company 5.
Return values
stringadvertScopeOwnerField()
Field to filter by when the caller did not send `advertId`, typically `advert.insertUserId`. `null` disables the second mode (fail-closed).
protected
advertScopeOwnerField() : string|null
Return values
string|nulladvertScopePrivilegeKey()
Privilege key to ask the privileged role about: always `getAll` of this presenter, i.e. "may the caller read this collection without restriction?".
protected
abstract advertScopePrivilegeKey() : string
Return values
stringloadScopedAdvert()
Loads the advert from the DB by id; returns `null` when it does not exist.
protected
abstract loadScopedAdvert(int $advertId) : object|null
IMPORTANT: never build the entity from request data; the ownership decision relies on DB state.
The return type is ?object on purpose: both shared classes are generic, so a union
would need seven type parameters. instanceof in self::advertScopeAllows()
narrows it and is fail-closed: anything other than an advert or company means false.
Parameters
- $advertId : int
Return values
object|nullresolveScopeFilter()
Returns the server-side scope filter, or `null` meaning "return nothing".
private
resolveScopeFilter(int|null $advertId) : EqualFilter|null
IMPORTANT: this return value is the only place that decides the collection scope; the caller cannot influence it.
Parameters
- $advertId : int|null