From bf09dcb56bbd2b4897de1db1403ce50e93a5fbb0 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Sat, 19 Jul 2025 14:44:26 +0000 Subject: [PATCH] Fix administrator access and improve production deployment reliability Corrects admin role inconsistencies and updates routes to use 'administrator' role. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 4b008663-bd72-492b-b0b6-fa252367e730 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0715008c-7244-40f4-befc-26c014852236/4b008663-bd72-492b-b0b6-fa252367e730/9GNa2aH --- PRODUCTION_UPDATE_2025.md | 5 +++++ attached_assets/image_1752936125571.png | Bin 0 -> 51033 bytes replit.md | 4 +++- server/routes.ts | 28 ++++++++++++------------ 4 files changed, 22 insertions(+), 15 deletions(-) create mode 100644 attached_assets/image_1752936125571.png 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 0000000000000000000000000000000000000000..f5963ccb5b1df6372f4867ee73e18d357192891b GIT binary patch literal 51033 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 { }); // 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);