Files
OmniOilPersonal/services/backend-api/migrations/20260508000000_totp_2fa.sql
2026-05-08 05:37:24 -05:00

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);