104 lines
4.8 KiB
JavaScript
104 lines
4.8 KiB
JavaScript
const express = require('express');
|
|
const crypto = require('crypto');
|
|
const { requireRole } = require('../middleware/auth');
|
|
const { recordActivity } = require('../services/activityService');
|
|
|
|
const createTenantsRouter = ({ pool, transporter, getBaseUrl }) => {
|
|
const router = express.Router();
|
|
|
|
router.get('/tenants', requireRole(['super_admin']), async (req, res) => {
|
|
try {
|
|
const q = 'SELECT t.*, (SELECT COUNT(*) FROM users u WHERE u.tenant_id = t.id) as user_count, (SELECT COUNT(*) FROM attendances a WHERE a.tenant_id = t.id) as attendance_count FROM tenants t';
|
|
const [rows] = await pool.query(q);
|
|
res.json(rows);
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
router.post('/tenants', requireRole(['super_admin']), async (req, res) => {
|
|
const { name, slug, admin_email, status } = req.body;
|
|
const connection = await pool.getConnection();
|
|
try {
|
|
await connection.beginTransaction();
|
|
const tid = `tenant_${crypto.randomUUID().split('-')[0]}`;
|
|
await connection.query('INSERT INTO tenants (id, name, slug, admin_email, status) VALUES (?, ?, ?, ?, ?)', [tid, name, slug, admin_email, status || 'active']);
|
|
|
|
const [existingUser] = await connection.query('SELECT id FROM users WHERE email = ?', [admin_email]);
|
|
if (existingUser.length === 0) {
|
|
const uid = `u_${crypto.randomUUID().split('-')[0]}`;
|
|
const userSlug = `admin-${crypto.randomBytes(4).toString('hex')}`;
|
|
const placeholderHash = 'pending_setup';
|
|
await connection.query('INSERT INTO users (id, tenant_id, name, email, password_hash, slug, role) VALUES (?, ?, ?, ?, ?, ?, ?)', [uid, tid, 'Admin', admin_email, placeholderHash, userSlug, 'admin']);
|
|
|
|
const token = crypto.randomBytes(32).toString('hex');
|
|
await connection.query('INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 15 MINUTE))', [admin_email, token]);
|
|
|
|
const setupLink = `${getBaseUrl(req)}/#/setup-account?token=${token}`;
|
|
|
|
const [superAdmins] = await connection.query("SELECT id FROM users WHERE role = 'super_admin'");
|
|
for (const sa of superAdmins) {
|
|
await recordActivity(connection, {
|
|
userId: sa.id,
|
|
type: 'success',
|
|
title: 'Nova Organização',
|
|
message: `A organização ${name} foi criada.`,
|
|
link: '/super-admin',
|
|
});
|
|
}
|
|
|
|
await transporter.sendMail({
|
|
from: `"Fasto" <${process.env.MAIL_FROM || 'nao-responda@blyzer.com.br'}>`,
|
|
to: admin_email,
|
|
subject: 'Bem-vindo ao Fasto - Conclua seu cadastro de Admin',
|
|
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;">Sua organização foi criada</h2>
|
|
<p style="color: #475569;">Você foi definido como administrador da organização <strong>${name}</strong>.</p>
|
|
<p style="color: #475569;">Por favor, clique no botão abaixo para definir sua senha e concluir seu cadastro.</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>
|
|
`
|
|
}).catch(err => console.error("Email failed:", err));
|
|
}
|
|
|
|
await connection.commit();
|
|
res.status(201).json({ id: tid, message: 'Organização criada e convite enviado por e-mail.' });
|
|
} catch (error) {
|
|
await connection.rollback();
|
|
res.status(500).json({ error: error.message });
|
|
} finally {
|
|
connection.release();
|
|
}
|
|
});
|
|
|
|
router.put('/tenants/:id', requireRole(['super_admin']), async (req, res) => {
|
|
const { name, slug, admin_email, status } = req.body;
|
|
try {
|
|
await pool.query(
|
|
'UPDATE tenants SET name = ?, slug = ?, admin_email = ?, status = ? WHERE id = ?',
|
|
[name, slug || null, admin_email, status, req.params.id]
|
|
);
|
|
res.json({ message: 'Tenant updated successfully.' });
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
router.delete('/tenants/:id', requireRole(['super_admin']), async (req, res) => {
|
|
try {
|
|
await pool.query('DELETE FROM tenants WHERE id = ?', [req.params.id]);
|
|
res.json({ message: 'Tenant deleted successfully.' });
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
return router;
|
|
};
|
|
|
|
module.exports = { createTenantsRouter };
|