CoolCMS API

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:

  • advertId given and allowed: the server injects advertId = <verified> (response and statistics tabs on the advert edit page);
  • advertId missing and advertScopeOwnerField() 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
bool

advertScopeCapability()

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
string

advertScopeOwnerField()

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|null

advertScopePrivilegeKey()

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
string

loadScopedAdvert()

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|null

resolveScopeFilter()

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
Return values
EqualFilter|null
On this page

Search results