mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
Grant employees access to system features and tasks
Adjust permissions for employee role to access tasks and supplier data, and allow directors to validate DLC products. Replit-Commit-Author: Agent Replit-Commit-Session-Id: b163d4c0-de5e-4f4e-a9c0-aed4c7049718 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/b163d4c0-de5e-4f4e-a9c0-aed4c7049718/69xEJ3P
This commit is contained in:
1 parent
5ea3481dc0
commit
072ad60ec1
6 files changed
+310
-158
No files matched your search
@@ -0,0 +1,102 @@
|
||||
# Résolution des Erreurs 403 pour les Employés - Résumé des Corrections
|
||||
|
||||
## Problème Identifié
|
||||
Les employés rencontraient des erreurs 403 (Forbidden) lors de l'accès aux modules de gestion des tâches et autres fonctionnalités, empêchant leur utilisation normale du système.
|
||||
|
||||
## Corrections Apportées
|
||||
|
||||
### 1. Permissions des Tâches pour Employés
|
||||
**Fichier**: `shared/permissions.ts`
|
||||
**Modification**:
|
||||
```typescript
|
||||
// AVANT
|
||||
tasks: {
|
||||
employee: ['view']
|
||||
}
|
||||
|
||||
// APRÈS
|
||||
tasks: {
|
||||
employee: ['view', 'create']
|
||||
}
|
||||
```
|
||||
**Impact**: Les employés peuvent maintenant créer des tâches dans leurs magasins assignés.
|
||||
|
||||
### 2. Accès aux Fournisseurs pour Employés
|
||||
**Fichier**: `server/routes.ts`
|
||||
**Route**: `GET /api/suppliers`
|
||||
**Modification**:
|
||||
```typescript
|
||||
// AVANT
|
||||
if (!user || (user.role !== 'admin' && user.role !== 'manager')) {
|
||||
|
||||
// APRÈS
|
||||
if (!user || (user.role !== 'admin' && user.role !== 'manager' && user.role !== 'directeur' && user.role !== 'employee')) {
|
||||
```
|
||||
**Impact**: Les employés peuvent accéder aux listes de fournisseurs pour les modules Commandes Client et DLC.
|
||||
|
||||
### 3. Validation DLC pour Directeurs
|
||||
**Fichier**: `server/routes.ts`
|
||||
**Route**: `POST /api/dlc-products/:id/validate`
|
||||
**Modification**:
|
||||
```typescript
|
||||
// AVANT
|
||||
if (!user || !['admin', 'manager'].includes(user.role)) {
|
||||
|
||||
// APRÈS
|
||||
if (!user || !['admin', 'manager', 'directeur'].includes(user.role)) {
|
||||
```
|
||||
**Impact**: Les directeurs peuvent maintenant valider les produits DLC.
|
||||
|
||||
### 4. Permissions Complètes pour Fournisseurs
|
||||
**Fichiers**: `server/routes.ts`
|
||||
**Routes modifiées**:
|
||||
- `POST /api/suppliers`: Ajout du rôle directeur
|
||||
- `PUT /api/suppliers/:id`: Ajout du rôle directeur
|
||||
- `DELETE /api/suppliers/:id`: Restriction admin/directeur uniquement
|
||||
|
||||
**Matrice des permissions finales**:
|
||||
- **GET**: admin, directeur, manager, employee (tous)
|
||||
- **POST**: admin, directeur, manager
|
||||
- **PUT**: admin, directeur, manager
|
||||
- **DELETE**: admin, directeur uniquement
|
||||
|
||||
## Scripts de Débogage Créés
|
||||
|
||||
### 1. `test-employee-supplier-access.js`
|
||||
Script pour tester l'accès des employés aux fournisseurs en production.
|
||||
|
||||
### 2. `debug-employee-403-production.js`
|
||||
Script complet de débogage pour identifier toutes les sources potentielles d'erreurs 403 pour les employés.
|
||||
|
||||
## Routes Potentiellement Problématiques (Documentation)
|
||||
|
||||
Les routes suivantes peuvent encore générer des erreurs 403 selon le rôle et l'assignation aux groupes:
|
||||
|
||||
### Restrictions par Rôle (Volontaires)
|
||||
- **Groupes** (POST/PUT/DELETE): Admin/Manager uniquement
|
||||
- **Livraisons** (DELETE/VALIDATE): Admin/Manager uniquement
|
||||
- **Commandes** (CREATE/EDIT/DELETE): Restrictions selon les permissions définies
|
||||
|
||||
### Restrictions par Groupe/Magasin (Fonctionnelles)
|
||||
- **Tâches**: Accès limité aux magasins assignés à l'utilisateur
|
||||
- **Commandes/Livraisons**: Accès limité aux magasins assignés
|
||||
- **Produits DLC**: Accès limité aux magasins assignés
|
||||
|
||||
## Vérification du Fonctionnement
|
||||
|
||||
Pour vérifier que les corrections fonctionnent:
|
||||
|
||||
1. **Connexion Employé**: Doit pouvoir se connecter sans erreur
|
||||
2. **Accès Fournisseurs**: Doit voir les listes de fournisseurs dans Commandes Client et DLC
|
||||
3. **Création Tâches**: Doit pouvoir créer des tâches dans ses magasins assignés
|
||||
4. **Navigation**: Ne doit plus voir d'erreurs 403 sur les modules autorisés
|
||||
|
||||
## Actions de Suivi Recommandées
|
||||
|
||||
1. **Test en Production**: Utiliser les scripts de test fournis
|
||||
2. **Monitoring**: Surveiller les logs pour d'autres erreurs 403 potentielles
|
||||
3. **Formation**: Informer les employés des nouvelles fonctionnalités disponibles
|
||||
4. **Documentation**: Mettre à jour la documentation utilisateur si nécessaire
|
||||
|
||||
## Status
|
||||
✅ **RÉSOLU** - Les erreurs 403 pour les employés ont été corrigées et les permissions sont maintenant cohérentes avec les besoins métier.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 252 KiB |
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script de débogage pour identifier les erreurs 403 des employés en production
|
||||
* Analyse les routes et permissions pour diagnostiquer les problèmes d'accès
|
||||
*/
|
||||
|
||||
const https = require('https');
|
||||
|
||||
// Configuration pour le serveur de production
|
||||
const PRODUCTION_URL = process.env.PRODUCTION_URL || 'https://votre-serveur-production.com';
|
||||
const TEST_EMPLOYEE_CREDENTIALS = {
|
||||
username: process.env.TEST_EMPLOYEE_USERNAME || 'test_employee',
|
||||
password: process.env.TEST_EMPLOYEE_PASSWORD || 'password123'
|
||||
};
|
||||
|
||||
console.log('🐛 === DÉBOGAGE ERREURS 403 EMPLOYÉS EN PRODUCTION ===\n');
|
||||
|
||||
// Routes susceptibles de poser problème pour les employés
|
||||
const ROUTES_TO_TEST = [
|
||||
{ path: '/api/tasks', method: 'GET', description: 'Liste des tâches' },
|
||||
{ path: '/api/tasks', method: 'POST', description: 'Création de tâche', data: { title: 'Test', description: 'Test', priority: 'medium', status: 'pending', groupId: 1 } },
|
||||
{ path: '/api/suppliers', method: 'GET', description: 'Liste des fournisseurs' },
|
||||
{ path: '/api/suppliers?dlc=true', method: 'GET', description: 'Fournisseurs DLC' },
|
||||
{ path: '/api/groups', method: 'GET', description: 'Liste des groupes/magasins' },
|
||||
{ path: '/api/customer-orders', method: 'GET', description: 'Commandes client' },
|
||||
{ path: '/api/dlc-products', method: 'GET', description: 'Produits DLC' },
|
||||
{ path: '/api/user', method: 'GET', description: 'Profil utilisateur' }
|
||||
];
|
||||
|
||||
async function makeRequest(path, method = 'GET', data = null, cookies = '') {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = new URL(path, PRODUCTION_URL);
|
||||
const options = {
|
||||
hostname: url.hostname,
|
||||
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
||||
path: url.pathname + url.search,
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'LogiFlow-Debug-Script/1.0',
|
||||
...(cookies ? { 'Cookie': cookies } : {}),
|
||||
...(data ? { 'Content-Length': Buffer.byteLength(JSON.stringify(data)) } : {})
|
||||
}
|
||||
};
|
||||
|
||||
const req = https.request(options, (res) => {
|
||||
let body = '';
|
||||
res.on('data', (chunk) => body += chunk);
|
||||
res.on('end', () => {
|
||||
try {
|
||||
const parsed = JSON.parse(body);
|
||||
resolve({
|
||||
status: res.statusCode,
|
||||
headers: res.headers,
|
||||
data: parsed
|
||||
});
|
||||
} catch (e) {
|
||||
resolve({
|
||||
status: res.statusCode,
|
||||
headers: res.headers,
|
||||
data: body
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
|
||||
if (data) {
|
||||
req.write(JSON.stringify(data));
|
||||
}
|
||||
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
async function debugEmployee403Errors() {
|
||||
try {
|
||||
console.log('1️⃣ Connexion avec compte employé...');
|
||||
|
||||
// Connexion employé
|
||||
const loginResponse = await makeRequest('/api/login', 'POST', TEST_EMPLOYEE_CREDENTIALS);
|
||||
|
||||
if (loginResponse.status !== 200) {
|
||||
console.error('❌ Échec de connexion employé');
|
||||
console.error(` Status: ${loginResponse.status}`);
|
||||
console.error(` Response: ${JSON.stringify(loginResponse.data, null, 2)}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ Connexion employé réussie\n');
|
||||
|
||||
// Extraire les cookies de session
|
||||
const setCookieHeaders = loginResponse.headers['set-cookie'] || [];
|
||||
const cookies = setCookieHeaders.join('; ');
|
||||
|
||||
console.log('2️⃣ Test des routes susceptibles de générer des erreurs 403...\n');
|
||||
|
||||
const results = [];
|
||||
|
||||
// Tester chaque route
|
||||
for (const route of ROUTES_TO_TEST) {
|
||||
console.log(`🔍 Test: ${route.method} ${route.path} - ${route.description}`);
|
||||
|
||||
try {
|
||||
const response = await makeRequest(route.path, route.method, route.data, cookies);
|
||||
|
||||
const status = response.status;
|
||||
const statusIcon = status === 200 ? '✅' : status === 403 ? '❌' : '⚠️';
|
||||
|
||||
console.log(` ${statusIcon} Status: ${status}`);
|
||||
|
||||
if (status === 403) {
|
||||
console.log(` 🚫 ERREUR 403: ${JSON.stringify(response.data, null, 2)}`);
|
||||
results.push({ route, status, error: response.data, success: false });
|
||||
} else if (status === 200) {
|
||||
const dataSize = Array.isArray(response.data) ? response.data.length : 'N/A';
|
||||
console.log(` 📊 Données retournées: ${dataSize} éléments`);
|
||||
results.push({ route, status, success: true });
|
||||
} else {
|
||||
console.log(` ⚠️ Status inattendu: ${JSON.stringify(response.data, null, 2)}`);
|
||||
results.push({ route, status, error: response.data, success: false });
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(` 💥 Erreur réseau: ${error.message}`);
|
||||
results.push({ route, status: 'ERROR', error: error.message, success: false });
|
||||
}
|
||||
|
||||
console.log(''); // Ligne vide entre les tests
|
||||
}
|
||||
|
||||
// Résumé des résultats
|
||||
console.log('📊 === RÉSUMÉ DES TESTS ===');
|
||||
console.log('==========================\n');
|
||||
|
||||
const successfulRoutes = results.filter(r => r.success);
|
||||
const forbiddenRoutes = results.filter(r => r.status === 403);
|
||||
const errorRoutes = results.filter(r => !r.success && r.status !== 403);
|
||||
|
||||
console.log(`✅ Routes accessibles: ${successfulRoutes.length}/${results.length}`);
|
||||
console.log(`❌ Erreurs 403: ${forbiddenRoutes.length}/${results.length}`);
|
||||
console.log(`⚠️ Autres erreurs: ${errorRoutes.length}/${results.length}\n`);
|
||||
|
||||
if (forbiddenRoutes.length > 0) {
|
||||
console.log('🚫 ROUTES BLOQUÉES (403):');
|
||||
forbiddenRoutes.forEach(result => {
|
||||
console.log(` • ${result.route.method} ${result.route.path} - ${result.route.description}`);
|
||||
console.log(` Erreur: ${result.error?.message || 'Permission refusée'}`);
|
||||
});
|
||||
console.log('');
|
||||
}
|
||||
|
||||
if (errorRoutes.length > 0) {
|
||||
console.log('⚠️ AUTRES ERREURS:');
|
||||
errorRoutes.forEach(result => {
|
||||
console.log(` • ${result.route.method} ${result.route.path} - Status: ${result.status}`);
|
||||
console.log(` Erreur: ${result.error?.message || result.error}`);
|
||||
});
|
||||
console.log('');
|
||||
}
|
||||
|
||||
console.log('💡 RECOMMANDATIONS:');
|
||||
if (forbiddenRoutes.length === 0) {
|
||||
console.log(' 🎉 Aucune erreur 403 détectée - les permissions semblent correctes !');
|
||||
} else {
|
||||
console.log(' 1. Vérifiez les permissions dans shared/permissions.ts');
|
||||
console.log(' 2. Vérifiez les middlewares de permission dans server/permissions.ts');
|
||||
console.log(' 3. Vérifiez l\'assignation de groupes/magasins à l\'employé');
|
||||
console.log(' 4. Examinez les logs serveur pendant l\'exécution des requêtes');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('💥 Erreur lors du débogage:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Instructions d'utilisation
|
||||
console.log('📋 Instructions:');
|
||||
console.log('1. Configurez les variables d\'environnement:');
|
||||
console.log(' - PRODUCTION_URL=https://votre-serveur.com');
|
||||
console.log(' - TEST_EMPLOYEE_USERNAME=nom_utilisateur_employe');
|
||||
console.log(' - TEST_EMPLOYEE_PASSWORD=mot_de_passe');
|
||||
console.log('2. Exécutez: node debug-employee-403-production.js\n');
|
||||
|
||||
// Exécuter le debug si le script est appelé directement
|
||||
if (require.main === module) {
|
||||
debugEmployee403Errors().catch(console.error);
|
||||
}
|
||||
|
||||
module.exports = { debugEmployee403Errors };
|
||||
@@ -9,38 +9,27 @@ Preferred communication style: Simple, everyday language.
|
||||
## System Architecture
|
||||
|
||||
### Frontend
|
||||
- **Framework**: React 18 with TypeScript
|
||||
- **Build Tool**: Vite
|
||||
- **UI Framework**: Shadcn/ui (built on Radix UI)
|
||||
- **Styling**: Tailwind CSS with custom CSS variables
|
||||
- **Framework**: React 18 with TypeScript, Vite
|
||||
- **UI Framework**: Shadcn/ui (built on Radix UI), Tailwind CSS
|
||||
- **State Management**: TanStack Query (React Query)
|
||||
- **Routing**: Wouter
|
||||
- **Forms**: React Hook Form with Zod validation
|
||||
- **UI/UX Decisions**: Focus on a clean, intuitive interface using Shadcn/ui components for consistency and accessibility. Color schemes are managed via Tailwind CSS custom variables for easy theming.
|
||||
- **UI/UX Decisions**: Clean, intuitive interface using Shadcn/ui components for consistency and accessibility. Color schemes managed via Tailwind CSS custom variables for easy theming.
|
||||
|
||||
### Backend
|
||||
- **Framework**: Express.js with TypeScript
|
||||
- **Runtime**: Node.js with ES modules
|
||||
- **Framework**: Express.js with TypeScript, Node.js (ES modules)
|
||||
- **Database ORM**: Drizzle ORM
|
||||
- **Authentication**: Dual system (local for production, Replit Auth for development)
|
||||
- **Session Management**: Express sessions with PostgreSQL storage
|
||||
- **Security**: Comprehensive middleware (rate limiting, input sanitization, security headers)
|
||||
|
||||
### Database
|
||||
- **Primary Database**: PostgreSQL with Drizzle ORM
|
||||
- **Development**: Neon serverless PostgreSQL
|
||||
- **Production**: Standard PostgreSQL in Docker containers
|
||||
- **Primary Database**: PostgreSQL with Drizzle ORM (Neon serverless for development, Docker for production)
|
||||
- **Schema**: Centralized definition in `shared/schema.ts`
|
||||
- **Migrations**: Drizzle Kit
|
||||
|
||||
### Core Business Entities
|
||||
- **Orders**: Purchase orders, supplier relationships, delivery tracking.
|
||||
- **Deliveries**: Delivery tracking and status.
|
||||
- **Customer Orders**: Point-of-sale management with barcode generation.
|
||||
- **Suppliers**: Vendor management and order history.
|
||||
- **Publicities**: Marketing campaign management and store participation.
|
||||
- **DLC Products**: Management of products with limited shelf life, including status tracking and alerts.
|
||||
- **Tasks**: Streamlined task management with simplified assignment and completion tracking.
|
||||
- **Management**: Orders, Deliveries, Customer Orders, Suppliers, Publicities, DLC Products (limited shelf life), Tasks.
|
||||
|
||||
### Data Flow
|
||||
- **Request Flow**: Client requests via React Query, processed by Express middleware for authentication/security, then by route handlers using Drizzle ORM for database operations.
|
||||
@@ -48,11 +37,14 @@ Preferred communication style: Simple, everyday language.
|
||||
- **Data Synchronization**: Real-time updates via React Query with optimistic updates and intelligent cache invalidation. Global store context filters data.
|
||||
|
||||
### Key Features
|
||||
- **Authentication System**: Secure dual authentication system with robust password hashing and session management.
|
||||
- **Authentication System**: Secure dual authentication with password hashing and session management.
|
||||
- **Multi-Store Management**: Global store context, role-based access control (admin, manager, employee, directeur), and data isolation.
|
||||
- **Universal Pagination**: Reusable client-side pagination component applied across all main tabular data pages (Orders, Deliveries, Customer Orders, DlcPage, BLReconciliation, Tasks) with configurable limits per module.
|
||||
- **Universal Pagination**: Reusable client-side pagination component across all main tabular data pages.
|
||||
- **Reconciliation Module**: For balancing and tracking financial discrepancies.
|
||||
- **Permission System**: Granular permission management with 54 permissions across 12 categories, assigned to 4 roles.
|
||||
- **Permission System**: Granular, hardcoded permissions (54 permissions across 12 categories, assigned to 4 roles) for improved performance and maintenance.
|
||||
- **User Management**: Comprehensive features including user deletion with ownership transfer, consistent name and email field handling, and robust password hashing.
|
||||
- **Calendar Synchronization**: Proper display of delivery dates and automatic synchronization of order statuses.
|
||||
- **Database Schema Download**: Admin-only feature to download comprehensive database structure reports.
|
||||
|
||||
## External Dependencies
|
||||
|
||||
@@ -75,138 +67,4 @@ Preferred communication style: Simple, everyday language.
|
||||
- **Development Server**: Vite dev server
|
||||
|
||||
### Other Integrations
|
||||
- **NocoDB Integration**: Configurable for invoice verification and data synchronization.
|
||||
|
||||
## Recent Changes
|
||||
|
||||
### August 11, 2025 - Permissions System Overhaul & User Management Improvements
|
||||
|
||||
#### Hardcoded Permissions System Implementation
|
||||
- **Migration from Database to Code**: Replaced flexible database-driven permissions with hardcoded permission system for better performance and control
|
||||
- **New Architecture**:
|
||||
- Created `client/src/lib/permissions.ts` and `shared/permissions.ts` with role-based module permissions
|
||||
- Implemented server-side middleware `server/permissions.ts` for route protection
|
||||
- Removed database tables: `roles`, `permissions`, `rolePermissions`, `userRoles`
|
||||
- Cleaned up storage interface and routes from old permission system
|
||||
- **Permission Matrix by Module**:
|
||||
- **Dashboard**: All roles can view
|
||||
- **Calendar/Orders/Deliveries**: Admin/Directeur full access, Manager all except delete, Employee view only
|
||||
- **Reconciliation**: Admin full access, Directeur all except delete, Manager/Employee no access
|
||||
- **Publicity**: Admin full access, others view only
|
||||
- **Customer Orders**: Admin/Directeur full access, Manager all except delete, Employee view + create
|
||||
- **DLC**: Admin/Directeur full access, Manager all except delete, Employee create + view
|
||||
- **Tasks**: Admin/Directeur full access, Manager view + validate, Employee view only
|
||||
- **Benefits**: Improved performance, simplified maintenance, no database queries for permission checks
|
||||
|
||||
### August 11, 2025 - User Management Improvements
|
||||
|
||||
#### User Deletion Fix
|
||||
- **Issue**: Foreign key constraint errors when deleting users who created customer orders or other records
|
||||
- **Root Cause**: User records were referenced by multiple tables (customer_orders, deliveries, DLC products, etc.)
|
||||
- **Solution Implemented**:
|
||||
- Enhanced deleteUser method with database transaction for atomicity
|
||||
- Prioritized lookup for `admin_local` (default admin) with fallback to any admin user
|
||||
- Ownership transfer of all user-created records to existing admin before deletion
|
||||
- Comprehensive handling of all foreign key relationships including role assignments
|
||||
- Graceful error handling when no admin user exists
|
||||
- **Tables Handled**: customer_orders, orders, deliveries, publicities, dlcProducts, tasks, nocodbConfig, userGroups, userRoles (both userId and assignedBy), database_backups
|
||||
- **Result**: Safe user deletion while preserving business data integrity
|
||||
|
||||
#### User Name Fields Optional in Production
|
||||
- **Issue**: Inconsistent validation between user creation and editing forms for name fields
|
||||
- **Root Cause**: Edit form required firstName/lastName while creation form had them as optional
|
||||
- **Solution Implemented**:
|
||||
- Removed required validation from edit form firstName/lastName fields
|
||||
- Updated placeholders to indicate "(optionnel)" for consistency
|
||||
- Maintained database schema where name fields are already optional
|
||||
- **Result**: Name fields now consistently optional across all user management interfaces
|
||||
|
||||
#### User Edit Form Initialization Fix
|
||||
- **Issue**: Prénom/nom fields in edit form were not editable because they were initialized from wrong data source
|
||||
- **Root Cause**: handleEditUser was only using the `name` field instead of `firstName`/`lastName` fields from database
|
||||
- **Solution Implemented**:
|
||||
- Modified handleEditUser to prioritize `firstName`/`lastName` fields from database
|
||||
- Added fallback to split `name` field if firstName/lastName are empty
|
||||
- Fixed edit form initialization to use actual database values
|
||||
- **Result**: Edit form now properly loads existing firstName/lastName values and allows editing
|
||||
|
||||
#### Email Field Consistency in Edit Form
|
||||
- **Issue**: Email field was marked as required in edit form but optional in create form
|
||||
- **Solution**: Removed `required` attribute and asterisk from email field in edit form
|
||||
- **Result**: Email field now consistently optional in both create and edit forms
|
||||
|
||||
#### Production Password Hashing Fix
|
||||
- **Issue**: Admin password changes failed in production with ERR_MODULE_NOT_FOUND for localAuth.production
|
||||
- **Root Cause**: Dynamic imports in production needed `.js` extension for compiled files
|
||||
- **Solution**: Updated import paths to use `./localAuth.production.js` for production environment
|
||||
- **Result**: Password hashing now works correctly in production for user updates
|
||||
|
||||
#### Email Constraint Fix for User Management
|
||||
- **Issue**: Both user creation and editing failed with "duplicate key value violates unique constraint users_email_key" error
|
||||
- **Root Cause**: PostgreSQL treats empty strings (`""`) as unique values, but multiple users with empty emails violated uniqueness constraint
|
||||
- **Solution Implemented**:
|
||||
- Updated both POST `/api/users` (creation) and PUT `/api/users/:id` (editing) routes to convert empty emails to `NULL`
|
||||
- Enhanced validation schemas to accept `null` values for email fields
|
||||
- Created `fix-duplicate-empty-email.sql` script to clean existing database records
|
||||
- Improved error handling and logging for better production debugging
|
||||
- **Result**: Users can now be created and edited with optional email fields without constraint violations
|
||||
|
||||
#### Calendar Order-Delivery Synchronization Fix
|
||||
- **Issue**: Orders linked to delivered deliveries were not showing proper status and dates in calendar view
|
||||
- **Root Cause**: Three interconnected problems:
|
||||
1. OrderDetailModal was displaying non-existent `plannedDate` instead of `scheduledDate`/`deliveredDate`
|
||||
2. Order status was not automatically updated when delivery status changed via updateDelivery method
|
||||
3. Delivered deliveries had missing `deliveredDate` field causing "Date non disponible" display
|
||||
- **Solution Implemented**:
|
||||
- Enhanced OrderDetailModal to display correct dates: `deliveredDate` for delivered items, `scheduledDate` for planned ones
|
||||
- Added automatic order status synchronization in `updateDelivery` method when delivery marked as delivered
|
||||
- Created `fix-delivery-order-sync.sql` script to correct existing production data inconsistencies
|
||||
- Improved Calendar date initialization to show current month instead of hardcoded July 2025
|
||||
- **Result**: Calendar now properly displays delivery dates and automatically synchronizes order statuses when deliveries are completed
|
||||
|
||||
### August 12, 2025 - Employee Permissions Restriction & Database Schema Download
|
||||
|
||||
#### Employee Role Permissions Update
|
||||
- **Issue**: Employee role had excessive access to orders and deliveries modules, but needed restricted calendar access
|
||||
- **Root Cause**: Permission system allowed employees full access to create orders/deliveries from calendar and sidebar navigation
|
||||
- **Solution Implemented**:
|
||||
- Updated `shared/permissions.ts`: Removed all permissions for employees on 'orders' and 'deliveries' modules
|
||||
- Modified `client/src/components/Sidebar.tsx`: Removed orders and deliveries menu items for employee role
|
||||
- Enhanced `client/src/pages/Calendar.tsx`: Added permission checks to hide "Nouveau" button for employees
|
||||
- Updated `client/src/components/modals/QuickCreateMenu.tsx`: Added role-based filtering for order/delivery creation options
|
||||
- **Employee Access Rules**:
|
||||
- **Calendar**: View-only access, cannot create orders or deliveries
|
||||
- **Sidebar**: No access to Orders and Deliveries menu items
|
||||
- **Customer Orders & DLC**: Maintains supplier list access for creating customer orders and DLC entries
|
||||
- **Result**: Employees now have appropriate restricted access while maintaining necessary supplier information for their workflows
|
||||
|
||||
#### Database Schema Download Feature
|
||||
- **Issue**: Database schema scan results were only available in server logs, needed downloadable reports
|
||||
- **Solution Implemented**:
|
||||
- Created new API route `/api/debug/download-schema` for production schema downloads
|
||||
- Added comprehensive schema report generation with tables, columns, constraints, and record counts
|
||||
- Enhanced `client/src/pages/DatabaseDebug.tsx`: Added download button that appears after successful scans
|
||||
- Implemented proper file download headers with automatic filename generation
|
||||
- Added admin-only access restriction and production environment validation
|
||||
- **Download Report Features**:
|
||||
- Complete database structure with column details and constraints
|
||||
- Record counts per table for data overview
|
||||
- Foreign key relationships mapping
|
||||
- Formatted text file with timestamps and user information
|
||||
- **Result**: Administrators can now download comprehensive database schema reports for documentation and analysis
|
||||
|
||||
#### Employee Supplier Access Fix
|
||||
- **Issue**: Employee role could not access supplier lists in Customer Orders and DLC modules on production server
|
||||
- **Root Cause**: API route `/api/suppliers` was restricted to admin and manager roles only, excluding employees and directeurs
|
||||
- **Solution Implemented**:
|
||||
- Updated `/api/suppliers` GET route: Added employee and directeur role access for read operations
|
||||
- Updated `/api/suppliers` POST route: Added directeur role access for creation operations
|
||||
- Updated `/api/suppliers` PUT route: Added directeur role access for edit operations
|
||||
- Updated `/api/suppliers` DELETE route: Restricted to admin and directeur only (removed manager access)
|
||||
- Created test script `test-employee-supplier-access.js` for production verification
|
||||
- **Access Matrix Updated**:
|
||||
- **GET /api/suppliers**: admin, directeur, manager, employee (all roles can read)
|
||||
- **POST /api/suppliers**: admin, directeur, manager (creation permissions)
|
||||
- **PUT /api/suppliers**: admin, directeur, manager (edit permissions)
|
||||
- **DELETE /api/suppliers**: admin, directeur only (delete permissions)
|
||||
- **Result**: Employees can now access supplier lists in Customer Orders and DLC modules while maintaining appropriate write restrictions
|
||||
- **NocoDB Integration**: Configurable for invoice verification and data synchronization.
|
||||
+1
-1
@@ -2329,7 +2329,7 @@ RÉSUMÉ DU SCAN
|
||||
const userId = req.user.claims ? req.user.claims.sub : req.user.id;
|
||||
const user = await storage.getUser(userId);
|
||||
|
||||
if (!user || !['admin', 'manager'].includes(user.role)) {
|
||||
if (!user || !['admin', 'manager', 'directeur'].includes(user.role)) {
|
||||
return res.status(403).json({ message: "Insufficient permissions to validate products" });
|
||||
}
|
||||
|
||||
|
||||
@@ -80,12 +80,12 @@ const PERMISSIONS: Record<Module, Record<Role, Permission[]>> = {
|
||||
employee: ['view', 'create']
|
||||
},
|
||||
|
||||
// Tâches - Admin/Directeur tout, Manager view + validate, Employé view
|
||||
// Tâches - Admin/Directeur tout, Manager view + validate, Employé view + create
|
||||
tasks: {
|
||||
admin: ['view', 'create', 'edit', 'delete', 'validate'],
|
||||
directeur: ['view', 'create', 'edit', 'delete', 'validate'],
|
||||
manager: ['view', 'validate'],
|
||||
employee: ['view']
|
||||
employee: ['view', 'create']
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user