fix: resolve production SMTP environment mapping and super_admin provisioning recovery
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m24s

This commit is contained in:
Cauê Faleiros
2026-03-05 16:11:02 -03:00
parent c4bd4d58a1
commit f7b019f1e1
2 changed files with 58 additions and 37 deletions

View File

@@ -609,50 +609,64 @@ if (process.env.NODE_ENV === 'production') {
}
// Auto-provision Super Admin
const provisionSuperAdmin = async () => {
const provisionSuperAdmin = async (retries = 5, delay = 5000) => {
const email = 'suporte@blyzer.com.br';
try {
// Ensure system tenant exists
await pool.query('INSERT IGNORE INTO tenants (id, name, slug, admin_email, status) VALUES (?, ?, ?, ?, ?)', ['system', 'System Admin', 'system', email, 'active']);
const [existing] = await pool.query('SELECT id FROM users WHERE email = ?', [email]);
if (existing.length === 0) {
console.log('Provisioning default super_admin...');
const uid = `u_${crypto.randomUUID().split('-')[0]}`;
const placeholderHash = 'pending_setup';
for (let i = 0; i < retries; i++) {
try {
// Test connection first
const connection = await pool.getConnection();
connection.release();
await pool.query(
'INSERT INTO users (id, tenant_id, name, email, password_hash, role, status) VALUES (?, ?, ?, ?, ?, ?, ?)',
[uid, 'system', 'Blyzer Suporte', email, placeholderHash, 'super_admin', 'active']
);
// Ensure system tenant exists
await pool.query('INSERT IGNORE INTO tenants (id, name, slug, admin_email, status) VALUES (?, ?, ?, ?, ?)', ['system', 'System Admin', 'system', email, 'active']);
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 [existing] = await pool.query('SELECT id, password_hash FROM users WHERE email = ?', [email]);
if (existing.length === 0 || existing[0].password_hash === 'pending_setup') {
console.log('Provisioning default super_admin or resending email...');
const setupLink = `${process.env.APP_URL || 'http://localhost:3001'}/#/reset-password?token=${token}`;
console.log(`\n\n=== SUPER ADMIN SETUP LINK ===\n${setupLink}\n==============================\n\n`);
if (existing.length === 0) {
const uid = `u_${crypto.randomUUID().split('-')[0]}`;
const placeholderHash = 'pending_setup';
await transporter.sendMail({
from: `"Fasto" <${process.env.MAIL_FROM || 'nao-responda@blyzer.com.br'}>`,
to: email,
subject: 'Conta Super Admin Criada - Fasto',
html: `
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e2e8f0; border-radius: 12px; background: #ffffff; color: #0f172a;">
<h2 style="color: #0f172a;">Conta Super Admin Gerada</h2>
<p style="color: #475569;">Sua conta de suporte (super_admin) foi criada no Fasto.</p>
<div style="text-align: center; margin: 30px 0;">
<a href="${setupLink}" style="background-color: #0f172a; color: white; padding: 12px 24px; text-decoration: none; border-radius: 8px; font-weight: bold; display: inline-block;">Finalizar Cadastro</a>
await pool.query(
'INSERT INTO users (id, tenant_id, name, email, password_hash, role, status) VALUES (?, ?, ?, ?, ?, ?, ?)',
[uid, 'system', 'Blyzer Suporte', email, placeholderHash, 'super_admin', 'active']
);
}
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 setupLink = `${process.env.APP_URL || 'http://localhost:3001'}/#/reset-password?token=${token}`;
console.log(`\n\n=== SUPER ADMIN SETUP LINK ===\n${setupLink}\n==============================\n\n`);
await transporter.sendMail({
from: `"Fasto" <${process.env.MAIL_FROM || 'nao-responda@blyzer.com.br'}>`,
to: email,
subject: 'Conta Super Admin Criada - Fasto',
html: `
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e2e8f0; border-radius: 12px; background: #ffffff; color: #0f172a;">
<h2 style="color: #0f172a;">Conta Super Admin Gerada</h2>
<p style="color: #475569;">Sua conta de suporte (super_admin) foi criada no Fasto.</p>
<div style="text-align: center; margin: 30px 0;">
<a href="${setupLink}" style="background-color: #0f172a; color: white; padding: 12px 24px; text-decoration: none; border-radius: 8px; font-weight: bold; display: inline-block;">Finalizar Cadastro</a>
</div>
<p style="font-size: 12px; color: #94a3b8;">Este link expira em 15 minutos.</p>
</div>
<p style="font-size: 12px; color: #94a3b8;">Este link expira em 15 minutos.</p>
</div>
`
}).catch(err => console.error("Failed to send super_admin email:", err));
`
}).catch(err => console.error("Failed to send super_admin email:", err));
}
return; // Success, exit the retry loop
} catch (error) {
console.error(`Failed to provision super_admin (Attempt ${i + 1}/${retries}):`, error.message);
if (i < retries - 1) {
await new Promise(res => setTimeout(res, delay));
}
}
} catch (error) {
console.error('Failed to provision super_admin:', error);
}
};

View File

@@ -10,6 +10,13 @@ services:
- DB_USER=${DB_USER:-root}
- DB_PASSWORD=${DB_PASSWORD:-root_password}
- DB_NAME=${DB_NAME:-agenciac_comia}
- SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=${SMTP_PORT}
- SMTP_USER=${SMTP_USER}
- SMTP_PASS=${SMTP_PASS}
- MAIL_FROM=${MAIL_FROM}
- APP_URL=${APP_URL}
- JWT_SECRET=${JWT_SECRET}
ports:
- "3001:3001"
deploy: