CoolCMS API

AdvertScopeGuardTrait

Single definition of the rule "may this caller see the data of one advert?".

Used by the response tab and the statistics tab of the advert edit page, in two modules, so four presenters. If the rule lived in each of them, the four copies would drift apart.

A caller is allowed for any of three independent reasons, checked cheapest first:

  • a privileged role (isGrantedByPrivilegedRole() reads an in-memory map, so an admin costs no extra SELECT);
  • classic ownership: insertUserId of the advert loaded from the DB equals jwt.userId;
  • a capability: the token carries a valid claim for this advertId, with the right scope and a password fingerprint equal to the hash in the DB (JwtCapability::grants()).

IMPORTANT: $advertId from the request is only the caller's claim of which advert, never proof of ownership. Proof comes from comparing against the entity loaded from the DB by that id; a foreign advertId yields false and the caller returns an empty collection.

Password-based advert editing runs without identity (jwt.userId is 0, a guest). Ownership is proven by a capability claim issued by CapabilityTokenIssuer only after the front session passed against the password hash in the DB. The fingerprint is compared again against the DB, so a password change by the owner invalidates access immediately.

Table of Contents

Methods

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`).
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.

Methods

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

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
On this page

Search results