MySQL · 1612 bytes Raw Blame History
1 -- SPDX-License-Identifier: AGPL-3.0-or-later
2 --
3 -- User email addresses. Users can have multiple emails; exactly one is
4 -- the primary at any time (enforced by a partial unique index).
5 -- email is citext + globally unique across all users (an email address
6 -- can belong to at most one shithub account).
7
8 -- +goose Up
9 CREATE TABLE user_emails (
10 id bigserial PRIMARY KEY,
11 user_id bigint NOT NULL REFERENCES users(id) ON DELETE CASCADE,
12 email citext NOT NULL UNIQUE,
13 is_primary boolean NOT NULL DEFAULT false,
14 verified boolean NOT NULL DEFAULT false,
15 verification_token_hash bytea,
16 verification_sent_at timestamptz,
17 verified_at timestamptz,
18 created_at timestamptz NOT NULL DEFAULT now(),
19
20 CONSTRAINT user_emails_email_length CHECK (char_length(email::text) BETWEEN 3 AND 254),
21 CONSTRAINT user_emails_email_shape CHECK (email::text LIKE '%@%')
22 );
23
24 -- At most one primary email per user.
25 CREATE UNIQUE INDEX user_emails_one_primary_per_user
26 ON user_emails (user_id) WHERE is_primary;
27
28 CREATE INDEX user_emails_user_id_idx ON user_emails (user_id);
29
30 -- Now that user_emails exists, attach the FK from users.primary_email_id.
31 ALTER TABLE users
32 ADD CONSTRAINT users_primary_email_fk
33 FOREIGN KEY (primary_email_id) REFERENCES user_emails(id)
34 ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
35
36 -- +goose Down
37 ALTER TABLE users DROP CONSTRAINT IF EXISTS users_primary_email_fk;
38 DROP TABLE IF EXISTS user_emails;
39