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>
This commit is contained in:
@@ -1,5 +1,18 @@
|
||||
# Changelog - project.linkedcorp.net
|
||||
|
||||
## [2.10.1] - 2026-10-12
|
||||
### Fixed
|
||||
- "Probar correo" en Configuración → Correo mostraba "Error interno" en vez de un mensaje
|
||||
claro cuando la clave SMTP guardada no se podía descifrar (por ejemplo, un servidor que
|
||||
restauró un dump de otro con su propia `ENCRYPTION_KEY` — el caso de exilaser). Ahora indica
|
||||
que hay que volver a escribir y guardar la clave.
|
||||
- El mismo problema podía tumbar silenciosamente cualquier envío real (recuperar contraseña,
|
||||
verificación de registro, invitaciones) en vez de degradar a modo dev como está documentado
|
||||
que debe pasar sin SMTP utilizable — ya degrada correctamente.
|
||||
- `trust proxy` configurado en Express (la app corre detrás de Nginx Proxy Manager): sin esto,
|
||||
el límite de intentos (login, SMTP, etc.) compartía un solo cupo entre todos los usuarios en
|
||||
vez de uno por persona, y cada request dejaba un aviso de validación en los logs.
|
||||
|
||||
## [2.10.0] - 2026-10-12
|
||||
### Added
|
||||
- Rediseño del módulo "Notas": ahora se ven como tarjetas (resumen del contenido), con una
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "project-linkedcorp-backend",
|
||||
"version": "2.10.0",
|
||||
"version": "2.10.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/server.js",
|
||||
|
||||
@@ -27,6 +27,11 @@ 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' }));
|
||||
|
||||
@@ -26,12 +26,22 @@ export async function getSmtpConfig() {
|
||||
export async function getSmtpConfigInternal() {
|
||||
const values = await repo.getAll(SMTP_KEYS);
|
||||
if (!values.smtp_host || !values.smtp_user || !values.smtp_pass_enc) return null;
|
||||
let pass;
|
||||
try {
|
||||
pass = decrypt(values.smtp_pass_enc);
|
||||
} catch {
|
||||
// ENCRYPTION_KEY distinta a la que se uso para guardar (ej. un dump restaurado en otro
|
||||
// servidor, caso exilaser) -- se trata como "no configurado" para no tumbar al que llama
|
||||
// (mailer.js degrada solo a modo dev, nunca debe romper forgot-password/registro/etc.).
|
||||
console.error('[smtp] no se pudo descifrar smtp_pass_enc -- revisa ENCRYPTION_KEY o vuelve a guardar la clave SMTP desde Configuracion');
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
host: values.smtp_host,
|
||||
port: values.smtp_port ? Number(values.smtp_port) : 587,
|
||||
user: values.smtp_user,
|
||||
from: values.smtp_from || values.smtp_user,
|
||||
pass: decrypt(values.smtp_pass_enc),
|
||||
pass,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,7 +79,14 @@ export async function testSmtpConfig(payload, actorId) {
|
||||
if (!pass) {
|
||||
const stored = await repo.getAll(['smtp_pass_enc']);
|
||||
if (!stored.smtp_pass_enc) throw new HttpError(400, 'No hay una clave guardada ni escrita para probar');
|
||||
try {
|
||||
pass = decrypt(stored.smtp_pass_enc);
|
||||
} catch {
|
||||
// Pasa si ENCRYPTION_KEY cambio desde que se guardo (ej. un dump restaurado en otro
|
||||
// servidor con su propia clave, como exilaser) -- sin este catch tiraba un error generico
|
||||
// sin pista de como resolverlo.
|
||||
throw new HttpError(400, 'No se pudo descifrar la clave SMTP guardada (puede que se haya guardado con otra clave de cifrado). Vuelve a escribirla y guarda de nuevo.');
|
||||
}
|
||||
}
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "project-linkedcorp-frontend",
|
||||
"private": true,
|
||||
"version": "2.10.0",
|
||||
"version": "2.10.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
Reference in New Issue
Block a user