fix: update email configuration handling and improve type safety
- Changed the mutation for testing SMTP connection to use an action for better handling. - Introduced an internal mutation to update the test timestamp for email configurations. - Enhanced type safety by specifying document types for user and session queries. - Improved error handling in the SMTP connection test to provide clearer feedback on failures.
This commit is contained in:
@@ -137,7 +137,7 @@
|
|||||||
|
|
||||||
testando = true;
|
testando = true;
|
||||||
try {
|
try {
|
||||||
const resultado = await client.mutation(api.configuracaoEmail.testarConexaoSMTP, {
|
const resultado = await client.action(api.configuracaoEmail.testarConexaoSMTP, {
|
||||||
servidor: servidor.trim(),
|
servidor: servidor.trim(),
|
||||||
porta: portaNum,
|
porta: portaNum,
|
||||||
usuario: usuario.trim(),
|
usuario: usuario.trim(),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
validarSenha,
|
validarSenha,
|
||||||
} from "./auth/utils";
|
} from "./auth/utils";
|
||||||
import { registrarLogin } from "./logsLogin";
|
import { registrarLogin } from "./logsLogin";
|
||||||
import { Id } from "./_generated/dataModel";
|
import { Id, Doc } from "./_generated/dataModel";
|
||||||
import type { QueryCtx } from "./_generated/server";
|
import type { QueryCtx } from "./_generated/server";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,6 +62,7 @@ export const login = mutation({
|
|||||||
matricula: v.string(),
|
matricula: v.string(),
|
||||||
nome: v.string(),
|
nome: v.string(),
|
||||||
email: v.string(),
|
email: v.string(),
|
||||||
|
funcionarioId: v.optional(v.id("funcionarios")),
|
||||||
role: v.object({
|
role: v.object({
|
||||||
_id: v.id("roles"),
|
_id: v.id("roles"),
|
||||||
nome: v.string(),
|
nome: v.string(),
|
||||||
@@ -100,16 +101,19 @@ export const login = mutation({
|
|||||||
const isEmail = args.matriculaOuEmail.includes("@");
|
const isEmail = args.matriculaOuEmail.includes("@");
|
||||||
|
|
||||||
// Buscar usuário
|
// Buscar usuário
|
||||||
let usuario;
|
let usuario: Doc<"usuarios"> | null = null;
|
||||||
if (isEmail) {
|
if (isEmail) {
|
||||||
usuario = await ctx.db
|
usuario = await ctx.db
|
||||||
.query("usuarios")
|
.query("usuarios")
|
||||||
.withIndex("by_email", (q) => q.eq("email", args.matriculaOuEmail))
|
.withIndex("by_email", (q) => q.eq("email", args.matriculaOuEmail))
|
||||||
.first();
|
.first();
|
||||||
} else {
|
} 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) {
|
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
|
// 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) {
|
if (!role) {
|
||||||
return {
|
return {
|
||||||
sucesso: false as const,
|
sucesso: false as const,
|
||||||
@@ -359,6 +363,7 @@ export const verificarSessao = query({
|
|||||||
matricula: v.string(),
|
matricula: v.string(),
|
||||||
nome: v.string(),
|
nome: v.string(),
|
||||||
email: v.string(),
|
email: v.string(),
|
||||||
|
funcionarioId: v.optional(v.id("funcionarios")),
|
||||||
role: v.object({
|
role: v.object({
|
||||||
_id: v.id("roles"),
|
_id: v.id("roles"),
|
||||||
nome: v.string(),
|
nome: v.string(),
|
||||||
@@ -375,7 +380,7 @@ export const verificarSessao = query({
|
|||||||
),
|
),
|
||||||
handler: async (ctx, args) => {
|
handler: async (ctx, args) => {
|
||||||
// Buscar sessão
|
// Buscar sessão
|
||||||
const sessao = await ctx.db
|
const sessao: Doc<"sessoes"> | null = await ctx.db
|
||||||
.query("sessoes")
|
.query("sessoes")
|
||||||
.withIndex("by_token", (q) => q.eq("token", args.token))
|
.withIndex("by_token", (q) => q.eq("token", args.token))
|
||||||
.first();
|
.first();
|
||||||
@@ -395,7 +400,7 @@ export const verificarSessao = query({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Buscar usuário
|
// 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) {
|
if (!usuario || !usuario.ativo) {
|
||||||
return {
|
return {
|
||||||
valido: false as const,
|
valido: false as const,
|
||||||
@@ -404,7 +409,7 @@ export const verificarSessao = query({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Buscar role
|
// Buscar role
|
||||||
const role = await ctx.db.get(usuario.roleId);
|
const role: Doc<"roles"> | null = await ctx.db.get(usuario.roleId);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
return { valido: false as const, motivo: "Role não encontrada" };
|
return { valido: false as const, motivo: "Role não encontrada" };
|
||||||
}
|
}
|
||||||
@@ -416,6 +421,7 @@ export const verificarSessao = query({
|
|||||||
matricula: usuario.matricula,
|
matricula: usuario.matricula,
|
||||||
nome: usuario.nome,
|
nome: usuario.nome,
|
||||||
email: usuario.email,
|
email: usuario.email,
|
||||||
|
funcionarioId: usuario.funcionarioId,
|
||||||
role: {
|
role: {
|
||||||
_id: role._id,
|
_id: role._id,
|
||||||
nome: role.nome,
|
nome: role.nome,
|
||||||
@@ -478,7 +484,7 @@ export const alterarSenha = mutation({
|
|||||||
),
|
),
|
||||||
handler: async (ctx, args) => {
|
handler: async (ctx, args) => {
|
||||||
// Verificar sessão
|
// Verificar sessão
|
||||||
const sessao = await ctx.db
|
const sessao: Doc<"sessoes"> | null = await ctx.db
|
||||||
.query("sessoes")
|
.query("sessoes")
|
||||||
.withIndex("by_token", (q) => q.eq("token", args.token))
|
.withIndex("by_token", (q) => q.eq("token", args.token))
|
||||||
.first();
|
.first();
|
||||||
@@ -487,7 +493,7 @@ export const alterarSenha = mutation({
|
|||||||
return { sucesso: false as const, erro: "Sessão inválida" };
|
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) {
|
if (!usuario) {
|
||||||
return { sucesso: false as const, erro: "Usuário não encontrado" };
|
return { sucesso: false as const, erro: "Usuário não encontrado" };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { v } from "convex/values";
|
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 { encryptSMTPPassword } from "./auth/utils";
|
||||||
import { registrarAtividade } from "./logsAtividades";
|
import { registrarAtividade } from "./logsAtividades";
|
||||||
import { api } from "./_generated/api";
|
import { api, internal } from "./_generated/api";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obter configuração de email ativa (senha mascarada)
|
* 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: {
|
args: {
|
||||||
servidor: v.string(),
|
servidor: v.string(),
|
||||||
porta: v.number(),
|
porta: v.number(),
|
||||||
@@ -142,7 +158,7 @@ export const testarConexaoSMTP = mutation({
|
|||||||
v.object({ sucesso: v.literal(true) }),
|
v.object({ sucesso: v.literal(true) }),
|
||||||
v.object({ sucesso: v.literal(false), erro: v.string() })
|
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
|
// Validações básicas
|
||||||
if (!args.servidor || args.servidor.trim().length === 0) {
|
if (!args.servidor || args.servidor.trim().length === 0) {
|
||||||
return { sucesso: false as const, erro: "Servidor SMTP não pode estar vazio" };
|
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)
|
// Chamar action de teste real (que usa nodemailer)
|
||||||
try {
|
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,
|
servidor: args.servidor,
|
||||||
porta: args.porta,
|
porta: args.porta,
|
||||||
usuario: args.usuario,
|
usuario: args.usuario,
|
||||||
@@ -178,23 +194,21 @@ export const testarConexaoSMTP = mutation({
|
|||||||
|
|
||||||
// Se o teste foi bem-sucedido e há uma config ativa, atualizar testadoEm
|
// Se o teste foi bem-sucedido e há uma config ativa, atualizar testadoEm
|
||||||
if (resultado.sucesso) {
|
if (resultado.sucesso) {
|
||||||
const configAtiva = await ctx.db
|
const configAtiva = await ctx.runQuery(api.configuracaoEmail.obterConfigEmail, {});
|
||||||
.query("configuracaoEmail")
|
|
||||||
.withIndex("by_ativo", (q) => q.eq("ativo", true))
|
|
||||||
.first();
|
|
||||||
|
|
||||||
if (configAtiva) {
|
if (configAtiva) {
|
||||||
await ctx.db.patch(configAtiva._id, {
|
await ctx.runMutation(internal.configuracaoEmail.atualizarTestadoEm, {
|
||||||
testadoEm: Date.now(),
|
configId: configAtiva._id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultado;
|
return resultado;
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
return {
|
return {
|
||||||
sucesso: false as const,
|
sucesso: false as const,
|
||||||
erro: error.message || "Erro ao conectar com o servidor SMTP"
|
erro: errorMessage || "Erro ao conectar com o servidor SMTP"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user