confluent/ConfluentTranslator/adminRoutes.js
StillHammer 3cd73e6598 Ajout système d'authentification complet avec interface de connexion
Backend:
- auth.js: Système de tokens avec API keys UUID
- rateLimiter.js: Rate limiting multi-tiers (global, traduction, admin)
- logger.js: Logging des requêtes avec rotation automatique
- adminRoutes.js: Routes admin pour gestion des tokens
- server.js: Intégration de tous les middlewares de sécurité

Frontend:
- Interface de connexion modale élégante
- Stockage sécurisé API key dans localStorage
- Bouton déconnexion dans le header
- authFetch() wrapper pour toutes les requêtes protégées
- Protection automatique des endpoints de traduction

Sécurité:
- Token admin généré automatiquement au premier lancement
- Limites quotidiennes par token configurables
- Rate limiting pour prévenir les abus
- Logs détaillés de toutes les requêtes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 12:01:01 +08:00

96 lines
2.4 KiB
JavaScript

const express = require('express');
const router = express.Router();
const { requireAdmin, createToken, listTokens, disableToken, enableToken, deleteToken, getGlobalStats } = require('./auth');
const { getLogs, getLogStats } = require('./logger');
const { adminLimiter } = require('./rateLimiter');
// Appliquer l'auth et rate limiting à toutes les routes admin
router.use(requireAdmin);
router.use(adminLimiter);
// Liste des tokens
router.get('/tokens', (req, res) => {
const tokens = listTokens();
res.json({ tokens });
});
// Créer un nouveau token
router.post('/tokens', (req, res) => {
const { name, role = 'user', dailyLimit = 100 } = req.body;
if (!name) {
return res.status(400).json({ error: 'Missing parameter: name' });
}
const token = createToken(name, role, dailyLimit);
res.json({
success: true,
token: {
...token,
apiKey: token.apiKey // Retourner la clé complète seulement à la création
}
});
});
// Désactiver un token
router.post('/tokens/:id/disable', (req, res) => {
const { id } = req.params;
const success = disableToken(id);
if (success) {
res.json({ success: true, message: 'Token disabled' });
} else {
res.status(404).json({ error: 'Token not found' });
}
});
// Réactiver un token
router.post('/tokens/:id/enable', (req, res) => {
const { id } = req.params;
const success = enableToken(id);
if (success) {
res.json({ success: true, message: 'Token enabled' });
} else {
res.status(404).json({ error: 'Token not found' });
}
});
// Supprimer un token
router.delete('/tokens/:id', (req, res) => {
const { id } = req.params;
const success = deleteToken(id);
if (success) {
res.json({ success: true, message: 'Token deleted' });
} else {
res.status(404).json({ error: 'Token not found or cannot be deleted' });
}
});
// Stats globales
router.get('/stats', (req, res) => {
const tokenStats = getGlobalStats();
const logStats = getLogStats();
res.json({
tokens: tokenStats,
logs: logStats
});
});
// Logs
router.get('/logs', (req, res) => {
const { limit = 100, user, path, statusCode } = req.query;
const filter = {};
if (user) filter.user = user;
if (path) filter.path = path;
if (statusCode) filter.statusCode = parseInt(statusCode);
const logs = getLogs(parseInt(limit), filter);
res.json({ logs });
});
module.exports = router;