-- Create users table if it doesn't exist CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, email VARCHAR(100), totp_secret VARCHAR(32), totp_enabled BOOLEAN DEFAULT FALSE, backup_codes TEXT, -- JSON array of hashed backup codes created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, last_password_change TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, password_reset_token VARCHAR(64), password_reset_expires TIMESTAMP WITH TIME ZONE, failed_2fa_attempts INTEGER DEFAULT 0, last_failed_2fa TIMESTAMP WITH TIME ZONE ); -- Index for faster login lookups CREATE INDEX IF NOT EXISTS idx_users_username ON users(username); CREATE INDEX IF NOT EXISTS idx_users_reset_token ON users(password_reset_token) WHERE password_reset_token IS NOT NULL;