CoolCMS API

ResponseMarkReadTrait

Marks a response as read from an e-mail link, without login, using only the key stored on the response (column `read_key`, random, set by {@see self::generateReadKey()} in `beforeSave()` when the response is created).

The key is verified on the Api side in the receiver check of the response (ResponseReceiverTrait::isResponseReceiver(), key branch; the comparison is done by self::readKeyMatches()). The front presenter and the front layers do not check it; they only pass id and key from the URL. The RBAC key :Api:{Bazaar,Comcat}:Response:markReadByKey (guest = 1) allows access without identity, so security rests entirely on that check: without a valid key nothing is written (self::markRead() must not be called without it).

IMPORTANT: contract:

  • the action only switches read = 1; it returns nothing from the response or the advert,
  • an invalid key, a response without a key (older ones, no backfill), a missing response and a deleted response all return the same result (INVALID_KEY); otherwise the action would be an oracle for the existence of a response,
  • modules stay separated because each manager looks in its own response table (a Bazaar key does not work for a response with the same id in Comcat, and vice versa),
  • the key is not deleted after use: a valid key on an already read response is a success again, so the link can be opened repeatedly and shows the confirmation again.

Table of Contents

Methods

generateReadKey()  : string
24 random bytes = 48 hex characters (column `read_key` is `varchar(64)`).
markRead()  : Result
Writes `read = 1` after the presenter decided that the caller is the receiver ({@see \App\Core\Traits\Api\Presenters\ResponseReceiverTrait::isResponseReceiver()}).
readKeyMatches()  : bool
Tells whether the given key matches the stored one. A null or empty stored key (older responses) and an empty given key never match; the comparison runs in constant time.

Methods

generateReadKey()

24 random bytes = 48 hex characters (column `read_key` is `varchar(64)`).

public static generateReadKey() : string
Return values
string

markRead()

Writes `read = 1` after the presenter decided that the caller is the receiver ({@see \App\Core\Traits\Api\Presenters\ResponseReceiverTrait::isResponseReceiver()}).

public markRead(int $id) : Result

The manager decides nothing itself, so there is no second copy of the check. An already read response is a success again without another write; the key is not deleted.

Parameters
$id : int
Return values
Result

readKeyMatches()

Tells whether the given key matches the stored one. A null or empty stored key (older responses) and an empty given key never match; the comparison runs in constant time.

public static readKeyMatches(string|null $stored, string $given) : bool
Parameters
$stored : string|null
$given : string
Return values
bool
On this page

Search results