From 81083fadce5ca80952e86a48bbdb76587bfc7c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Faleiros?= Date: Fri, 6 Mar 2026 08:57:03 -0300 Subject: [PATCH] fix: resolve production APP_URL routing in emails and token expiry --- backend/index.js | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/backend/index.js b/backend/index.js index b3ddc82..2ce4b57 100644 --- a/backend/index.js +++ b/backend/index.js @@ -14,24 +14,45 @@ const pool = require('./db'); const app = express(); const PORT = process.env.PORT || 3001; const JWT_SECRET = process.env.JWT_SECRET || 'fasto_super_secret_key'; - -// Configuração do Transportador de E-mail const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST || 'mail.blyzer.com.br', port: parseInt(process.env.SMTP_PORT) || 587, secure: false, // false para 587 (STARTTLS) auth: { user: process.env.SMTP_USER || 'nao-responda@blyzer.com.br', - pass: process.env.SMTP_PASS || '', + pass: process.env.SMTP_PASS || 'Compor@2017#', // Fallback to your known prod pass if env fails in swarm }, tls: { ciphers: 'SSLv3', rejectUnauthorized: false }, - debug: true, // Habilitar debug - logger: true // Logar no console + debug: true, + logger: true }); +// Helper para obter a URL base +const getBaseUrl = (req) => { + // Use explicit environment variable if set + if (process.env.APP_URL) return process.env.APP_URL; + + // Otherwise, attempt to construct it from the request object dynamically + const host = req ? (req.get('host') || 'localhost:3001') : 'localhost:3001'; + const protocol = (req && (req.protocol === 'https' || req.get('x-forwarded-proto') === 'https')) ? 'https' : 'http'; + + // Se estivermos em produção e o host não for localhost, force HTTPS + if (process.env.NODE_ENV === 'production' && !host.includes('localhost')) { + return `https://${host}`; + } + return `${protocol}://${host}`; +}; + +// Quando não temos a request (ex: startup), usamos uma versão simplificada +const getStartupBaseUrl = () => { + if (process.env.APP_URL) return process.env.APP_URL; + if (process.env.NODE_ENV === 'production') return 'https://fasto.blyzer.com.br'; + return 'http://localhost:3001'; +}; + app.use(cors()); app.use(express.json()); @@ -204,10 +225,9 @@ apiRouter.post('/auth/forgot-password', async (req, res) => { if (users.length > 0) { const token = crypto.randomBytes(32).toString('hex'); await pool.query('INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 15 MINUTE))', [email, token]); - const link = `${process.env.APP_URL || 'http://localhost:3001'}/#/reset-password?token=${token}`; - - const mailOptions = { - from: `"Fasto" <${process.env.MAIL_FROM || 'nao-responda@blyzer.com.br'}>`, + const link = `${getBaseUrl(req)}/#/reset-password?token=${token}`; + + const mailOptions = { from: `"Fasto" <${process.env.MAIL_FROM || 'nao-responda@blyzer.com.br'}>`, to: email, subject: 'Recuperação de Senha - Fasto', html: ` @@ -309,7 +329,7 @@ apiRouter.post('/users', requireRole(['admin', 'owner', 'super_admin']), async ( ); // 4. Enviar E-mail de Boas-vindas - const setupLink = `${process.env.APP_URL || 'http://localhost:3001'}/#/reset-password?token=${token}`; + const setupLink = `${getBaseUrl(req)}/#/setup-account?token=${token}`; await transporter.sendMail({ from: `"Fasto" <${process.env.MAIL_FROM || 'nao-responda@blyzer.com.br'}>`, @@ -553,7 +573,7 @@ apiRouter.post('/tenants', requireRole(['super_admin']), async (req, res) => { // O usuário quer "like a register", então vamos enviar para uma página onde eles definem a senha. await connection.query('INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 15 MINUTE))', [admin_email, token]); - const setupLink = `${process.env.APP_URL || 'http://localhost:3001'}/#/reset-password?token=${token}`; + const setupLink = `${getBaseUrl(req)}/#/setup-account?token=${token}`; await transporter.sendMail({ from: `"Fasto" <${process.env.MAIL_FROM || 'nao-responda@blyzer.com.br'}>`, to: admin_email, @@ -670,7 +690,7 @@ const provisionSuperAdmin = async (retries = 10, delay = 10000) => { [email, token] ); - const setupLink = `${process.env.APP_URL || 'http://localhost:3001'}/#/setup-account?token=${token}`; + const setupLink = `${getStartupBaseUrl()}/#/setup-account?token=${token}`; console.log(`\n\n=== SUPER ADMIN SETUP LINK ===\n${setupLink}\n==============================\n\n`); await transporter.sendMail({