Files
project.linkedcorp.net/backend/src/app.js
T
Milton Gonzalez da4d83e7cc fix: version 2.10.1 -- "Probar correo" tiraba Error interno si la clave SMTP no descifraba
El decrypt() de la clave SMTP guardada estaba fuera del try/catch tanto en testSmtpConfig
(el boton "Probar") como en getSmtpConfigInternal (usado por el mailer real para forgot-
password, registro, invitaciones). Si ENCRYPTION_KEY no coincide con la que se uso para
guardar -- el caso documentado de exilaser, que recibio un dump de LinkedCorp con su propia
clave -- el fallo de decrypt() se propagaba sin control: "Error interno" generico en el boton
de prueba, y un crash silencioso en el envio real en vez de la degradacion a modo dev que el
propio comentario del codigo promete. Ambos casos ahora devuelven un mensaje claro / degradan
correctamente.

De paso se agrega `app.set('trust proxy', 1)`: la app corre detras de Nginx Proxy Manager pero
Express no lo sabia, asi que express-rate-limit usaba la IP del proxy para todos los clientes
(un cupo compartido en vez de uno por usuario) y tiraba un aviso de validacion en cada request.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-12 12:26:00 -05:00

67 lines
3.0 KiB
JavaScript

import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import { env } from './config/env.js';
import { notFoundHandler, errorHandler } from './middleware/errorHandler.js';
import authRoutes from './modules/auth/routes.js';
import usersRoutes from './modules/users/routes.js';
import departmentsRoutes from './modules/departments/routes.js';
import catalogsRoutes from './modules/catalogs/routes.js';
import projectsRoutes from './modules/projects/routes.js';
import activitiesRoutes from './modules/activities/routes.js';
import tasksRoutes from './modules/tasks/routes.js';
import commentsRoutes from './modules/comments/routes.js';
import attachmentsRoutes from './modules/attachments/routes.js';
import notificationsRoutes from './modules/notifications/routes.js';
import dashboardRoutes from './modules/dashboard/routes.js';
import auditRoutes from './modules/audit/routes.js';
import settingsRoutes from './modules/settings/routes.js';
import companyRoutes from './modules/company/routes.js';
import recurringTasksRoutes from './modules/recurring-tasks/routes.js';
import searchRoutes from './modules/search/routes.js';
import updaterRoutes from './modules/updater/routes.js';
import errorLogsRoutes from './modules/errorLogs/routes.js';
import notesRoutes from './modules/notes/routes.js';
import vaultRoutes from './modules/vault/routes.js';
export const app = express();
// Produccion (y exilaser) corren detras de Nginx Proxy Manager (un solo salto). Sin esto,
// express-rate-limit usa la IP del proxy para TODOS los clientes (un balde compartido en vez
// de uno por usuario) y ademas tira un ValidationError que ensucia los logs en cada request.
app.set('trust proxy', 1);
app.use(helmet({ contentSecurityPolicy: false }));
app.use(cors({ origin: env.corsOrigin, credentials: true }));
app.use(express.json({ limit: '2mb' }));
app.get('/health', (req, res) => res.json({ success: true, data: { status: 'ok' }, error: null }));
app.use('/api/auth', authRoutes);
app.use('/api/users', usersRoutes);
app.use('/api/departments', departmentsRoutes);
app.use('/api/catalogs', catalogsRoutes);
app.use('/api/projects', projectsRoutes);
app.use('/api/activities', activitiesRoutes);
app.use('/api/comments', commentsRoutes);
app.use('/api/attachments', attachmentsRoutes);
app.use('/api/notifications', notificationsRoutes);
app.use('/api/dashboard', dashboardRoutes);
app.use('/api/audit', auditRoutes);
app.use('/api/settings', settingsRoutes);
app.use('/api/company', companyRoutes);
app.use('/api/recurring-tasks', recurringTasksRoutes);
app.use('/api/search', searchRoutes);
app.use('/api/updater', updaterRoutes);
app.use('/api/error-logs', errorLogsRoutes);
app.use('/api/notes', notesRoutes);
app.use('/api/vault', vaultRoutes);
// Mas generico (mount en /api sin sub-path propio) — SIEMPRE al final de los /api/*, para no
// interceptar con su requireAuth interno una ruta que en realidad pertenece a un router mas
// especifico registrado despues (ver ESTADO.md, deuda tecnica).
app.use('/api', tasksRoutes);
app.use(notFoundHandler);
app.use(errorHandler);