diff --git a/PRODUCTION-FIX-GUIDE.md b/PRODUCTION-FIX-GUIDE.md index 82458cc..5875fe1 100644 --- a/PRODUCTION-FIX-GUIDE.md +++ b/PRODUCTION-FIX-GUIDE.md @@ -52,8 +52,19 @@ Si l'interface affiche "Aucun utilisateur trouvé" : - `production-users-debug.sql` : Problème de récupération des utilisateurs ### Problème Création d'Utilisateur -Si la création d'utilisateur échoue : +#### Erreur "duplicate key value violates unique constraint users_email_key" +Cette erreur survient quand plusieurs utilisateurs ont un email vide (`""`) car PostgreSQL traite les chaînes vides comme des valeurs uniques. + +**Solution** : +1. Exécutez le script de correction : + ```bash + psql $DATABASE_URL -f fix-duplicate-empty-email.sql + ``` + +2. Redéployez l'application (le code a été corrigé pour utiliser `NULL` au lieu de `""`) + +#### Tests de Création 1. **Test Manuel** : Utilisez `test-create-user-production.js` ```bash PRODUCTION_HOST=votre-domaine.com SESSION_COOKIE="connect.sid=..." node test-create-user-production.js @@ -62,7 +73,7 @@ Si la création d'utilisateur échoue : 2. **Vérification Logs** : Cherchez ces messages d'erreur : - `❌ Password hashing failed` - `❌ Storage createUser error` - - Database connection errors + - `duplicate key value violates unique constraint` ### Logs de Débogage Disponibles **Récupération Utilisateurs :** diff --git a/attached_assets/Pasted--group-created-at-2025-07-22-11-09-08-977622-group-updated-at-2025-07-28-1-1754942841066_1754942841066.txt b/attached_assets/Pasted--group-created-at-2025-07-22-11-09-08-977622-group-updated-at-2025-07-28-1-1754942841066_1754942841066.txt new file mode 100644 index 0000000..56daa6f --- /dev/null +++ b/attached_assets/Pasted--group-created-at-2025-07-22-11-09-08-977622-group-updated-at-2025-07-28-1-1754942841066_1754942841066.txt @@ -0,0 +1,201 @@ + + + group_created_at: '2025-07-22 11:09:08.977622', + + group_updated_at: '2025-07-28 18:25:49.452346' + + } + +] + +✅ Processed 1 groups for user _1753266816257 + +🔐 API /api/users - Returning: { isArray: true, length: 7, totalGroups: 6 } + +GET /api/users 304 in 81ms + +HEAD /api/health 200 in 1ms + +🔍 getUserWithGroups called for user: admin_local + +🔍 Querying user_groups for user: admin_local + +🔍 Found 0 group assignments for user admin_local + +🔍 Raw query result: [] + +✅ Processed 0 groups for user admin_local + +🔍 getUserWithGroups called for user: admin_local + +🔍 Querying user_groups for user: admin_local + +🔍 Found 0 group assignments for user admin_local + +🔍 Raw query result: [] + +✅ Processed 0 groups for user admin_local + +🔍 POST /api/users - Creating new user + +📥 Request body: { + + "email": "", + + "firstName": "", + + "lastName": "", + + "username": "ff292m", + + "password": "ff292m", + + "role": "manager", + + "id": "_1754942821925" + +} + +🔍 getUserWithGroups called for user: admin_local + +🔍 Querying user_groups for user: admin_local + +🔍 Found 0 group assignments for user admin_local + +🔍 Raw query result: [] + +✅ Processed 0 groups for user admin_local + +🔍 Parsing user data... + +✅ User data parsed successfully + +🔒 Hashing password... + +✅ Password hashed successfully + +🔍 Generated user ID: _1754942821925 + +🔍 Creating user in database... + +🔍 Storage createUser called with: ff292m + +❌ Storage createUser error: error: duplicate key value violates unique constraint "users_email_key" + + at /app/node_modules/pg-pool/index.js:45:11 + + at process.processTicksAndRejections (node:internal/process/task_queues:95:5) + + at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22 + + at async DatabaseStorage.createUser (file:///app/dist/index.js:989:26) + + at async file:///app/dist/index.js:3993:23 { + + length: 192, + + severity: 'ERROR', + + code: '23505', + + detail: 'Key (email)=() already exists.', + + hint: undefined, + + position: undefined, + + internalPosition: undefined, + + internalQuery: undefined, + + where: undefined, + + schema: 'public', + + table: 'users', + + column: undefined, + + dataType: undefined, + + constraint: 'users_email_key', + + file: 'nbtinsert.c', + + line: '664', + + routine: '_bt_check_unique' + +} + +❌ Storage error code: 23505 + +❌ Storage error constraint: users_email_key + +❌ Error creating user: error: duplicate key value violates unique constraint "users_email_key" + + at /app/node_modules/pg-pool/index.js:45:11 + + at process.processTicksAndRejections (node:internal/process/task_queues:95:5) + + at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22 + + at async DatabaseStorage.createUser (file:///app/dist/index.js:989:26) + + at async file:///app/dist/index.js:3993:23 { + + length: 192, + + severity: 'ERROR', + + code: '23505', + + detail: 'Key (email)=() already exists.', + + hint: undefined, + + position: undefined, + + internalPosition: undefined, + + internalQuery: undefined, + + where: undefined, + + schema: 'public', + + table: 'users', + + column: undefined, + + dataType: undefined, + + constraint: 'users_email_key', + + file: 'nbtinsert.c', + + line: '664', + + routine: '_bt_check_unique' + +} + +❌ Error type: DatabaseError + +❌ Error code: 23505 + +❌ Error constraint: users_email_key + +❌ Error stack: error: duplicate key value violates unique constraint "users_email_key" + + at /app/node_modules/pg-pool/index.js:45:11 + + at process.processTicksAndRejections (node:internal/process/task_queues:95:5) + + at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22 + + at async DatabaseStorage.createUser (file:///app/dist/index.js:989:26) + + at async file:///app/dist/index.js:3993:23 + +POST /api/users 409 in 109ms \ No newline at end of file diff --git a/attached_assets/image_1754942828642.png b/attached_assets/image_1754942828642.png new file mode 100644 index 0000000..ac8d34b Binary files /dev/null and b/attached_assets/image_1754942828642.png differ diff --git a/fix-duplicate-empty-email.sql b/fix-duplicate-empty-email.sql new file mode 100644 index 0000000..ef180c6 --- /dev/null +++ b/fix-duplicate-empty-email.sql @@ -0,0 +1,28 @@ +-- Fix duplicate empty email constraint issue in production +-- This script converts empty string emails to NULL to allow multiple users without email + +-- Step 1: Update all empty string emails to NULL +UPDATE users +SET email = NULL +WHERE email = '' OR email IS NULL OR TRIM(email) = ''; + +-- Step 2: Verify the change +SELECT 'Users with NULL email:' as status, COUNT(*) as count +FROM users +WHERE email IS NULL; + +-- Step 3: Verify no empty string emails remain +SELECT 'Users with empty string email:' as status, COUNT(*) as count +FROM users +WHERE email = ''; + +-- Step 4: Show sample of updated users +SELECT id, username, + CASE + WHEN email IS NULL THEN '[NULL]' + ELSE email + END as email_display, + role +FROM users +ORDER BY username +LIMIT 10; \ No newline at end of file diff --git a/server/routes.ts b/server/routes.ts index 64936f8..6c7a5b1 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -921,7 +921,7 @@ export async function registerRoutes(app: Express): Promise { const createUserSchema = z.object({ id: z.string().optional(), username: z.string().min(1, "L'identifiant est obligatoire"), - email: z.union([z.string().email(), z.literal("")]).optional(), + email: z.union([z.string().email(), z.literal(""), z.null()]).optional(), firstName: z.string().optional(), lastName: z.string().optional(), password: z.string().min(1, "Le mot de passe est obligatoire"), @@ -952,7 +952,7 @@ export async function registerRoutes(app: Express): Promise { const userToCreate = { id: newUserId, username: userData.username, - email: userData.email || '', + email: userData.email && userData.email.trim() !== '' ? userData.email : null, // Use NULL instead of empty string firstName: userData.firstName || '', lastName: userData.lastName || '', password: hashedPassword,