trading-platform-database/ddl/schemas/auth/tables/09-login_attempts.sql

68 lines
2.8 KiB
SQL

-- ============================================================================
-- OrbiQuant IA - Trading Platform
-- Schema: auth
-- File: tables/09-login_attempts.sql
-- Description: Login attempt tracking for rate limiting and security monitoring
-- ============================================================================
CREATE TABLE auth.login_attempts (
-- Primary Key
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Attempt Information
email CITEXT,
user_id UUID,
-- Request Context
ip_address INET NOT NULL,
user_agent TEXT,
-- Attempt Result
success BOOLEAN NOT NULL,
failure_reason VARCHAR(100),
-- Additional Details
attempted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Metadata
metadata JSONB DEFAULT '{}'::jsonb,
-- Audit Fields
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Check Constraints
CONSTRAINT login_attempt_has_identifier CHECK (
email IS NOT NULL OR user_id IS NOT NULL
),
CONSTRAINT failure_reason_consistency CHECK (
(success = false AND failure_reason IS NOT NULL) OR
(success = true AND failure_reason IS NULL)
)
);
-- Indexes for Performance
CREATE INDEX idx_login_attempts_email ON auth.login_attempts(email, created_at DESC);
CREATE INDEX idx_login_attempts_user_id ON auth.login_attempts(user_id, created_at DESC);
CREATE INDEX idx_login_attempts_ip ON auth.login_attempts(ip_address, created_at DESC);
CREATE INDEX idx_login_attempts_created ON auth.login_attempts(created_at DESC);
CREATE INDEX idx_login_attempts_failures ON auth.login_attempts(email, ip_address, created_at DESC)
WHERE success = false;
CREATE INDEX idx_login_attempts_success ON auth.login_attempts(email, created_at DESC)
WHERE success = true;
CREATE INDEX idx_login_attempts_metadata ON auth.login_attempts USING gin(metadata);
-- Table Comments
COMMENT ON TABLE auth.login_attempts IS 'Login attempt tracking for rate limiting, brute force detection, and security monitoring';
-- Column Comments
COMMENT ON COLUMN auth.login_attempts.id IS 'Unique identifier for the login attempt';
COMMENT ON COLUMN auth.login_attempts.email IS 'Email address used in login attempt';
COMMENT ON COLUMN auth.login_attempts.user_id IS 'User ID if resolved from email';
COMMENT ON COLUMN auth.login_attempts.ip_address IS 'IP address of the login attempt';
COMMENT ON COLUMN auth.login_attempts.user_agent IS 'User agent string from the request';
COMMENT ON COLUMN auth.login_attempts.success IS 'Whether the login attempt was successful';
COMMENT ON COLUMN auth.login_attempts.failure_reason IS 'Reason for login failure (invalid_password, account_locked, etc.)';
COMMENT ON COLUMN auth.login_attempts.attempted_at IS 'Timestamp when login was attempted';
COMMENT ON COLUMN auth.login_attempts.metadata IS 'Additional attempt metadata as JSON';
COMMENT ON COLUMN auth.login_attempts.created_at IS 'Timestamp when record was created';