35 lines
1.3 KiB
SQL
35 lines
1.3 KiB
SQL
-- Console TOTP 2FA migration.
|
|
-- Destructive by design: the legacy plaintext users.two_factor_secret column is removed.
|
|
|
|
ALTER TABLE users DROP COLUMN IF EXISTS two_factor_secret;
|
|
|
|
ALTER TABLE users
|
|
ADD COLUMN IF NOT EXISTS two_factor_secret_encrypted BYTEA,
|
|
ADD COLUMN IF NOT EXISTS two_factor_secret_nonce BYTEA,
|
|
ADD COLUMN IF NOT EXISTS last_totp_step_used BIGINT,
|
|
ADD COLUMN IF NOT EXISTS totp_locked_until TIMESTAMPTZ,
|
|
ADD COLUMN IF NOT EXISTS totp_failed_attempts INT NOT NULL DEFAULT 0,
|
|
ADD COLUMN IF NOT EXISTS totp_first_failed_at TIMESTAMPTZ;
|
|
|
|
UPDATE users
|
|
SET two_factor_enabled = false,
|
|
two_factor_secret_encrypted = NULL,
|
|
two_factor_secret_nonce = NULL,
|
|
last_totp_step_used = NULL,
|
|
totp_locked_until = NULL,
|
|
totp_failed_attempts = 0,
|
|
totp_first_failed_at = NULL
|
|
WHERE two_factor_enabled = true
|
|
AND two_factor_secret_encrypted IS NULL;
|
|
|
|
CREATE TABLE IF NOT EXISTS two_factor_recovery_codes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
code_hash TEXT NOT NULL,
|
|
used_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_two_factor_recovery_codes_user_id
|
|
ON two_factor_recovery_codes(user_id);
|