PhoenixKit.Migrations.Postgres.V197 (phoenix_kit v2.41.0)

Copy Markdown View Source

V197: Failed sign-in attempts.

phoenix_kit_login_attempts records sign-ins that did NOT succeed. Until now a wrong password produced a flash and nothing else: no activity entry, no row, nothing either the targeted account holder or the site owner could ever see. The only trace was Hammer's in-memory counter, which is node-local, lost on restart, and only says anything once a bucket overflows.

Rows are aggregated at write time rather than one-per-attempt. The unique index is the dedup key, and the write is a single INSERT ... ON CONFLICT DO UPDATE SET attempt_count = attempt_count + 1 — no read, no lock contention, and a brute-force run against one account from one network collapses into one row per hour instead of thousands.

bucket_start is that hour, truncated by the caller (PhoenixKit.Users.LoginAttempts) rather than by a database default, so the value written and the value conflicted on are always the same one.

identifier is what the person typed, normalized and truncated to 160 characters — the same cap PhoenixKitWeb.Users.Session already applies before echoing it back into a flash. It is attacker-controlled text and must be treated as such by anything that renders it.

user_uuid is NULL when the identifier matched no account, and the FK is ON DELETE CASCADE so deleting a user takes their attempt history with them. It is deliberately NOT part of the dedup key: NULL never equals NULL in a unique index, so keying on it would silently stop deduplicating for exactly the rows an attacker generates most of.

Summary

Functions

down(opts)

up(opts)