KemalIdentity::Postgres::ActionTokenRepository
Inherits KemalIdentity::Accounts::ActionTokenRepository < Reference < Object
Accounts::ActionTokenRepository over auth_action_tokens.
The interesting method is #consume, and what makes it correct is that it is a single
conditional UPDATE ... RETURNING rather than a SELECT followed by an UPDATE. Two
concurrent requests presenting the same reset link both reach the statement; PostgreSQL
serialises them on the row, the second finds used_at IS NULL no longer true, and updates
nothing. Exactly one gets a row back.
Written as a read-then-write it would be a race with an account takeover at the end of it.
Constants
Constructors
Instance methods
Spends the token with this digest, for this purpose, and returns it — or nil.
Atomic: exactly one of any number of concurrent callers gets the token back.
purpose is part of the condition, not a label checked afterwards. A token issued to
confirm an email address must not be redeemable to reset a password, or anybody able to
trigger a confirmation message gets an account takeover.
Returns nil for expired, already used, wrong purpose, and unknown alike.
Stores a newly issued token.
Raises KemalIdentity::InfrastructureError if the digest is already present. As with
sessions, the unique index exists so that a collision is a loud error rather than two
grants sharing a secret.
Deletes rows past their expiry, returning the count.
Disk reclamation only. Correctness never depends on it: expiry is evaluated inside
#consume.
Marks every outstanding token of this purpose for this account as used, returning how many it spent.
Issuing a new reset link invalidates the previous ones, so a link sitting in an old email — or in an inbox somebody else now controls — stops working. Also the right response to a completed password change.