Some checks failed
Deploy Development / deploy (push) Successful in 49s
Test Suite / pytest-backend (push) Successful in 47s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 15s
Test Suite / k6 /health Baseline (push) Successful in 35s
Test Suite / playwright-tests (push) Failing after 5m43s
Limit brute-force attempts, require admin TOTP, and keep session tokens out of media URLs. Co-authored-by: Cursor <cursoragent@cursor.com>
30 lines
1.1 KiB
SQL
30 lines
1.1 KiB
SQL
-- Login-Sperre, Sitzungszweck (Vollzugriff / 2FA-Einrichtung / 2FA-Challenge), TOTP.
|
|
|
|
ALTER TABLE profiles
|
|
ADD COLUMN IF NOT EXISTS failed_login_count INTEGER NOT NULL DEFAULT 0,
|
|
ADD COLUMN IF NOT EXISTS locked_until TIMESTAMP,
|
|
ADD COLUMN IF NOT EXISTS totp_secret TEXT,
|
|
ADD COLUMN IF NOT EXISTS totp_pending_secret TEXT,
|
|
ADD COLUMN IF NOT EXISTS totp_enabled BOOLEAN NOT NULL DEFAULT FALSE;
|
|
|
|
ALTER TABLE sessions
|
|
ADD COLUMN IF NOT EXISTS purpose VARCHAR(32) NOT NULL DEFAULT 'full',
|
|
ADD COLUMN IF NOT EXISTS failed_attempts INTEGER NOT NULL DEFAULT 0;
|
|
|
|
UPDATE sessions
|
|
SET purpose = 'password_reset'
|
|
WHERE token LIKE 'reset_%' AND purpose = 'full';
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_sessions_profile_purpose ON sessions (profile_id, purpose);
|
|
|
|
CREATE TABLE IF NOT EXISTS profile_recovery_codes (
|
|
id SERIAL PRIMARY KEY,
|
|
profile_id INTEGER NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
|
|
code_hash VARCHAR(64) NOT NULL,
|
|
used_at TIMESTAMP,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_profile_recovery_codes_profile
|
|
ON profile_recovery_codes (profile_id);
|