diff --git a/apps/web/src/routes/(dashboard)/ti/configuracoes-email/+page.svelte b/apps/web/src/routes/(dashboard)/ti/configuracoes-email/+page.svelte index c6e32eb..449de6f 100644 --- a/apps/web/src/routes/(dashboard)/ti/configuracoes-email/+page.svelte +++ b/apps/web/src/routes/(dashboard)/ti/configuracoes-email/+page.svelte @@ -137,7 +137,7 @@ testando = true; try { - const resultado = await client.mutation(api.configuracaoEmail.testarConexaoSMTP, { + const resultado = await client.action(api.configuracaoEmail.testarConexaoSMTP, { servidor: servidor.trim(), porta: portaNum, usuario: usuario.trim(), diff --git a/packages/backend/convex/autenticacao.ts b/packages/backend/convex/autenticacao.ts index 3f7912c..dc6757d 100644 --- a/packages/backend/convex/autenticacao.ts +++ b/packages/backend/convex/autenticacao.ts @@ -8,7 +8,7 @@ import { validarSenha, } from "./auth/utils"; import { registrarLogin } from "./logsLogin"; -import { Id } from "./_generated/dataModel"; +import { Id, Doc } from "./_generated/dataModel"; import type { QueryCtx } from "./_generated/server"; /** @@ -62,6 +62,7 @@ export const login = mutation({ matricula: v.string(), nome: v.string(), email: v.string(), + funcionarioId: v.optional(v.id("funcionarios")), role: v.object({ _id: v.id("roles"), nome: v.string(), @@ -100,16 +101,19 @@ export const login = mutation({ const isEmail = args.matriculaOuEmail.includes("@"); // Buscar usuário - let usuario; + let usuario: Doc<"usuarios"> | null = null; if (isEmail) { usuario = await ctx.db .query("usuarios") .withIndex("by_email", (q) => q.eq("email", args.matriculaOuEmail)) .first(); } else { - funcionario = await ctx.db.query("funcionarios").withIndex("by_matricula", (q) => q.eq("matricula", args.matriculaOuEmail)).first(); + const funcionario: Doc<"funcionarios"> | null = await ctx.db.query("funcionarios").withIndex("by_matricula", (q) => q.eq("matricula", args.matriculaOuEmail)).first(); if (funcionario) { - usuario = await ctx.db.get(funcionario.usuarioId); + usuario = await ctx.db + .query("usuarios") + .withIndex("by_funcionarioId", (q) => q.eq("funcionarioId", funcionario._id)) + .first(); } } @@ -242,7 +246,7 @@ export const login = mutation({ }); // Buscar role do usuário - const role = await ctx.db.get(usuario.roleId); + const role: Doc<"roles"> | null = await ctx.db.get(usuario.roleId); if (!role) { return { sucesso: false as const, @@ -359,6 +363,7 @@ export const verificarSessao = query({ matricula: v.string(), nome: v.string(), email: v.string(), + funcionarioId: v.optional(v.id("funcionarios")), role: v.object({ _id: v.id("roles"), nome: v.string(), @@ -375,7 +380,7 @@ export const verificarSessao = query({ ), handler: async (ctx, args) => { // Buscar sessão - const sessao = await ctx.db + const sessao: Doc<"sessoes"> | null = await ctx.db .query("sessoes") .withIndex("by_token", (q) => q.eq("token", args.token)) .first(); @@ -395,7 +400,7 @@ export const verificarSessao = query({ } // Buscar usuário - const usuario = await ctx.db.get(sessao.usuarioId); + const usuario: Doc<"usuarios"> | null = await ctx.db.get(sessao.usuarioId); if (!usuario || !usuario.ativo) { return { valido: false as const, @@ -404,7 +409,7 @@ export const verificarSessao = query({ } // Buscar role - const role = await ctx.db.get(usuario.roleId); + const role: Doc<"roles"> | null = await ctx.db.get(usuario.roleId); if (!role) { return { valido: false as const, motivo: "Role não encontrada" }; } @@ -416,6 +421,7 @@ export const verificarSessao = query({ matricula: usuario.matricula, nome: usuario.nome, email: usuario.email, + funcionarioId: usuario.funcionarioId, role: { _id: role._id, nome: role.nome, @@ -478,7 +484,7 @@ export const alterarSenha = mutation({ ), handler: async (ctx, args) => { // Verificar sessão - const sessao = await ctx.db + const sessao: Doc<"sessoes"> | null = await ctx.db .query("sessoes") .withIndex("by_token", (q) => q.eq("token", args.token)) .first(); @@ -487,7 +493,7 @@ export const alterarSenha = mutation({ return { sucesso: false as const, erro: "Sessão inválida" }; } - const usuario = await ctx.db.get(sessao.usuarioId); + const usuario: Doc<"usuarios"> | null = await ctx.db.get(sessao.usuarioId); if (!usuario) { return { sucesso: false as const, erro: "Usuário não encontrado" }; } diff --git a/packages/backend/convex/configuracaoEmail.ts b/packages/backend/convex/configuracaoEmail.ts index 4988860..8453f87 100644 --- a/packages/backend/convex/configuracaoEmail.ts +++ b/packages/backend/convex/configuracaoEmail.ts @@ -1,8 +1,8 @@ import { v } from "convex/values"; -import { mutation, query } from "./_generated/server"; +import { mutation, query, action, internalMutation } from "./_generated/server"; import { encryptSMTPPassword } from "./auth/utils"; import { registrarAtividade } from "./logsAtividades"; -import { api } from "./_generated/api"; +import { api, internal } from "./_generated/api"; /** * Obter configuração de email ativa (senha mascarada) @@ -127,9 +127,25 @@ export const salvarConfigEmail = mutation({ }); /** - * Testar conexão SMTP (mutation que chama action real) + * Mutation interna para atualizar testadoEm */ -export const testarConexaoSMTP = mutation({ +export const atualizarTestadoEm = internalMutation({ + args: { + configId: v.id("configuracaoEmail"), + }, + returns: v.null(), + handler: async (ctx, args) => { + await ctx.db.patch(args.configId, { + testadoEm: Date.now(), + }); + return null; + }, +}); + +/** + * Testar conexão SMTP (action que chama action real) + */ +export const testarConexaoSMTP = action({ args: { servidor: v.string(), porta: v.number(), @@ -142,7 +158,7 @@ export const testarConexaoSMTP = mutation({ v.object({ sucesso: v.literal(true) }), v.object({ sucesso: v.literal(false), erro: v.string() }) ), - handler: async (ctx, args) => { + handler: async (ctx, args): Promise<{ sucesso: true } | { sucesso: false; erro: string }> => { // Validações básicas if (!args.servidor || args.servidor.trim().length === 0) { return { sucesso: false as const, erro: "Servidor SMTP não pode estar vazio" }; @@ -167,7 +183,7 @@ export const testarConexaoSMTP = mutation({ // Chamar action de teste real (que usa nodemailer) try { - const resultado = await ctx.scheduler.runAfter(0, api.actions.smtp.testarConexao, { + const resultado: { sucesso: true } | { sucesso: false; erro: string } = await ctx.runAction(api.actions.smtp.testarConexao, { servidor: args.servidor, porta: args.porta, usuario: args.usuario, @@ -178,23 +194,21 @@ export const testarConexaoSMTP = mutation({ // Se o teste foi bem-sucedido e há uma config ativa, atualizar testadoEm if (resultado.sucesso) { - const configAtiva = await ctx.db - .query("configuracaoEmail") - .withIndex("by_ativo", (q) => q.eq("ativo", true)) - .first(); - + const configAtiva = await ctx.runQuery(api.configuracaoEmail.obterConfigEmail, {}); + if (configAtiva) { - await ctx.db.patch(configAtiva._id, { - testadoEm: Date.now(), + await ctx.runMutation(internal.configuracaoEmail.atualizarTestadoEm, { + configId: configAtiva._id, }); } } return resultado; - } catch (error: any) { + } catch (error: unknown) { + const errorMessage = error instanceof Error ? error.message : String(error); return { sucesso: false as const, - erro: error.message || "Erro ao conectar com o servidor SMTP" + erro: errorMessage || "Erro ao conectar com o servidor SMTP" }; } },