Files
claboral.linkedcorp.net/backend/src/routes/superadmin.js
T
2026-03-03 11:54:00 -05:00

181 lines
6.7 KiB
JavaScript

const express = require('express');
const { authRequired } = require('../middleware/auth');
const { requireRole } = require('../middleware/rbac');
const { getCentralPool } = require('../db/central');
const { provisionTenant } = require('../services/tenantProvision');
const { getTenantPool } = require('../db/tenant');
const { hashPassword } = require('../utils/password');
const { getParticipationSummary } = require('../services/participationService');
const router = express.Router();
router.get('/companies', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const central = getCentralPool();
const [rows] = await central.query('SELECT id, name, code, status, start_date, end_date, db_host, db_port, db_name, created_at FROM companies ORDER BY id DESC');
res.json(rows);
} catch (err) {
next(err);
}
});
router.post('/companies', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const { name, code, start_date, end_date, db_name, db_host, db_port, db_user, db_pass, admin_name, admin_email, admin_password } = req.body;
if (!name || !code || !db_name || !db_host || !db_user || !db_pass || !admin_name || !admin_email || !admin_password) {
return res.status(400).json({ error: 'Faltan campos requeridos' });
}
if (!start_date || !end_date) {
return res.status(400).json({ error: 'Fecha inicio y fin son obligatorias' });
}
if (start_date > end_date) {
return res.status(400).json({ error: 'Fecha inicio no puede ser mayor que fecha fin' });
}
await provisionTenant({
name,
code,
dbName: db_name,
dbHost: db_host,
dbPort: db_port || 3306,
dbUser: db_user,
dbPass: db_pass,
adminName: admin_name,
adminEmail: admin_email,
adminPassword: admin_password,
startDate: start_date,
endDate: end_date
});
res.json({ ok: true });
} catch (err) {
next(err);
}
});
router.patch('/companies/:id/status', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const { status } = req.body;
if (!['active', 'suspended'].includes(status)) {
return res.status(400).json({ error: 'Estado inválido' });
}
const central = getCentralPool();
await central.query('UPDATE companies SET status = ? WHERE id = ?', [status, req.params.id]);
res.json({ ok: true });
} catch (err) {
next(err);
}
});
router.patch('/companies/:id/dates', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const { start_date, end_date } = req.body;
if (!start_date || !end_date) {
return res.status(400).json({ error: 'Fecha inicio y fin son obligatorias' });
}
if (start_date > end_date) {
return res.status(400).json({ error: 'Fecha inicio no puede ser mayor que fecha fin' });
}
const central = getCentralPool();
await central.query('UPDATE companies SET start_date = ?, end_date = ? WHERE id = ?', [
start_date || null,
end_date || null,
req.params.id
]);
res.json({ ok: true });
} catch (err) {
next(err);
}
});
router.get('/companies/:id/participation', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const central = getCentralPool();
const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]);
if (!company) return res.status(404).json({ error: 'Empresa no encontrada' });
const tenantPool = getTenantPool(company);
const participation = await getParticipationSummary(tenantPool);
res.json({ company_id: company.id, participation });
} catch (err) {
next(err);
}
});
router.delete('/companies/:id', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const central = getCentralPool();
const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]);
if (!company) return res.status(404).json({ error: 'Empresa no encontrada' });
const tenantPool = getTenantPool(company);
const [[{ periods }]] = await tenantPool.query('SELECT COUNT(*) AS periods FROM survey_periods');
const [[{ responses }]] = await tenantPool.query('SELECT COUNT(*) AS responses FROM responses');
if (periods > 0 || responses > 0) {
return res.status(400).json({ error: 'No se puede eliminar: existen encuestas registradas' });
}
await central.query('DROP DATABASE IF EXISTS `' + company.db_name + '`');
await central.query('DELETE FROM companies WHERE id = ?', [company.id]);
res.json({ ok: true });
} catch (err) {
next(err);
}
});
router.post('/companies/:id/admins', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const { name, email, password } = req.body;
if (!name || !email || !password) {
return res.status(400).json({ error: 'Nombre, email y password requeridos' });
}
const central = getCentralPool();
const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]);
if (!company) return res.status(404).json({ error: 'Empresa no encontrada' });
const tenantPool = getTenantPool(company);
const passwordHash = await hashPassword(password);
await tenantPool.query(
'INSERT INTO admins (name, email, password_hash, role, status) VALUES (?, ?, ?, "admin", "active")',
[name, email, passwordHash]
);
res.json({ ok: true });
} catch (err) {
next(err);
}
});
router.get('/companies/:id/admins', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const central = getCentralPool();
const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]);
if (!company) return res.status(404).json({ error: 'Empresa no encontrada' });
const tenantPool = getTenantPool(company);
const [rows] = await tenantPool.query('SELECT id, name, email, status, created_at FROM admins ORDER BY id DESC');
res.json(rows);
} catch (err) {
next(err);
}
});
router.patch('/companies/:id/admins/:adminId/status', authRequired, requireRole('superadmin'), async (req, res, next) => {
try {
const { status } = req.body;
if (!['active', 'inactive'].includes(status)) {
return res.status(400).json({ error: 'Estado inválido' });
}
const central = getCentralPool();
const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]);
if (!company) return res.status(404).json({ error: 'Empresa no encontrada' });
const tenantPool = getTenantPool(company);
await tenantPool.query('UPDATE admins SET status = ? WHERE id = ?', [status, req.params.adminId]);
res.json({ ok: true });
} catch (err) {
next(err);
}
});
module.exports = router;