refactor: remove authentication module and integrate Better Auth

- Deleted the `autenticacao.ts` file to streamline the authentication process.
- Updated the `auth.ts` file to include new functions for user management and password updates.
- Modified the schema to enforce the presence of `authId` for users, ensuring integration with Better Auth.
- Refactored the seed process to create users with Better Auth integration, enhancing user management capabilities.
- Cleaned up the `usuarios.ts` file to utilize the new authentication functions and improve code clarity.
This commit is contained in:
2025-11-07 23:33:09 -03:00
parent 427c78ec37
commit 3a32f5e4eb
6 changed files with 377 additions and 1350 deletions

View File

@@ -1,8 +1,15 @@
import { internalMutation, mutation, query } from "./_generated/server";
import {
action,
internalAction,
internalMutation,
mutation,
query,
} from "./_generated/server";
import { internal } from "./_generated/api";
import { v } from "convex/values";
import { hashPassword } from "./auth/utils";
import { Id } from "./_generated/dataModel";
import { createAuthUser } from "./auth";
// Dados exportados do Convex Cloud
const simbolosData = [
@@ -187,83 +194,63 @@ const solicitacoesAcessoData = [
/**
* Seed inicial do banco de dados com os dados exportados do Convex Cloud
*/
export const seedDatabase = internalMutation({
export const seedCreateRoles = internalMutation({
args: {},
returns: v.null(),
handler: async (ctx) => {
console.log("🌱 Iniciando seed do banco de dados...");
// 1. Criar Roles (Perfis de Acesso)
console.log("🔐 Criando roles...");
// TI_MASTER - Nível 0 - Acesso total irrestrito
const roleTIMaster = await ctx.db.insert("roles", {
nome: "ti_master",
descricao: "TI Master",
nivel: 0,
setor: "ti",
customizado: false,
editavel: false,
});
console.log(" ✅ Role criada: ti_master (Nível 0 - Acesso Total)");
const ensureRole = async (
nome: string,
descricao: string,
nivel: number,
setor?: string,
editavel?: boolean
) => {
const existing = await ctx.db
.query("roles")
.withIndex("by_nome", (q) => q.eq("nome", nome))
.first();
if (existing) {
console.log(` Role já existe: ${nome}`);
return existing._id;
}
const id = await ctx.db.insert("roles", {
nome,
descricao,
nivel,
setor,
customizado: false,
editavel,
});
console.log(` ✅ Role criada: ${nome}`);
return id;
};
// ADMIN - Nível 2 - Permissões configuráveis
const roleAdmin = await ctx.db.insert("roles", {
nome: "admin",
descricao: "Administrador Geral",
nivel: 2,
setor: "administrativo",
customizado: false,
editavel: true, // Permissões configuráveis
});
console.log(" ✅ Role criada: admin (Nível 2 - Configurável)");
await ensureRole("ti_master", "TI Master", 0, "ti", false);
await ensureRole("admin", "Administrador Geral", 2, "administrativo", true);
await ensureRole("ti_usuario", "TI Usuário", 2, "ti", true);
await ensureRole("rh", "Recursos Humanos", 2, "recursos_humanos", false);
await ensureRole("financeiro", "Financeiro", 2, "financeiro", false);
await ensureRole("usuario", "Usuário Padrão", 3, undefined, false);
// Encadeia próxima etapa
await ctx.scheduler.runAfter(0, internal.seed.seedCreateSimbolos, {});
return null;
},
});
// TI_USUARIO - Nível 2 - Suporte técnico
const roleTIUsuario = await ctx.db.insert("roles", {
nome: "ti_usuario",
descricao: "TI Usuário",
nivel: 2,
setor: "ti",
customizado: false,
editavel: true,
});
console.log(" ✅ Role criada: ti_usuario (Nível 2 - Suporte)");
const roleRH = await ctx.db.insert("roles", {
nome: "rh",
descricao: "Recursos Humanos",
nivel: 2,
setor: "recursos_humanos",
customizado: false,
editavel: false,
});
console.log(" ✅ Role criada: rh");
const roleFinanceiro = await ctx.db.insert("roles", {
nome: "financeiro",
descricao: "Financeiro",
nivel: 2,
setor: "financeiro",
customizado: false,
editavel: false,
});
console.log(" ✅ Role criada: financeiro");
const roleUsuario = await ctx.db.insert("roles", {
nome: "usuario",
descricao: "Usuário Padrão",
nivel: 3,
setor: undefined,
customizado: false,
editavel: false,
});
console.log(" ✅ Role criada: usuario (Nível 3 - Padrão)");
// 2. Criar Símbolos (Cargos)
export const seedCreateSimbolos = internalMutation({
args: {},
returns: v.null(),
handler: async (ctx) => {
console.log("💰 Criando símbolos...");
const simbolosMap = new Map<string, Id<"simbolos">>();
const existentes = await ctx.db.query("simbolos").collect();
const nomesExistentes = new Set(existentes.map((s) => s.nome));
for (const simbolo of simbolosData) {
const simboloId = await ctx.db.insert("simbolos", {
if (nomesExistentes.has(simbolo.nome)) {
console.log(` Símbolo já existe: ${simbolo.nome}`);
continue;
}
await ctx.db.insert("simbolos", {
nome: simbolo.nome,
descricao: simbolo.descricao,
tipo: simbolo.tipo,
@@ -271,24 +258,43 @@ export const seedDatabase = internalMutation({
repValor: simbolo.repValor || "",
vencValor: simbolo.vencValor || "",
});
simbolosMap.set(simbolo.nome, simboloId);
console.log(` ✅ Símbolo criado: ${simbolo.nome}`);
}
// Encadeia próxima etapa
await ctx.scheduler.runAfter(0, internal.seed.seedCreateFuncionarios, {});
return null;
},
});
// 3. Criar Funcionários
export const seedCreateFuncionarios = internalMutation({
args: {},
returns: v.null(),
handler: async (ctx) => {
console.log("👥 Criando funcionários...");
const funcionariosMap = new Map<string, Id<"funcionarios">>();
const simbolos = await ctx.db.query("simbolos").collect();
const simbolosMap = new Map<string, Id<"simbolos">>();
for (const s of simbolos) {
simbolosMap.set(s.nome, s._id as Id<"simbolos">);
}
for (const funcionario of funcionariosData) {
const simboloId = simbolosMap.get(funcionario.simboloNome);
if (!simboloId) {
// Evitar duplicar por CPF
const existente = await ctx.db
.query("funcionarios")
.withIndex("by_cpf", (q) => q.eq("cpf", funcionario.cpf))
.first();
if (existente) {
console.log(
` ❌ Símbolo não encontrado: ${funcionario.simboloNome}`
` Funcionário já existe (CPF ${funcionario.cpf}): ${existente.nome}`
);
continue;
}
const funcId = await ctx.db.insert("funcionarios", {
const simboloId = simbolosMap.get(funcionario.simboloNome);
if (!simboloId) {
console.log(` ❌ Símbolo não encontrado: ${funcionario.simboloNome}`);
continue;
}
await ctx.db.insert("funcionarios", {
admissaoData: funcionario.admissaoData,
cep: funcionario.cep,
cidade: funcionario.cidade,
@@ -304,36 +310,126 @@ export const seedDatabase = internalMutation({
telefone: funcionario.telefone,
uf: funcionario.uf,
});
funcionariosMap.set(funcionario.matricula, funcId);
console.log(` ✅ Funcionário criado: ${funcionario.nome}`);
}
// Encadeia próxima etapa
await ctx.scheduler.runAfter(
0,
internal.seed.seedCreateUsuariosParaFuncionarios,
{}
);
return null;
},
});
// 5. Criar usuários para os funcionários
export const seedCreateUsuariosParaFuncionarios = internalMutation({
args: {},
returns: v.null(),
handler: async (ctx) => {
console.log("👤 Criando usuários para funcionários...");
// Agenda criação por funcionário para evitar timeout
let delay = 0;
for (const funcionario of funcionariosData) {
const funcId = funcionariosMap.get(funcionario.matricula);
if (!funcId) continue;
const senhaInicial = await hashPassword("Mudar@123");
await ctx.db.insert("usuarios", {
senhaHash: senhaInicial,
nome: funcionario.nome,
email: funcionario.email,
funcionarioId: funcId as Id<"funcionarios">,
roleId: roleUsuario,
ativo: true,
primeiroAcesso: true,
criadoEm: Date.now(),
atualizadoEm: Date.now(),
});
console.log(
` ✅ Usuário criado: ${funcionario.nome} (senha: Mudar@123)`
await ctx.scheduler.runAfter(
delay,
internal.seed.seedCreateUsuarioParaFuncionario,
{
matricula: funcionario.matricula,
nome: funcionario.nome,
email: funcionario.email,
}
);
delay += 50;
}
// Agenda próxima etapa após as criações individuais
await ctx.scheduler.runAfter(
delay + 300,
internal.seed.seedInserirSolicitacoesAcesso,
{}
);
return null;
},
});
export const seedCreateUsuarioParaFuncionario = internalMutation({
args: {
matricula: v.string(),
nome: v.string(),
email: v.string(),
},
returns: v.null(),
handler: async (ctx, args) => {
// Role "usuario"
const roleUsuario = await ctx.db
.query("roles")
.withIndex("by_nome", (q) => q.eq("nome", "usuario"))
.first();
if (!roleUsuario) {
console.log(' ❌ Role "usuario" não encontrada');
return null;
}
// 6. Inserir solicitações de acesso
const funcionarioDoc = await ctx.db
.query("funcionarios")
.withIndex("by_matricula", (q) => q.eq("matricula", args.matricula))
.first();
if (!funcionarioDoc) {
console.log(
` ❌ Funcionário não encontrado pela matrícula: ${args.matricula}`
);
return null;
}
const usuarioExistente = await ctx.db
.query("usuarios")
.withIndex("by_email", (q) => q.eq("email", args.email))
.first();
if (usuarioExistente) {
console.log(` Usuário já existe para ${args.email}`);
return null;
}
const authUserId = await createAuthUser(ctx, {
nome: args.nome,
email: args.email,
password: "Mudar@123",
});
await ctx.db.insert("usuarios", {
authId: authUserId,
nome: args.nome,
email: args.email,
funcionarioId: funcionarioDoc._id as Id<"funcionarios">,
roleId: roleUsuario._id,
ativo: true,
primeiroAcesso: true,
criadoEm: Date.now(),
atualizadoEm: Date.now(),
});
console.log(` ✅ Usuário criado: ${args.nome} (senha: Mudar@123)`);
return null;
},
});
export const seedInserirSolicitacoesAcesso = internalMutation({
args: {},
returns: v.null(),
handler: async (ctx) => {
console.log("📋 Inserindo solicitações de acesso...");
for (const solicitacao of solicitacoesAcessoData) {
// Evitar duplicidade por matrícula
const existente = await ctx.db
.query("solicitacoesAcesso")
.withIndex("by_matricula", (q) =>
q.eq("matricula", solicitacao.matricula)
)
.first();
if (existente) {
console.log(
` Solicitação já existe p/ matrícula ${solicitacao.matricula}`
);
continue;
}
const dadosSolicitacao: {
nome: string;
matricula: string;
@@ -365,10 +461,24 @@ export const seedDatabase = internalMutation({
` ✅ Solicitação criada: ${solicitacao.nome} (${solicitacao.status})`
);
}
console.log("✨ Seed do banco de dados concluído com sucesso!");
console.log("✨ Seed concluído!");
return null;
}
},
});
export const seedDatabase = internalAction({
args: {},
returns: v.null(),
handler: async (ctx) => {
console.log("🌱 Iniciando seed do banco de dados (action)...");
await ctx.runMutation(internal.seed.seedCreateRoles, {});
await ctx.runMutation(internal.seed.seedCreateSimbolos, {});
await ctx.runMutation(internal.seed.seedCreateFuncionarios, {});
await ctx.runMutation(internal.seed.seedCreateUsuariosParaFuncionarios, {});
await ctx.runMutation(internal.seed.seedInserirSolicitacoesAcesso, {});
console.log("✨ Seed do banco de dados concluído com sucesso pela action!");
return null;
},
});
/**
@@ -379,10 +489,12 @@ export const popularBanco = mutation({
args: {},
returns: v.null(),
handler: async (ctx) => {
console.log("🌱 Executando popularBanco (wrapper público para seedDatabase)...");
// Chama a internalMutation para reaproveitar a lógica de seed
await ctx.runMutation(internal.seed.seedDatabase, {});
console.log("✅ Seed concluído pelo wrapper público");
console.log(
"🌱 Executando popularBanco (wrapper público para seedDatabase)..."
);
// Agenda apenas a primeira etapa; as demais serão encadeadas internamente
await ctx.scheduler.runAfter(0, internal.seed.seedCreateRoles, {});
console.log("✅ Seed iniciado (etapa 1 agendada)");
return null;
},
});
@@ -525,7 +637,7 @@ export const clearDatabase = internalMutation({
);
// 9. Perfis customizados
// 10. Templates de mensagens
const templatesMensagens = await ctx.db
.query("templatesMensagens")
@@ -587,9 +699,9 @@ export const clearDatabase = internalMutation({
console.log(`${sessoes.length} sessões removidas`);
// 14. Menu-permissões personalizadas
// 15. Menu-permissões
// 16. Role-permissões
const rolePermissoes = await ctx.db.query("rolePermissoes").collect();
for (const rp of rolePermissoes) {
@@ -795,7 +907,7 @@ export const limparBanco = mutation({
);
// 9. Perfis customizados (já está no código da internalMutation mas vazio)
// 10. Templates de mensagens
const templatesMensagens = await ctx.db
.query("templatesMensagens")
@@ -857,9 +969,9 @@ export const limparBanco = mutation({
console.log(`${sessoes.length} sessões removidas`);
// 14. Menu-permissões personalizadas (já está no código da internalMutation mas vazio)
// 15. Menu-permissões (já está no código da internalMutation mas vazio)
// 16. Role-permissões
const rolePermissoes = await ctx.db.query("rolePermissoes").collect();
for (const rp of rolePermissoes) {
@@ -942,13 +1054,14 @@ export const verificarBanco = query({
const funcionarios = await ctx.db.query("funcionarios").collect();
const roles = await ctx.db.query("roles").collect();
const simbolos = await ctx.db.query("simbolos").collect();
return {
usuarios: usuarios.length,
funcionarios: funcionarios.length,
roles: roles.length,
simbolos: simbolos.length,
total: usuarios.length + funcionarios.length + roles.length + simbolos.length,
total:
usuarios.length + funcionarios.length + roles.length + simbolos.length,
};
},
});