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:
@@ -1,10 +1,10 @@
|
||||
import { v } from "convex/values";
|
||||
import { mutation, query } from "./_generated/server";
|
||||
import { hashPassword, generateToken } from "./auth/utils";
|
||||
import { hashPassword } from "./auth/utils";
|
||||
import { registrarAtividade } from "./logsAtividades";
|
||||
import { Id, Doc } from "./_generated/dataModel";
|
||||
import { api } from "./_generated/api";
|
||||
import type { QueryCtx, MutationCtx } from "./_generated/server";
|
||||
import { createAuthUser, getCurrentUserFunction } from "./auth";
|
||||
|
||||
/**
|
||||
* Helper para obter a matrícula do usuário (do funcionário se houver)
|
||||
@@ -20,33 +20,6 @@ async function obterMatriculaUsuario(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper para obter usuário autenticado (Better Auth ou Sessão)
|
||||
* Usa a mesma lógica do obterPerfil para garantir consistência
|
||||
*/
|
||||
async function getUsuarioAutenticado(ctx: QueryCtx | MutationCtx) {
|
||||
// FASE 1 IMPLEMENTADA: Usa Custom Auth Provider configurado no convex.config.ts
|
||||
// O provider busca sessão por token específico (seguro) ou Better Auth
|
||||
const identity = await ctx.auth.getUserIdentity();
|
||||
let usuarioAtual = null;
|
||||
|
||||
if (identity && identity.email) {
|
||||
usuarioAtual = await ctx.db
|
||||
.query("usuarios")
|
||||
.withIndex("by_email", (q) => q.eq("email", identity.email!))
|
||||
.first();
|
||||
}
|
||||
|
||||
if (!usuarioAtual && identity) {
|
||||
console.error("⚠️ [getUsuarioAutenticado] Identity encontrada mas usuário não encontrado no banco:", {
|
||||
email: identity.email,
|
||||
subject: identity.subject
|
||||
});
|
||||
}
|
||||
|
||||
return usuarioAtual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associar funcionário a um usuário
|
||||
*/
|
||||
@@ -132,12 +105,17 @@ export const criar = mutation({
|
||||
return { sucesso: false as const, erro: "E-mail já cadastrado" };
|
||||
}
|
||||
|
||||
// Gerar hash da senha inicial
|
||||
const senhaHash = await hashPassword(args.senhaInicial);
|
||||
const senhaTemporaria = args.senhaInicial;
|
||||
|
||||
const authUserId = await createAuthUser(ctx, {
|
||||
nome: args.nome,
|
||||
email: args.email,
|
||||
password: senhaTemporaria,
|
||||
});
|
||||
|
||||
// Criar usuário
|
||||
const usuarioId = await ctx.db.insert("usuarios", {
|
||||
senhaHash,
|
||||
authId: authUserId,
|
||||
nome: args.nome,
|
||||
email: args.email,
|
||||
funcionarioId: args.funcionarioId,
|
||||
@@ -161,69 +139,6 @@ export const listar = query({
|
||||
matricula: v.optional(v.string()),
|
||||
ativo: v.optional(v.boolean()),
|
||||
},
|
||||
// returns: v.array(
|
||||
// v.object({
|
||||
// _id: v.id("usuarios"),
|
||||
// matricula: v.string(),
|
||||
// nome: v.string(),
|
||||
// email: v.string(),
|
||||
// ativo: v.boolean(),
|
||||
// bloqueado: v.optional(v.boolean()),
|
||||
// motivoBloqueio: v.optional(v.string()),
|
||||
// primeiroAcesso: v.boolean(),
|
||||
// ultimoAcesso: v.optional(v.number()),
|
||||
// criadoEm: v.number(),
|
||||
// role: v.union(
|
||||
// v.object({
|
||||
// _id: v.id("roles"),
|
||||
// _creationTime: v.optional(v.number()),
|
||||
// criadoPor: v.optional(v.id("usuarios")),
|
||||
// customizado: v.optional(v.boolean()),
|
||||
// descricao: v.string(),
|
||||
// editavel: v.optional(v.boolean()),
|
||||
// nome: v.string(),
|
||||
// nivel: v.number(),
|
||||
// setor: v.optional(v.string()),
|
||||
// }),
|
||||
// v.object({
|
||||
// _id: v.id("roles"),
|
||||
// _creationTime: v.optional(v.number()),
|
||||
// criadoPor: v.optional(v.id("usuarios")),
|
||||
// customizado: v.optional(v.boolean()),
|
||||
// descricao: v.literal("Perfil não encontrado"),
|
||||
// editavel: v.optional(v.boolean()),
|
||||
// nome: v.literal("erro_role_ausente"),
|
||||
// nivel: v.literal(999),
|
||||
// setor: v.optional(v.string()),
|
||||
// erro: v.literal(true),
|
||||
// })
|
||||
// ),
|
||||
// funcionario: v.optional(
|
||||
// v.object({
|
||||
// _id: v.id("funcionarios"),
|
||||
// nome: v.string(),
|
||||
// matricula: v.optional(v.string()),
|
||||
// descricaoCargo: v.optional(v.string()),
|
||||
// simboloTipo: v.union(
|
||||
// v.literal("cargo_comissionado"),
|
||||
// v.literal("funcao_gratificada")
|
||||
// ),
|
||||
// })
|
||||
// ),
|
||||
// avisos: v.optional(
|
||||
// v.array(
|
||||
// v.object({
|
||||
// tipo: v.union(
|
||||
// v.literal("erro"),
|
||||
// v.literal("aviso"),
|
||||
// v.literal("info")
|
||||
// ),
|
||||
// mensagem: v.string(),
|
||||
// })
|
||||
// )
|
||||
// ),
|
||||
// })
|
||||
// ),
|
||||
handler: async (ctx, args) => {
|
||||
let usuarios = await ctx.db.query("usuarios").collect();
|
||||
|
||||
@@ -439,34 +354,34 @@ export const alterarStatus = mutation({
|
||||
/**
|
||||
* Resetar senha do usuário
|
||||
*/
|
||||
export const resetarSenha = mutation({
|
||||
args: {
|
||||
usuarioId: v.id("usuarios"),
|
||||
novaSenha: v.string(),
|
||||
},
|
||||
returns: v.null(),
|
||||
handler: async (ctx, args) => {
|
||||
const senhaHash = await hashPassword(args.novaSenha);
|
||||
// export const resetarSenha = mutation({
|
||||
// args: {
|
||||
// usuarioId: v.id("usuarios"),
|
||||
// novaSenha: v.string(),
|
||||
// },
|
||||
// returns: v.null(),
|
||||
// handler: async (ctx, args) => {
|
||||
// const senhaHash = await hashPassword(args.novaSenha);
|
||||
|
||||
await ctx.db.patch(args.usuarioId, {
|
||||
senhaHash,
|
||||
primeiroAcesso: true,
|
||||
atualizadoEm: Date.now(),
|
||||
});
|
||||
// await ctx.db.patch(args.usuarioId, {
|
||||
// senhaHash,
|
||||
// primeiroAcesso: true,
|
||||
// atualizadoEm: Date.now(),
|
||||
// });
|
||||
|
||||
// Desativar todas as sessões
|
||||
const sessoes = await ctx.db
|
||||
.query("sessoes")
|
||||
.withIndex("by_usuario", (q) => q.eq("usuarioId", args.usuarioId))
|
||||
.collect();
|
||||
// // Desativar todas as sessões
|
||||
// const sessoes = await ctx.db
|
||||
// .query("sessoes")
|
||||
// .withIndex("by_usuario", (q) => q.eq("usuarioId", args.usuarioId))
|
||||
// .collect();
|
||||
|
||||
for (const sessao of sessoes) {
|
||||
await ctx.db.patch(sessao._id, { ativo: false });
|
||||
}
|
||||
// for (const sessao of sessoes) {
|
||||
// await ctx.db.patch(sessao._id, { ativo: false });
|
||||
// }
|
||||
|
||||
return null;
|
||||
},
|
||||
});
|
||||
// return null;
|
||||
// },
|
||||
// });
|
||||
|
||||
/**
|
||||
* Excluir usuário
|
||||
@@ -601,19 +516,6 @@ export const atualizarPerfil = mutation({
|
||||
.first();
|
||||
}
|
||||
|
||||
// SE NÃO ENCONTROU, BUSCAR POR SESSÃO ATIVA (Sistema customizado)
|
||||
if (!usuarioAtual) {
|
||||
const sessaoAtiva = await ctx.db
|
||||
.query("sessoes")
|
||||
.filter((q) => q.eq(q.field("ativo"), true))
|
||||
.order("desc")
|
||||
.first();
|
||||
|
||||
if (sessaoAtiva) {
|
||||
usuarioAtual = await ctx.db.get(sessaoAtiva.usuarioId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!usuarioAtual) throw new Error("Usuário não encontrado");
|
||||
|
||||
// Validar statusMensagem (max 100 chars)
|
||||
@@ -678,9 +580,6 @@ export const obterPerfil = query({
|
||||
v.null()
|
||||
),
|
||||
handler: async (ctx) => {
|
||||
console.log("=== DEBUG obterPerfil ===");
|
||||
|
||||
// TENTAR BETTER AUTH PRIMEIRO
|
||||
const identity = await ctx.auth.getUserIdentity();
|
||||
console.log("Identity:", identity ? "encontrado" : "null");
|
||||
|
||||
@@ -693,42 +592,9 @@ export const obterPerfil = query({
|
||||
.query("usuarios")
|
||||
.withIndex("by_email", (q) => q.eq("email", identity.email!))
|
||||
.first();
|
||||
|
||||
console.log(
|
||||
"Usuário encontrado por email:",
|
||||
usuarioAtual ? "SIM" : "NÃO"
|
||||
);
|
||||
}
|
||||
|
||||
// SE NÃO ENCONTROU, BUSCAR POR SESSÃO ATIVA (Sistema customizado)
|
||||
if (!usuarioAtual) {
|
||||
console.log("Buscando por sessão ativa...");
|
||||
const sessaoAtiva = await ctx.db
|
||||
.query("sessoes")
|
||||
.filter((q) => q.eq(q.field("ativo"), true))
|
||||
.order("desc")
|
||||
.first();
|
||||
|
||||
console.log("Sessão ativa encontrada:", sessaoAtiva ? "SIM" : "NÃO");
|
||||
|
||||
if (sessaoAtiva) {
|
||||
usuarioAtual = await ctx.db.get(sessaoAtiva.usuarioId);
|
||||
console.log(
|
||||
"Usuário da sessão encontrado:",
|
||||
usuarioAtual ? "SIM" : "NÃO"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!usuarioAtual) {
|
||||
console.log("❌ Nenhum usuário encontrado");
|
||||
// Listar todos os usuários para debug
|
||||
const todosUsuarios = await ctx.db.query("usuarios").collect();
|
||||
console.log("Total de usuários no banco:", todosUsuarios.length);
|
||||
console.log(
|
||||
"Emails cadastrados:",
|
||||
todosUsuarios.map((u) => u.email)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -789,7 +655,10 @@ export const listarParaChat = query({
|
||||
),
|
||||
handler: async (ctx) => {
|
||||
// Obter usuário autenticado usando função helper compartilhada
|
||||
const usuarioAtual = await getUsuarioAutenticado(ctx);
|
||||
const usuarioAtual = await getCurrentUserFunction(ctx);
|
||||
if (!usuarioAtual) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Buscar todos os usuários ativos
|
||||
const usuarios = await ctx.db
|
||||
@@ -888,6 +757,11 @@ export const bloquearUsuario = mutation({
|
||||
v.object({ sucesso: v.literal(false), erro: v.string() })
|
||||
),
|
||||
handler: async (ctx, args) => {
|
||||
const usuarioAtual = await getCurrentUserFunction(ctx);
|
||||
if (!usuarioAtual) {
|
||||
return { sucesso: false as const, erro: "Usuário não autenticado" };
|
||||
}
|
||||
|
||||
const usuario = await ctx.db.get(args.usuarioId);
|
||||
if (!usuario) {
|
||||
return { sucesso: false as const, erro: "Usuário não encontrado" };
|
||||
@@ -948,6 +822,11 @@ export const desbloquearUsuario = mutation({
|
||||
v.object({ sucesso: v.literal(false), erro: v.string() })
|
||||
),
|
||||
handler: async (ctx, args) => {
|
||||
const usuarioAtual = await getCurrentUserFunction(ctx);
|
||||
if (!usuarioAtual) {
|
||||
return { sucesso: false as const, erro: "Usuário não autenticado" };
|
||||
}
|
||||
|
||||
const usuario = await ctx.db.get(args.usuarioId);
|
||||
if (!usuario) {
|
||||
return { sucesso: false as const, erro: "Usuário não encontrado" };
|
||||
@@ -995,48 +874,48 @@ export const desbloquearUsuario = mutation({
|
||||
/**
|
||||
* Resetar senha de usuário (apenas TI_MASTER)
|
||||
*/
|
||||
export const resetarSenhaUsuario = mutation({
|
||||
args: {
|
||||
usuarioId: v.id("usuarios"),
|
||||
resetadoPorId: v.id("usuarios"),
|
||||
novaSenhaTemporaria: v.optional(v.string()), // Se não fornecer, gera automática
|
||||
},
|
||||
returns: v.union(
|
||||
v.object({ sucesso: v.literal(true), senhaTemporaria: v.string() }),
|
||||
v.object({ sucesso: v.literal(false), erro: v.string() })
|
||||
),
|
||||
handler: async (ctx, args) => {
|
||||
const usuario = await ctx.db.get(args.usuarioId);
|
||||
if (!usuario) {
|
||||
return { sucesso: false as const, erro: "Usuário não encontrado" };
|
||||
}
|
||||
// export const resetarSenhaUsuario = mutation({
|
||||
// args: {
|
||||
// usuarioId: v.id("usuarios"),
|
||||
// resetadoPorId: v.id("usuarios"),
|
||||
// novaSenhaTemporaria: v.optional(v.string()), // Se não fornecer, gera automática
|
||||
// },
|
||||
// returns: v.union(
|
||||
// v.object({ sucesso: v.literal(true), senhaTemporaria: v.string() }),
|
||||
// v.object({ sucesso: v.literal(false), erro: v.string() })
|
||||
// ),
|
||||
// handler: async (ctx, args) => {
|
||||
// const usuario = await ctx.db.get(args.usuarioId);
|
||||
// if (!usuario) {
|
||||
// return { sucesso: false as const, erro: "Usuário não encontrado" };
|
||||
// }
|
||||
|
||||
// Gerar senha temporária se não foi fornecida
|
||||
const senhaTemporaria = args.novaSenhaTemporaria || gerarSenhaTemporaria();
|
||||
const senhaHash = await hashPassword(senhaTemporaria);
|
||||
// // Gerar senha temporária se não foi fornecida
|
||||
// const senhaTemporaria = args.novaSenhaTemporaria || gerarSenhaTemporaria();
|
||||
// const senhaHash = await hashPassword(senhaTemporaria);
|
||||
|
||||
// Atualizar usuário
|
||||
await ctx.db.patch(args.usuarioId, {
|
||||
senhaHash,
|
||||
primeiroAcesso: true, // Força mudança de senha no próximo login
|
||||
tentativasLogin: 0,
|
||||
ultimaTentativaLogin: undefined,
|
||||
atualizadoEm: Date.now(),
|
||||
});
|
||||
// // Atualizar usuário
|
||||
// await ctx.db.patch(args.usuarioId, {
|
||||
// senhaHash,
|
||||
// primeiroAcesso: true, // Força mudança de senha no próximo login
|
||||
// tentativasLogin: 0,
|
||||
// ultimaTentativaLogin: undefined,
|
||||
// atualizadoEm: Date.now(),
|
||||
// });
|
||||
|
||||
// Log de atividade
|
||||
await registrarAtividade(
|
||||
ctx,
|
||||
args.resetadoPorId,
|
||||
"resetar_senha",
|
||||
"usuarios",
|
||||
JSON.stringify({ usuarioId: args.usuarioId }),
|
||||
args.usuarioId
|
||||
);
|
||||
// // Log de atividade
|
||||
// await registrarAtividade(
|
||||
// ctx,
|
||||
// args.resetadoPorId,
|
||||
// "resetar_senha",
|
||||
// "usuarios",
|
||||
// JSON.stringify({ usuarioId: args.usuarioId }),
|
||||
// args.usuarioId
|
||||
// );
|
||||
|
||||
return { sucesso: true as const, senhaTemporaria };
|
||||
},
|
||||
});
|
||||
// return { sucesso: true as const, senhaTemporaria };
|
||||
// },
|
||||
// });
|
||||
|
||||
// Helper para gerar senha temporária
|
||||
function gerarSenhaTemporaria(): string {
|
||||
@@ -1066,6 +945,11 @@ export const editarUsuario = mutation({
|
||||
v.object({ sucesso: v.literal(false), erro: v.string() })
|
||||
),
|
||||
handler: async (ctx, args) => {
|
||||
const usuarioAtual = await getCurrentUserFunction(ctx);
|
||||
if (!usuarioAtual) {
|
||||
return { sucesso: false as const, erro: "Usuário não autenticado" };
|
||||
}
|
||||
|
||||
const usuario = await ctx.db.get(args.usuarioId);
|
||||
if (!usuario) {
|
||||
return { sucesso: false as const, erro: "Usuário não encontrado" };
|
||||
@@ -1153,7 +1037,12 @@ export const criarAdminMaster = mutation({
|
||||
}
|
||||
|
||||
const senhaTemporaria = args.senha || gerarSenhaTemporaria();
|
||||
const senhaHash = await hashPassword(senhaTemporaria);
|
||||
|
||||
const authUserId = await createAuthUser(ctx, {
|
||||
nome: args.nome,
|
||||
email: args.email,
|
||||
password: senhaTemporaria,
|
||||
});
|
||||
|
||||
// Verificar se email já existe
|
||||
const existentePorEmail = await ctx.db
|
||||
@@ -1164,11 +1053,11 @@ export const criarAdminMaster = mutation({
|
||||
// Promove usuário existente por email
|
||||
await ctx.db.patch(existentePorEmail._id, {
|
||||
nome: args.nome,
|
||||
senhaHash,
|
||||
roleId: roleTIMaster._id,
|
||||
ativo: true,
|
||||
primeiroAcesso: true,
|
||||
atualizadoEm: Date.now(),
|
||||
authId: authUserId,
|
||||
});
|
||||
return {
|
||||
sucesso: true as const,
|
||||
@@ -1179,7 +1068,7 @@ export const criarAdminMaster = mutation({
|
||||
|
||||
// Criar novo usuário TI Master
|
||||
const usuarioId = await ctx.db.insert("usuarios", {
|
||||
senhaHash,
|
||||
authId: authUserId,
|
||||
nome: args.nome,
|
||||
email: args.email,
|
||||
roleId: roleTIMaster._id,
|
||||
@@ -1192,191 +1081,3 @@ export const criarAdminMaster = mutation({
|
||||
return { sucesso: true as const, usuarioId, senhaTemporaria };
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Desativar usuário logicamente (soft delete - apenas TI_MASTER)
|
||||
*/
|
||||
export const excluirUsuarioLogico = mutation({
|
||||
args: {
|
||||
usuarioId: v.id("usuarios"),
|
||||
excluidoPorId: v.id("usuarios"),
|
||||
},
|
||||
returns: v.union(
|
||||
v.object({ sucesso: v.literal(true) }),
|
||||
v.object({ sucesso: v.literal(false), erro: v.string() })
|
||||
),
|
||||
handler: async (ctx, args) => {
|
||||
const usuario = await ctx.db.get(args.usuarioId);
|
||||
if (!usuario) {
|
||||
return { sucesso: false as const, erro: "Usuário não encontrado" };
|
||||
}
|
||||
|
||||
// Marcar como inativo
|
||||
await ctx.db.patch(args.usuarioId, {
|
||||
ativo: false,
|
||||
atualizadoEm: Date.now(),
|
||||
});
|
||||
|
||||
// Desativar todas as sessões
|
||||
const sessoes = await ctx.db
|
||||
.query("sessoes")
|
||||
.withIndex("by_usuario", (q) => q.eq("usuarioId", args.usuarioId))
|
||||
.filter((q) => q.eq(q.field("ativo"), true))
|
||||
.collect();
|
||||
|
||||
for (const sessao of sessoes) {
|
||||
await ctx.db.patch(sessao._id, { ativo: false });
|
||||
}
|
||||
|
||||
// Log de atividade
|
||||
await registrarAtividade(
|
||||
ctx,
|
||||
args.excluidoPorId,
|
||||
"excluir",
|
||||
"usuarios",
|
||||
JSON.stringify({ usuarioId: args.usuarioId }),
|
||||
args.usuarioId
|
||||
);
|
||||
|
||||
return { sucesso: true as const };
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Criar usuário completo com permissões (TI_MASTER)
|
||||
*/
|
||||
export const criarUsuarioCompleto = mutation({
|
||||
args: {
|
||||
nome: v.string(),
|
||||
email: v.string(),
|
||||
roleId: v.id("roles"),
|
||||
setor: v.optional(v.string()),
|
||||
senhaInicial: v.optional(v.string()),
|
||||
criadoPorId: v.id("usuarios"),
|
||||
enviarEmailBoasVindas: v.optional(v.boolean()),
|
||||
},
|
||||
returns: v.union(
|
||||
v.object({
|
||||
sucesso: v.literal(true),
|
||||
usuarioId: v.id("usuarios"),
|
||||
senhaTemporaria: v.string(),
|
||||
}),
|
||||
v.object({ sucesso: v.literal(false), erro: v.string() })
|
||||
),
|
||||
handler: async (ctx, args) => {
|
||||
// Verificar se email já existe
|
||||
const emailExistente = await ctx.db
|
||||
.query("usuarios")
|
||||
.withIndex("by_email", (q) => q.eq("email", args.email))
|
||||
.first();
|
||||
|
||||
if (emailExistente) {
|
||||
return { sucesso: false as const, erro: "E-mail já cadastrado" };
|
||||
}
|
||||
|
||||
// Gerar senha inicial se não fornecida
|
||||
const senhaTemporaria = args.senhaInicial || gerarSenhaTemporaria();
|
||||
const senhaHash = await hashPassword(senhaTemporaria);
|
||||
|
||||
// Criar usuário
|
||||
const usuarioId = await ctx.db.insert("usuarios", {
|
||||
senhaHash,
|
||||
nome: args.nome,
|
||||
email: args.email,
|
||||
roleId: args.roleId,
|
||||
setor: args.setor,
|
||||
ativo: true,
|
||||
primeiroAcesso: true,
|
||||
criadoEm: Date.now(),
|
||||
atualizadoEm: Date.now(),
|
||||
});
|
||||
|
||||
// Log de atividade
|
||||
await registrarAtividade(
|
||||
ctx,
|
||||
args.criadoPorId,
|
||||
"criar",
|
||||
"usuarios",
|
||||
JSON.stringify({ usuarioId, nome: args.nome }),
|
||||
usuarioId
|
||||
);
|
||||
|
||||
// TODO: Se enviarEmailBoasVindas = true, enfileirar email
|
||||
// Isso será implementado quando criarmos o sistema de emails
|
||||
|
||||
return { sucesso: true as const, usuarioId, senhaTemporaria };
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Criar (ou garantir) um usuário ADMIN padrão
|
||||
*/
|
||||
export const criarAdminPadrao = mutation({
|
||||
args: {
|
||||
nome: v.optional(v.string()),
|
||||
email: v.optional(v.string()),
|
||||
senha: v.optional(v.string()),
|
||||
},
|
||||
returns: v.object({
|
||||
sucesso: v.boolean(),
|
||||
usuarioId: v.optional(v.id("usuarios")),
|
||||
}),
|
||||
handler: async (ctx, args) => {
|
||||
const nome = args.nome ?? "Administrador Geral";
|
||||
const email = args.email ?? "admin@sgse.pe.gov.br";
|
||||
const senha = args.senha ?? "Admin@123";
|
||||
|
||||
// Garantir role ADMIN (nível 2)
|
||||
let roleAdmin = await ctx.db
|
||||
.query("roles")
|
||||
.withIndex("by_nome", (q) => q.eq("nome", "admin"))
|
||||
.first();
|
||||
if (!roleAdmin) {
|
||||
const roleId = await ctx.db.insert("roles", {
|
||||
nome: "admin",
|
||||
descricao: "Administrador Geral",
|
||||
nivel: 2,
|
||||
setor: "administrativo",
|
||||
customizado: false,
|
||||
editavel: true,
|
||||
});
|
||||
roleAdmin = await ctx.db.get(roleId);
|
||||
}
|
||||
|
||||
if (!roleAdmin) return { sucesso: false };
|
||||
|
||||
// Verificar se já existe por email
|
||||
const existentePorEmail = await ctx.db
|
||||
.query("usuarios")
|
||||
.withIndex("by_email", (q) => q.eq("email", email))
|
||||
.first();
|
||||
|
||||
const senhaHash = await hashPassword(senha);
|
||||
|
||||
if (existentePorEmail) {
|
||||
await ctx.db.patch(existentePorEmail._id, {
|
||||
nome,
|
||||
email,
|
||||
senhaHash,
|
||||
roleId: roleAdmin._id,
|
||||
ativo: true,
|
||||
primeiroAcesso: false,
|
||||
atualizadoEm: Date.now(),
|
||||
});
|
||||
return { sucesso: true, usuarioId: existentePorEmail._id };
|
||||
}
|
||||
|
||||
const usuarioId = await ctx.db.insert("usuarios", {
|
||||
senhaHash,
|
||||
nome,
|
||||
email,
|
||||
roleId: roleAdmin._id,
|
||||
ativo: true,
|
||||
primeiroAcesso: false,
|
||||
criadoEm: Date.now(),
|
||||
atualizadoEm: Date.now(),
|
||||
});
|
||||
|
||||
return { sucesso: true, usuarioId };
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user