diff --git a/PRODUCTION_UPDATE_2025.md b/PRODUCTION_UPDATE_2025.md index 431a5cc..92c666e 100644 --- a/PRODUCTION_UPDATE_2025.md +++ b/PRODUCTION_UPDATE_2025.md @@ -59,6 +59,11 @@ curl http://localhost:5000/health - **Implémentation** : sslmode=disable dans DATABASE_URL - **Robustesse** : Détection automatique du mode SSL nécessaire +5. **Erreur Permissions Admin** : "Insufficient permissions" pour admin + - **Problème** : Incohérence entre rôle 'admin' en DB et 'administrator' dans code + - **Solution** : Mise à jour rôle admin vers 'administrator' et correction routes + - **Implémentation** : UPDATE users + correction toutes routes requireRole() + ### Status : ✅ RÉSOLU COMPLET Cette solution garantit un déploiement Docker fiable en production sans les problèmes de fichiers manquants, migrations échouées, ou erreurs SSL. diff --git a/attached_assets/image_1752936125571.png b/attached_assets/image_1752936125571.png new file mode 100644 index 0000000..f5963cc Binary files /dev/null and b/attached_assets/image_1752936125571.png differ diff --git a/replit.md b/replit.md index a20cf71..8df97ef 100644 --- a/replit.md +++ b/replit.md @@ -330,7 +330,9 @@ Preferred communication style: Simple, everyday language. - ✅ **Graceful Degradation**: Application starts even if migrations fail - ✅ **Auto-Creation**: Database tables created automatically on first connection - ✅ **SSL Configuration**: Fixed PostgreSQL SSL errors with sslmode=disable for Docker -- ✅ **Backup Import Fix**: Corrected timestamp conversion in backup import functionality +- ✅ **Backup Import Fix**: Corrected timestamp conversion in backup import functionality +- ✅ **Admin Permissions Fix**: Corrected user role 'admin' to 'administrator' for production consistency +- ✅ **Role Middleware Fix**: Updated all admin routes to use 'administrator' role instead of 'admin' - ✅ **Production Guide**: Created comprehensive DEPLOYMENT_GUIDE.md with troubleshooting - ✅ **Environment Templates**: Updated .env.production.example with security defaults - ✅ **Health Diagnostics**: Added production-ready health checks and monitoring diff --git a/server/routes.ts b/server/routes.ts index bdfc531..e5e3501 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -341,7 +341,7 @@ export async function registerRoutes(app: Express): Promise { }); // Admin routes - Users - app.get('/api/admin/users', requireRole(['admin']), async (req, res) => { + app.get('/api/admin/users', requireRole(['administrator']), async (req, res) => { try { const users = await storage.getAllUsers(); const safeUsers = users.map(user => ({ ...user, password: undefined })); @@ -352,7 +352,7 @@ export async function registerRoutes(app: Express): Promise { } }); - app.post('/api/admin/users', requireRole(['admin']), async (req, res) => { + app.post('/api/admin/users', requireRole(['administrator']), async (req, res) => { try { const userData = insertUserSchema.parse(req.body); const user = await storage.createUser(userData); @@ -366,7 +366,7 @@ export async function registerRoutes(app: Express): Promise { } }); - app.put('/api/admin/users/:id', requireRole(['admin']), async (req, res) => { + app.put('/api/admin/users/:id', requireRole(['administrator']), async (req, res) => { try { const userId = parseInt(req.params.id); const currentUser = await storage.getUser(req.session.userId!); @@ -409,7 +409,7 @@ export async function registerRoutes(app: Express): Promise { } }); - app.delete('/api/admin/users/:id', requireRole(['admin']), async (req, res) => { + app.delete('/api/admin/users/:id', requireRole(['administrator']), async (req, res) => { try { const userId = parseInt(req.params.id); @@ -431,7 +431,7 @@ export async function registerRoutes(app: Express): Promise { }); // Admin routes - Stores - app.get('/api/admin/stores', requireRole(['admin']), async (req, res) => { + app.get('/api/admin/stores', requireRole(['administrator']), async (req, res) => { try { const stores = await storage.getAllStores(); res.json(stores); @@ -441,7 +441,7 @@ export async function registerRoutes(app: Express): Promise { } }); - app.post('/api/admin/stores', requireRole(['admin']), async (req, res) => { + app.post('/api/admin/stores', requireRole(['administrator']), async (req, res) => { try { const storeData = insertStoreSchema.parse(req.body); const store = await storage.createStore(storeData); @@ -455,7 +455,7 @@ export async function registerRoutes(app: Express): Promise { } }); - app.put('/api/admin/stores/:id', requireRole(['admin']), async (req, res) => { + app.put('/api/admin/stores/:id', requireRole(['administrator']), async (req, res) => { try { const storeId = parseInt(req.params.id); const storeData = insertStoreSchema.partial().parse(req.body); @@ -473,7 +473,7 @@ export async function registerRoutes(app: Express): Promise { } }); - app.delete('/api/admin/stores/:id', requireRole(['admin']), async (req, res) => { + app.delete('/api/admin/stores/:id', requireRole(['administrator']), async (req, res) => { try { const storeId = parseInt(req.params.id); @@ -497,7 +497,7 @@ export async function registerRoutes(app: Express): Promise { }); // Backup routes - app.get('/api/admin/backup/export', requireRole(['admin']), async (req, res) => { + app.get('/api/admin/backup/export', requireRole(['administrator']), async (req, res) => { try { // Get all data from the database const users = await storage.getAllUsers(); @@ -537,7 +537,7 @@ export async function registerRoutes(app: Express): Promise { } }); - app.post('/api/admin/backup/import', requireRole(['admin']), async (req, res) => { + app.post('/api/admin/backup/import', requireRole(['administrator']), async (req, res) => { try { const backupData = req.body; @@ -648,7 +648,7 @@ export async function registerRoutes(app: Express): Promise { }); // Manual backup trigger route - app.post('/api/admin/backup/create', requireRole(['admin']), async (req, res) => { + app.post('/api/admin/backup/create', requireRole(['administrator']), async (req, res) => { try { const result = await createAutomaticBackup(); if (result.success) { @@ -667,7 +667,7 @@ export async function registerRoutes(app: Express): Promise { }); // Backup statistics route - app.get('/api/admin/backup/stats', requireRole(['admin']), async (req, res) => { + app.get('/api/admin/backup/stats', requireRole(['administrator']), async (req, res) => { try { const stats = getBackupStats(); res.json(stats); @@ -678,7 +678,7 @@ export async function registerRoutes(app: Express): Promise { }); // Admin routes - Data Purge - app.get('/api/admin/purge/stats', requireRole(['admin']), async (req, res) => { + app.get('/api/admin/purge/stats', requireRole(['administrator']), async (req, res) => { try { const stats = await getPurgeStats(); res.json(stats); @@ -688,7 +688,7 @@ export async function registerRoutes(app: Express): Promise { } }); - app.post('/api/admin/purge/execute', requireRole(['admin']), async (req, res) => { + app.post('/api/admin/purge/execute', requireRole(['administrator']), async (req, res) => { try { const result = await executePurgeManually(); res.json(result);