feat: RLA API v1.0.0 — API complète + exports + thème McKinsey

- 9 endpoints métier : synthese, alertes, en-service, en-cours,
  par-region, clotures, pilotage-proactif, matrice-risque
- Exports PDF (tous rôles) / XLSX PPTX DOCX (superadmin)
- services/calc.js : helpers normalisés partagés
- services/export-pdf.js : PDF async PDFKit par vue
- Thème McKinsey (#1C2B4B / bleu pétrole / gris sobre)
- Boutons XLSX/DOCX front (superadmin uniquement)
- BASEROW_API_URL → https://baserow.bolbol.tn/api/
- dotenv override: true

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Nabil Derouiche
2026-03-12 23:47:10 +01:00
co-authored by Claude Sonnet 4.6
commit 88a0dbe6d2
39 changed files with 7622 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const { getUsers } = require('../services/users');
const { logLogin } = require('../services/logs');
// POST /api/auth/login
router.post('/login', async (req, res) => {
const { username, password } = req.body || {};
const ip = req.ip || req.socket?.remoteAddress || null;
const user = getUsers().find(u => u.username === username);
if (!user) {
logLogin({ username: username || '?', role: null, ip, success: false });
return res.status(401).json({ error: 'Identifiants invalides' });
}
const valid = await bcrypt.compare(password || '', user.password);
if (!valid) {
logLogin({ username, role: user.role, ip, success: false });
return res.status(401).json({ error: 'Identifiants invalides' });
}
logLogin({ username, role: user.role, ip, success: true });
const token = jwt.sign(
{ sub: user.username, id: user.id, username: user.username, role: user.role, region: user.region },
process.env.JWT_SECRET,
{ expiresIn: '8h' }
);
res.json({ token });
});
module.exports = router;