-- ============================================================ -- Migration 001: Módulo de Autenticação -- Tabelas: usuários, provedores, perfis de acesso e auditoria -- ============================================================ -- ------------------------------------------------------------ -- Tabela: usuarios -- Representa qualquer pessoa que acessa o sistema, -- independente de como ela se autenticou -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS usuarios ( id SERIAL PRIMARY KEY, nome VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE, -- pode ser nulo em contas só com LDAP sem email ativo BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_usuarios_email ON usuarios (email); -- ------------------------------------------------------------ -- Tabela: usuarios_provedores -- Vincula um usuário a um ou mais provedores de autenticação -- Um mesmo usuário pode logar via LDAP e via Microsoft -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS usuarios_provedores ( id SERIAL PRIMARY KEY, -- FK para o usuário correspondente usuario_id INTEGER NOT NULL REFERENCES usuarios (id) ON DELETE CASCADE, -- Provedor de autenticação: 'ldap' | 'microsoft' | 'google' | etc. provedor VARCHAR(50) NOT NULL, -- ID do usuário dentro do provedor (azure_id, username do AD, sub do Google...) provedor_user_id VARCHAR(255) NOT NULL, -- Evita duplicidade do mesmo provedor pro mesmo usuário CONSTRAINT uq_provedor_user UNIQUE (provedor, provedor_user_id), created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_usuarios_provedores_usuario ON usuarios_provedores (usuario_id); CREATE INDEX IF NOT EXISTS idx_usuarios_provedores_lookup ON usuarios_provedores (provedor, provedor_user_id); -- ------------------------------------------------------------ -- Tabela: perfis_acesso -- Define os papéis disponíveis no sistema -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS perfis_acesso ( id SERIAL PRIMARY KEY, nome VARCHAR(100) NOT NULL UNIQUE, descricao TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- ------------------------------------------------------------ -- Tabela: usuarios_perfis -- Relacionamento entre usuários e perfis (muitos-para-muitos) -- Um usuário pode ter mais de um perfil se necessário -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS usuarios_perfis ( id SERIAL PRIMARY KEY, usuario_id INTEGER NOT NULL REFERENCES usuarios (id) ON DELETE CASCADE, perfil_id INTEGER NOT NULL REFERENCES perfis_acesso (id) ON DELETE CASCADE, CONSTRAINT uq_usuario_perfil UNIQUE (usuario_id, perfil_id), created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_usuarios_perfis_usuario ON usuarios_perfis (usuario_id); CREATE INDEX IF NOT EXISTS idx_usuarios_perfis_perfil ON usuarios_perfis (perfil_id); -- ------------------------------------------------------------ -- Tabela: logs_auditoria -- Registra ações relevantes feitas por usuários ou pelo sistema -- usuario_id NULL = ação do sistema (ex: tentativa de login falha) -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS logs_auditoria ( id SERIAL PRIMARY KEY, usuario_id INTEGER REFERENCES usuarios (id) ON DELETE SET NULL, -- Ação realizada — ex: 'LOGIN_LDAP', 'LOGIN_MICROSOFT', 'LOGIN_FALHOU', 'USUARIO_CRIADO' acao VARCHAR(100) NOT NULL, -- Dados extras livres — ex: { "ip": "...", "provedor": "microsoft", "motivo": "..." } detalhes JSONB, ip_origem VARCHAR(45), created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_logs_usuario ON logs_auditoria (usuario_id); CREATE INDEX IF NOT EXISTS idx_logs_acao ON logs_auditoria (acao); CREATE INDEX IF NOT EXISTS idx_logs_created_at ON logs_auditoria (created_at); -- ------------------------------------------------------------ -- Dados iniciais: perfis de acesso -- ON CONFLICT garante que pode rodar mais de uma vez sem erro -- ------------------------------------------------------------ INSERT INTO perfis_acesso (nome, descricao) VALUES ('Agente', 'Atendente responsável por responder e encaminhar chamados'), ('Supervisor', 'Gestor com visibilidade de filas e relatórios'), ('Admin', 'Administrador com acesso total ao sistema') ON CONFLICT (nome) DO NOTHING;