d5b4bba018
Re-apply the deeplink backend deferred out of PR1a: migration 00006 adds email_confirmations.purpose + link_token_hash (hand-edited jet), each issued code now carries an opaque 256-bit token (only its SHA-256 stored), and ConfirmByToken resolves a token to a login (confirm + clear guest) or a link (attach when free, signal merge when owned elsewhere). issueCode now embeds the /app/#/confirm/<token> link in the email. The confirm endpoint, gateway RPC and SPA route follow.
28 lines
1.4 KiB
SQL
28 lines
1.4 KiB
SQL
-- Add the confirm deeplink token and the confirmation purpose to email_confirmations.
|
|
-- purpose tags what verifying the code/token does (email login, identity link, email
|
|
-- change, or account deletion); link_token_hash holds the SHA-256 hex of the one-click
|
|
-- deeplink token (only the hash is stored, mirroring the session-token model).
|
|
-- Expand-contract: both columns are additive. purpose gets a NOT NULL DEFAULT so
|
|
-- existing rows fill in; link_token_hash is nullable with a partial-unique index. A
|
|
-- backend image rollback stays DB-safe — older code simply ignores the new columns. The
|
|
-- table shape changes, so the generated go-jet model for this table is regenerated.
|
|
|
|
-- +goose Up
|
|
ALTER TABLE backend.email_confirmations
|
|
ADD COLUMN purpose text NOT NULL DEFAULT 'link',
|
|
ADD COLUMN link_token_hash text;
|
|
ALTER TABLE backend.email_confirmations
|
|
ADD CONSTRAINT email_confirmations_purpose_chk
|
|
CHECK ((purpose = ANY (ARRAY['login'::text, 'link'::text, 'change'::text, 'delete'::text])));
|
|
CREATE UNIQUE INDEX email_confirmations_link_token_hash_key
|
|
ON backend.email_confirmations (link_token_hash)
|
|
WHERE link_token_hash IS NOT NULL;
|
|
|
|
-- +goose Down
|
|
DROP INDEX IF EXISTS backend.email_confirmations_link_token_hash_key;
|
|
ALTER TABLE backend.email_confirmations
|
|
DROP CONSTRAINT IF EXISTS email_confirmations_purpose_chk;
|
|
ALTER TABLE backend.email_confirmations
|
|
DROP COLUMN IF EXISTS link_token_hash,
|
|
DROP COLUMN IF EXISTS purpose;
|