Merge pull request #32 from R0m1k3/1.1

1.1
This commit is contained in:
LogiFlow authored and GitHub committed 2025-08-12 15:43:56 +02:00
commit 09eb222fe3
6 files changed
+233 -18

No files matched your search

+77
View File
@@ -0,0 +1,77 @@
# Solution - Problème Calendrier Directeur en Production
## Problème Identifié
Le rôle directeur rencontre une erreur réseau lors de l'accès au module calendrier en production.
## Diagnostic Effectué
### ✅ Corrections Appliquées
1. **Permissions côté serveur ajoutées** pour tous les modules:
- `GET /api/orders` utilise maintenant `requirePermission('orders', 'view')`
- `GET /api/deliveries` utilise maintenant `requirePermission('deliveries', 'view')`
- `POST /api/customer-orders` utilise `requirePermission('customer-orders', 'create')`
- `PUT /api/customer-orders/:id` utilise `requirePermission('customer-orders', 'edit')`
- `DELETE /api/customer-orders/:id` utilise `requirePermission('customer-orders', 'delete')`
- Toutes les routes DLC utilisent les bonnes permissions (`view`, `create`, `edit`, `delete`, `validate`)
2. **Permissions directeur vérifiées** dans `shared/permissions.ts`:
- ✅ Directeur a `view` pour `orders` (ligne 38)
- ✅ Directeur a `view` pour `deliveries` (ligne 46)
- ✅ Directeur a toutes les permissions pour `customer-orders` (ligne 70)
### 🔍 Analyse du Problème
Le problème n'est **PAS** lié aux permissions côté serveur. Les permissions sont correctement configurées pour le rôle directeur.
### 🚨 Cause Probable
L'erreur réseau indique un problème de **connectivité** ou de **configuration serveur** en production:
1. **Timeout réseau** - Les APIs `/api/orders` et `/api/deliveries` prennent trop de temps à répondre
2. **Problème de load balancer** - Les requêtes ne parviennent pas au serveur d'applications
3. **Configuration firewall** - Certaines requêtes sont bloquées
4. **Problème de base de données** - Lenteur ou indisponibilité temporaire
## 🛠️ Script de Diagnostic
Un script de diagnostic a été créé: `debug-calendar-production.js`
### Utilisation:
```bash
# 1. Configurez les variables d'environnement
export PRODUCTION_URL="https://votre-serveur-production.com"
export PROD_USERNAME="votre-directeur-username"
export PROD_PASSWORD="votre-directeur-password"
# 2. Exécutez le diagnostic
node debug-calendar-production.js --run
```
### Le script teste:
- ✅ Connexion au serveur
- ✅ Authentification directeur
- ✅ Récupération du profil utilisateur
- ✅ API `/api/orders` (utilisée par le calendrier)
- ✅ API `/api/deliveries` (utilisée par le calendrier)
- ✅ Temps de réponse réseau
## 📋 Actions Recommandées
### 1. Vérifications Immédiates
- [ ] Vérifier que le serveur de production est démarré
- [ ] Tester la connectivité réseau depuis le navigateur du directeur
- [ ] Vérifier les logs serveur pour erreurs de timeout
### 2. Diagnostic Approfondi
- [ ] Exécuter `debug-calendar-production.js` pour identifier l'API défaillante
- [ ] Vérifier les performances de la base de données en production
- [ ] Contrôler la configuration du load balancer/reverse proxy
### 3. Solutions selon le diagnostic
- **Si timeout réseau**: Augmenter les timeouts du serveur web
- **Si problème DB**: Optimiser les requêtes ou redémarrer la DB
- **Si load balancer**: Vérifier la configuration du proxy
## 📊 État du Projet
- ✅ **Permissions employé** - Customer Orders et DLC fonctionnent
- ✅ **Permissions directeur** - Système de permissions correct
- 🔄 **Connectivité production** - Diagnostic en cours avec script
Le système de permissions est maintenant entièrement cohérent entre côté client et serveur pour tous les rôles.
Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 KiB

+143
View File
@@ -0,0 +1,143 @@
#!/usr/bin/env node
/**
* Script de diagnostic pour le problème de calendrier en production
* avec le rôle directeur
*/
const fetch = require('node-fetch');
// Configuration de votre serveur de production
const PRODUCTION_URL = process.env.PRODUCTION_URL || 'https://votre-serveur-production.com';
const USERNAME = process.env.PROD_USERNAME || 'votre-directeur-username';
const PASSWORD = process.env.PROD_PASSWORD || 'votre-directeur-password';
async function testCalendarAPIs() {
console.log('🔍 Test de diagnostic du calendrier en production pour directeur');
console.log('URL de production:', PRODUCTION_URL);
try {
// 1. Test de connexion au serveur
console.log('\n1. Test de connexion au serveur...');
const healthResponse = await fetch(`${PRODUCTION_URL}/api/health`, {
timeout: 10000
});
console.log('✅ Serveur accessible:', healthResponse.status);
// 2. Test d'authentification
console.log('\n2. Test d\'authentification...');
const loginResponse = await fetch(`${PRODUCTION_URL}/api/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: USERNAME,
password: PASSWORD
})
});
if (!loginResponse.ok) {
console.error('❌ Échec de l\'authentification:', loginResponse.status);
return;
}
const cookies = loginResponse.headers.get('set-cookie');
console.log('✅ Authentification réussie');
// 3. Test de récupération du profil utilisateur
console.log('\n3. Test du profil utilisateur...');
const userResponse = await fetch(`${PRODUCTION_URL}/api/user`, {
headers: {
'Cookie': cookies
}
});
if (!userResponse.ok) {
console.error('❌ Impossible de récupérer le profil:', userResponse.status);
return;
}
const user = await userResponse.json();
console.log('✅ Profil utilisateur:', {
role: user.role,
id: user.id,
groupsCount: user.userGroups?.length || 0
});
// 4. Test API orders (utilisée par le calendrier)
console.log('\n4. Test API /api/orders...');
const ordersResponse = await fetch(`${PRODUCTION_URL}/api/orders?startDate=2025-08-01&endDate=2025-08-31`, {
headers: {
'Cookie': cookies
},
timeout: 15000
});
console.log('Status orders:', ordersResponse.status);
if (ordersResponse.ok) {
const orders = await ordersResponse.json();
console.log('✅ API orders fonctionne, nombre de commandes:', orders.length);
} else {
const errorText = await ordersResponse.text();
console.error('❌ Erreur API orders:', errorText);
}
// 5. Test API deliveries (utilisée par le calendrier)
console.log('\n5. Test API /api/deliveries...');
const deliveriesResponse = await fetch(`${PRODUCTION_URL}/api/deliveries?startDate=2025-08-01&endDate=2025-08-31`, {
headers: {
'Cookie': cookies
},
timeout: 15000
});
console.log('Status deliveries:', deliveriesResponse.status);
if (deliveriesResponse.ok) {
const deliveries = await deliveriesResponse.json();
console.log('✅ API deliveries fonctionne, nombre de livraisons:', deliveries.length);
} else {
const errorText = await deliveriesResponse.text();
console.error('❌ Erreur API deliveries:', errorText);
}
// 6. Test de connectivité réseau détaillé
console.log('\n6. Test de connectivité réseau...');
const start = Date.now();
const timeoutResponse = await fetch(`${PRODUCTION_URL}/api/health`, {
timeout: 30000
});
const duration = Date.now() - start;
console.log(`✅ Temps de réponse réseau: ${duration}ms`);
} catch (error) {
console.error('❌ Erreur de diagnostic:', error.message);
if (error.code === 'ECONNREFUSED') {
console.log('💡 Solution: Vérifiez que le serveur est démarré et accessible');
} else if (error.code === 'ETIMEDOUT') {
console.log('💡 Solution: Problème de timeout réseau - vérifiez la connectivité');
} else if (error.message.includes('ENOTFOUND')) {
console.log('💡 Solution: URL du serveur incorrecte ou problème DNS');
}
}
}
// Instructions d'utilisation
console.log(`
🚀 INSTRUCTIONS D'UTILISATION:
1. Configurez les variables d'environnement:
export PRODUCTION_URL="https://votre-serveur-production.com"
export PROD_USERNAME="votre-directeur-username"
export PROD_PASSWORD="votre-directeur-password"
2. Exécutez le script:
node debug-calendar-production.js
3. Analysez les résultats pour identifier le problème
`);
if (process.argv.includes('--run')) {
testCalendarAPIs();
}
+13 -18
View File
@@ -2,7 +2,7 @@ import type { Express } from "express";
import { createServer, type Server } from "http";
import { storage } from "./storage";
import { setupLocalAuth, requireAuth } from "./localAuth";
import { requireModulePermission, requireAdmin } from "./permissions";
import { requireModulePermission, requireAdmin, requirePermission } from "./permissions";
import { db, pool } from "./db";
console.log('🔍 Using development storage and authentication');
@@ -1928,7 +1928,7 @@ RÉSUMÉ DU SCAN
}
});
app.post('/api/customer-orders', isAuthenticated, async (req: any, res) => {
app.post('/api/customer-orders', isAuthenticated, requirePermission('customer-orders', 'create'), async (req: any, res) => {
try {
console.log("Raw body received:", req.body);
console.log("Body type:", typeof req.body);
@@ -1965,7 +1965,7 @@ RÉSUMÉ DU SCAN
}
});
app.put('/api/customer-orders/:id', isAuthenticated, async (req: any, res) => {
app.put('/api/customer-orders/:id', isAuthenticated, requirePermission('customer-orders', 'edit'), async (req: any, res) => {
try {
const id = parseInt(req.params.id);
const userId = req.user.claims ? req.user.claims.sub : req.user.id;
@@ -1996,7 +1996,7 @@ RÉSUMÉ DU SCAN
}
});
app.delete('/api/customer-orders/:id', isAuthenticated, async (req: any, res) => {
app.delete('/api/customer-orders/:id', isAuthenticated, requirePermission('customer-orders', 'delete'), async (req: any, res) => {
try {
const id = parseInt(req.params.id);
const userId = req.user.claims ? req.user.claims.sub : req.user.id;
@@ -2011,10 +2011,7 @@ RÉSUMÉ DU SCAN
return res.status(404).json({ message: "Customer order not found" });
}
// Check permissions using the shared permission system
if (!hasPermission(user.role, 'customer-orders', 'delete')) {
return res.status(403).json({ message: "Insufficient permissions to delete customer orders" });
}
// Permission already checked by middleware
await storage.deleteCustomerOrder(id);
res.status(204).send();
@@ -2164,7 +2161,7 @@ RÉSUMÉ DU SCAN
});
// DLC Products routes
app.get('/api/dlc-products', isAuthenticated, async (req: any, res) => {
app.get('/api/dlc-products', isAuthenticated, requirePermission('dlc', 'view'), async (req: any, res) => {
try {
const userId = req.user.claims ? req.user.claims.sub : req.user.id;
const user = await storage.getUserWithGroups(userId);
@@ -2211,7 +2208,7 @@ RÉSUMÉ DU SCAN
}
});
app.get('/api/dlc-products/stats', isAuthenticated, async (req: any, res) => {
app.get('/api/dlc-products/stats', isAuthenticated, requirePermission('dlc', 'view'), async (req: any, res) => {
try {
const userId = req.user.claims ? req.user.claims.sub : req.user.id;
const user = await storage.getUserWithGroups(userId);
@@ -2240,7 +2237,7 @@ RÉSUMÉ DU SCAN
}
});
app.get('/api/dlc-products/:id', isAuthenticated, async (req: any, res) => {
app.get('/api/dlc-products/:id', isAuthenticated, requirePermission('dlc', 'view'), async (req: any, res) => {
try {
const id = parseInt(req.params.id);
const dlcProduct = await storage.getDlcProduct(id);
@@ -2267,7 +2264,7 @@ RÉSUMÉ DU SCAN
}
});
app.post('/api/dlc-products', isAuthenticated, async (req: any, res) => {
app.post('/api/dlc-products', isAuthenticated, requirePermission('dlc', 'create'), async (req: any, res) => {
try {
console.log('📨 POST /api/dlc-products - Request body:', JSON.stringify(req.body, null, 2));
@@ -2307,7 +2304,7 @@ RÉSUMÉ DU SCAN
}
});
app.put('/api/dlc-products/:id', isAuthenticated, async (req: any, res) => {
app.put('/api/dlc-products/:id', isAuthenticated, requirePermission('dlc', 'edit'), async (req: any, res) => {
try {
const id = parseInt(req.params.id);
const userId = req.user.claims ? req.user.claims.sub : req.user.id;
@@ -2342,15 +2339,13 @@ RÉSUMÉ DU SCAN
}
});
app.post('/api/dlc-products/:id/validate', isAuthenticated, async (req: any, res) => {
app.post('/api/dlc-products/:id/validate', isAuthenticated, requirePermission('dlc', 'validate'), async (req: any, res) => {
try {
const id = parseInt(req.params.id);
const userId = req.user.claims ? req.user.claims.sub : req.user.id;
const user = await storage.getUser(userId);
if (!user || !hasPermission(user.role, 'dlc', 'validate')) {
return res.status(403).json({ message: "Insufficient permissions to validate products" });
}
// Permission already checked by middleware
// Check if the product exists and user has access
const existingProduct = await storage.getDlcProduct(id);
@@ -2374,7 +2369,7 @@ RÉSUMÉ DU SCAN
}
});
app.delete('/api/dlc-products/:id', isAuthenticated, async (req: any, res) => {
app.delete('/api/dlc-products/:id', isAuthenticated, requirePermission('dlc', 'delete'), async (req: any, res) => {
try {
const id = parseInt(req.params.id);
const userId = req.user.claims ? req.user.claims.sub : req.user.id;