chore: snapshot état initial API Gestion des Marchés RLA — V0

Version initiale de l'API complète :
- Frontend : index.html (thème McKinsey, tableau de bord dynamique)
- Backend Express : server.js, routes/, services/, middleware/
- Authentification JWT, rôles, logs
- Connexion Baserow (NAS 192.168.100.33)
- Export PDF/XLSX, statistiques, alertes, pilotage
- Docker : Dockerfile, .env.example

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Nabil Derouiche
2026-03-22 22:17:27 +01:00
co-authored by Claude Sonnet 4.6
commit 2be438f1f1
43 changed files with 7672 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
const jwt = require('jsonwebtoken');
module.exports = function authMiddleware(req, res, next) {
const header = req.headers['authorization'] || '';
const token = header.startsWith('Bearer ') ? header.slice(7) : null;
if (!token) {
return res.status(401).json({ error: 'Token manquant' });
}
try {
req.user = jwt.verify(token, process.env.JWT_SECRET);
next();
} catch {
res.status(401).json({ error: 'Token invalide ou expiré' });
}
};
+32
View File
@@ -0,0 +1,32 @@
module.exports = {
requireSuperAdmin(req, res, next) {
if (req.user?.role !== 'superadmin') {
return res.status(403).json({ error: 'Accès réservé au super-administrateur' });
}
next();
},
requireAdmin(req, res, next) {
if (!['superadmin', 'admin'].includes(req.user?.role)) {
return res.status(403).json({ error: 'Accès réservé aux administrateurs' });
}
next();
},
requireUser(req, res, next) {
if (!req.user?.role) {
return res.status(403).json({ error: 'Accès non autorisé' });
}
next();
},
// Injecte req.regionFilter : null = toutes régions, string = région filtrée
filterByRegion(req, res, next) {
req.regionFilter = (req.user?.role === 'user' && req.user.region !== 'all')
? req.user.region
: null;
next();
},
};