← back to Animals

migrations/013_email_verification.sql

32 lines

-- Project: Animals — email verification tokens.
--
-- Wires a "click the link in your inbox before you can post listings or send
-- friend requests" gate. Token is generated at signup, emailed via George,
-- consumed (cleared) when the user clicks /auth/verify?token=.
--
-- Grandfathering: every existing app_users row gets email_verified_at = created_at
-- and email_verified = TRUE so we don't lock out anyone who signed up before
-- the gate existed. The boolean stays in sync with the timestamp — boolean is
-- the cheap predicate, timestamp is the audit trail.

BEGIN;

ALTER TABLE app_users
  ADD COLUMN IF NOT EXISTS email_verification_token   TEXT,
  ADD COLUMN IF NOT EXISTS email_verification_sent_at TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS email_verified_at          TIMESTAMPTZ;

-- Tokens are random opaque strings — must be unique while live (NULL after consumption).
CREATE UNIQUE INDEX IF NOT EXISTS idx_app_users_verification_token
  ON app_users (email_verification_token)
  WHERE email_verification_token IS NOT NULL;

-- Grandfather every pre-existing user. After this migration, only NEW signups
-- (post-deploy) will have email_verified_at = NULL.
UPDATE app_users
   SET email_verified_at = created_at,
       email_verified    = TRUE
 WHERE email_verified_at IS NULL;

COMMIT;