Marketplace móvil para negocios locales mexicanos. Estructura inicial: - apps/backend (NestJS API) - apps/frontend (React Web) - apps/mobile (Expo/React Native) - apps/mcp-server (Claude MCP Server) - apps/whatsapp-service (WhatsApp Business API) - database/ (PostgreSQL DDL) - docs/ (Documentación) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
85 lines
2.3 KiB
SQL
85 lines
2.3 KiB
SQL
-- =============================================================================
|
|
-- MICHANGARRITO - 04 AUTH
|
|
-- =============================================================================
|
|
-- Autenticación y usuarios
|
|
-- =============================================================================
|
|
|
|
-- Usuarios
|
|
CREATE TABLE IF NOT EXISTS auth.users (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Identificación
|
|
phone VARCHAR(20) NOT NULL,
|
|
email VARCHAR(100),
|
|
name VARCHAR(100) NOT NULL,
|
|
|
|
-- Autenticación
|
|
pin_hash VARCHAR(255),
|
|
biometric_enabled BOOLEAN DEFAULT false,
|
|
biometric_key TEXT,
|
|
|
|
-- Rol
|
|
role VARCHAR(20) NOT NULL DEFAULT 'owner',
|
|
permissions JSONB DEFAULT '{}',
|
|
|
|
-- Estado
|
|
status VARCHAR(20) DEFAULT 'active',
|
|
last_login_at TIMESTAMPTZ,
|
|
failed_attempts INTEGER DEFAULT 0,
|
|
locked_until TIMESTAMPTZ,
|
|
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
|
|
UNIQUE(tenant_id, phone)
|
|
);
|
|
|
|
CREATE INDEX idx_users_tenant ON auth.users(tenant_id);
|
|
CREATE INDEX idx_users_phone ON auth.users(phone);
|
|
|
|
CREATE TRIGGER update_users_updated_at
|
|
BEFORE UPDATE ON auth.users
|
|
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
|
|
|
|
-- Sesiones
|
|
CREATE TABLE IF NOT EXISTS auth.sessions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
|
|
token_hash VARCHAR(255) NOT NULL,
|
|
refresh_token_hash VARCHAR(255),
|
|
|
|
device_type VARCHAR(20),
|
|
device_info JSONB,
|
|
ip_address VARCHAR(45),
|
|
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
|
refresh_expires_at TIMESTAMPTZ,
|
|
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
last_activity_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_sessions_user ON auth.sessions(user_id);
|
|
CREATE INDEX idx_sessions_token ON auth.sessions(token_hash);
|
|
|
|
-- Códigos OTP
|
|
CREATE TABLE IF NOT EXISTS auth.otp_codes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
phone VARCHAR(20) NOT NULL,
|
|
|
|
code VARCHAR(6) NOT NULL,
|
|
purpose VARCHAR(20) NOT NULL,
|
|
|
|
attempts INTEGER DEFAULT 0,
|
|
max_attempts INTEGER DEFAULT 3,
|
|
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
|
used_at TIMESTAMPTZ,
|
|
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_otp_phone ON auth.otp_codes(phone, purpose);
|