From 7009d8756d88a2832b72a6989e1309339f105ad2 Mon Sep 17 00:00:00 2001 From: Nurfog Date: Wed, 16 Sep 2026 11:31:22 -0300 Subject: [PATCH] =?UTF-8?q?refactor:=20gesti=C3=B3n=20de=20m=C3=B3dulos=20?= =?UTF-8?q?de=20correo=20al=20portal=20IT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../src/app/(app)/settings/email/page.tsx | 155 +----------------- frontend/src/lib/api.ts | 22 --- 3 files changed, 4 insertions(+), 175 deletions(-) diff --git a/README.md b/README.md index 00ac8d6..4d6aede 100644 --- a/README.md +++ b/README.md @@ -83,5 +83,5 @@ Base: `NEXT_PUBLIC_API_URL/api/helpdesk` - `GET|POST /users` · `PUT /users/{id}` (admin) - `GET|POST /sla` · `PUT /sla/{id}` (admin) - `GET /notifications?module=&limit=&unreadOnly=` · `GET /notifications/unread-count?module=` · `PUT /notifications/{id}/read` · `PUT /notifications/read-all?module=` (propias, estándar multi-módulo `mail.notifications`, campana con polling 60s + color por módulo) · `POST /notifications/send` (módulos con `X-Module` + `X-Api-Key`) -- `GET /email/templates` · `POST /email/templates` · `PUT /email/templates/{key}` · `GET /email/log?module=helpdesk&limit=` · `GET|POST /email/modules` · `DELETE /email/modules/{m}` (admin, banco único `mail.*`) +- `GET /email/templates` · `POST /email/templates` · `PUT /email/templates/{key}` · `GET /email/log?module=helpdesk&limit=` (admin, banco único `mail.*`; las claves de módulos se gestionan en el portal IT) - `POST /api/correos` (route propio server-side → `POST /api/email/send` con `X-Module: helpdesk` + `X-Api-Key`) · `POST /helpdesk/email/inbound/sync` (admin, inbound Gmail sin cambios) diff --git a/frontend/src/app/(app)/settings/email/page.tsx b/frontend/src/app/(app)/settings/email/page.tsx index cc98f89..d41a1c3 100644 --- a/frontend/src/app/(app)/settings/email/page.tsx +++ b/frontend/src/app/(app)/settings/email/page.tsx @@ -8,12 +8,8 @@ import { getEmailLog, sendTestEmail, syncInboundEmail, - getEmailModules, - registerEmailModule, - revokeEmailModule, type EmailTemplate, type EmailLogEntry, - type EmailModule, } from "@/lib/api"; import { useAuth } from "@/lib/auth"; import Modal from "@/components/Modal"; @@ -36,7 +32,6 @@ export default function EmailPage() { const { user, isLoading: authLoading } = useAuth(); const [templates, setTemplates] = useState([]); const [log, setLog] = useState([]); - const [modules, setModules] = useState([]); const [logModule, setLogModule] = useState("helpdesk"); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); @@ -56,15 +51,6 @@ export default function EmailPage() { const [newModule, setNewModule] = useState("helpdesk"); const [creating, setCreating] = useState(false); const [createError, setCreateError] = useState(""); - // Módulos (GET/POST/DELETE /api/email/modules) - const [newModuleName, setNewModuleName] = useState(""); - const [registering, setRegistering] = useState(false); - const [registerResult, setRegisterResult] = useState<{ - ok: boolean; - text: string; - apiKey?: string; - } | null>(null); - const [revoking, setRevoking] = useState(null); const [testTo, setTestTo] = useState(""); const [testResult, setTestResult] = useState<{ ok: boolean; text: string } | null>(null); const [testing, setTesting] = useState(false); @@ -75,19 +61,16 @@ export default function EmailPage() { setLoading(true); setError(""); try { - const [t, l, m] = await Promise.all([ + const [t, l] = await Promise.all([ getEmailTemplates(), getEmailLog(50, logModule), - getEmailModules(), ]); setTemplates(t); setLog(l); - setModules(m); } catch (err) { setError(err instanceof Error ? err.message : "Error al cargar"); setTemplates([]); setLog([]); - setModules([]); } finally { setLoading(false); } @@ -95,22 +78,16 @@ export default function EmailPage() { useEffect(() => { if (authLoading || user?.role !== "admin") return; - Promise.all([ - getEmailTemplates(), - getEmailLog(50, logModule), - getEmailModules(), - ]) - .then(([t, l, m]) => { + Promise.all([getEmailTemplates(), getEmailLog(50, logModule)]) + .then(([t, l]) => { setTemplates(t); setLog(l); - setModules(m); setError(""); }) .catch((err) => { setError(err instanceof Error ? err.message : "Error al cargar"); setTemplates([]); setLog([]); - setModules([]); }) .finally(() => setLoading(false)); }, [authLoading, user?.role, logModule]); @@ -191,43 +168,6 @@ export default function EmailPage() { } }; - const handleRegister = async () => { - const modName = newModuleName.trim().toLowerCase(); - if (!/^[a-z0-9-]{2,32}$/.test(modName)) { - setRegisterResult({ ok: false, text: "Módulo inválido ([a-z0-9-], 2-32)" }); - return; - } - setRegistering(true); - setRegisterResult(null); - try { - const r = await registerEmailModule(modName); - setRegisterResult({ - ok: true, - text: `Clave de "${r.module}" generada. Se muestra una sola vez.`, - apiKey: r.apiKey, - }); - setNewModuleName(""); - fetchData(); - } catch (err) { - setRegisterResult({ ok: false, text: err instanceof Error ? err.message : "Error al registrar" }); - } finally { - setRegistering(false); - } - }; - - const handleRevoke = async (modName: string) => { - if (!window.confirm(`¿Revocar la clave del módulo "${modName}"? Dejará de poder usar POST /api/email/send.`)) return; - setRevoking(modName); - try { - await revokeEmailModule(modName); - fetchData(); - } catch (err) { - setRegisterResult({ ok: false, text: err instanceof Error ? err.message : "Error al revocar" }); - } finally { - setRevoking(null); - } - }; - const handleTest = async () => { if (!testTo.trim() || !testTo.includes("@")) { setTestResult({ ok: false, text: "Destino inválido" }); @@ -361,95 +301,6 @@ export default function EmailPage() { -
-
-
- - Módulos autorizados -
- {registerResult && ( -
- {registerResult.text} - {registerResult.apiKey && ( -
- {registerResult.apiKey} -
- Guárdala en el .env del módulo como MAIL_API_KEY. No se vuelve a mostrar. - Registrar de nuevo rota la clave anterior. -
-
- )} -
- )} - {modules.length > 0 && ( -
- - - - - - - - - - {modules.map((m) => ( - - - - - - ))} - -
MóduloEstadoAcciones
- {m.module} - - {m.isActive ? ( - Activo - ) : ( - Revocado - )} - - -
-
- )} -
- setNewModuleName(e.target.value)} - style={{ maxWidth: 320 }} - /> - -
- - La clave plana se muestra una sola vez (POST /api/email/modules). - -
-
-
diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 6f0c30b..385ba79 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -361,11 +361,6 @@ export interface EmailLogEntry { createdAt: string; } -export interface EmailModule { - module: string; - isActive: boolean; -} - export async function getEmailTemplates() { return fetchApi("/api/email/templates"); } @@ -399,23 +394,6 @@ export async function getEmailLog(limit = 50, module = "helpdesk") { return fetchApi(`/api/email/log?${query.toString()}`); } -export async function getEmailModules() { - return fetchApi("/api/email/modules"); -} - -export async function registerEmailModule(module: string) { - return fetchApi<{ module: string; apiKey: string }>("/api/email/modules", { - method: "POST", - body: JSON.stringify({ module }), - }); -} - -export async function revokeEmailModule(module: string) { - return fetchApi<{ module: string }>(`/api/email/modules/${encodeURIComponent(module)}`, { - method: "DELETE", - }); -} - // Envío vía route handler propio (/api/correos) → POST /api/email/send con // X-Module + X-Api-Key en el servidor (la clave nunca va en el bundle). // Reenvía el Bearer de admin para que el route verifique el rol.