CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE TABLE tenants ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(255) NOT NULL, status VARCHAR(50) DEFAULT 'active', config JSONB DEFAULT '{}', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), tenant_id UUID NOT NULL REFERENCES tenants(id), email VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL, full_name VARCHAR(100), phone_number VARCHAR(20), is_active BOOLEAN DEFAULT TRUE, is_verified BOOLEAN DEFAULT FALSE, mfa_enabled BOOLEAN DEFAULT FALSE, mfa_secret VARCHAR(255), last_login_at TIMESTAMP WITH TIME ZONE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE UNIQUE INDEX idx_users_tenant_email ON users(tenant_id, email); CREATE TABLE roles ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), tenant_id UUID NOT NULL REFERENCES tenants(id), name VARCHAR(50) NOT NULL, description TEXT, is_system BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(tenant_id, name) ); CREATE TABLE permissions ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), code VARCHAR(100) NOT NULL UNIQUE, description TEXT, resource VARCHAR(50), action VARCHAR(50), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE TABLE role_permissions ( role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE, permission_id UUID NOT NULL REFERENCES permissions(id) ON DELETE CASCADE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), PRIMARY KEY (role_id, permission_id) ); CREATE TABLE user_roles ( user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), PRIMARY KEY (user_id, role_id) ); CREATE TABLE refresh_tokens ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, token_hash VARCHAR(255) NOT NULL, expires_at TIMESTAMP WITH TIME ZONE NOT NULL, is_revoked BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), replaced_by_token_hash VARCHAR(255) ); CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens(user_id); CREATE INDEX idx_refresh_tokens_token_hash ON refresh_tokens(token_hash); CREATE TABLE audit_logs ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), tenant_id UUID REFERENCES tenants(id), user_id UUID, action VARCHAR(100) NOT NULL, resource VARCHAR(100), ip_address VARCHAR(45), user_agent TEXT, status VARCHAR(20) NOT NULL, details JSONB, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); INSERT INTO tenants (id, name) VALUES ('11111111-1111-1111-1111-111111111111', 'Default Corp'); INSERT INTO permissions (code, description, resource, action) VALUES ('user:read', 'View users', 'user', 'read'), ('user:write', 'Create/Update/Delete users', 'user', 'write'), ('role:read', 'View roles', 'role', 'read'), ('role:write', 'Manage roles', 'role', 'write'), ('tenant:read', 'View tenant info', 'tenant', 'read'), ('tenant:write', 'Manage tenant settings and status', 'tenant', 'write'); INSERT INTO roles (tenant_id, name, description, is_system) VALUES ('11111111-1111-1111-1111-111111111111', 'Admin', 'Administrator with full access', TRUE); INSERT INTO role_permissions (role_id, permission_id) SELECT r.id, p.id FROM roles r, permissions p WHERE r.name = 'Admin' AND r.tenant_id = '11111111-1111-1111-1111-111111111111';