mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-21 14:08:15 +02:00
Fix user creation errors by handling empty emails properly
Adjust user creation schema to allow null emails, update data handling to convert empty strings to null, and provide a SQL script to clean up existing duplicate empty email entries, resolving the `users_email_key` constraint violation. Replit-Commit-Author: Agent Replit-Commit-Session-Id: a8a78c07-e900-425c-a577-5b4c5894379d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/a8a78c07-e900-425c-a577-5b4c5894379d/aiHrulP
This commit is contained in:
1 parent
b886f317ca
commit
c77ea88e9d
5 files changed
+244
-4
No files matched your search
+13
-2
@@ -52,8 +52,19 @@ Si l'interface affiche "Aucun utilisateur trouvé" :
|
|||||||
- `production-users-debug.sql` : Problème de récupération des utilisateurs
|
- `production-users-debug.sql` : Problème de récupération des utilisateurs
|
||||||
|
|
||||||
### Problème Création d'Utilisateur
|
### 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`
|
1. **Test Manuel** : Utilisez `test-create-user-production.js`
|
||||||
```bash
|
```bash
|
||||||
PRODUCTION_HOST=votre-domaine.com SESSION_COOKIE="connect.sid=..." node test-create-user-production.js
|
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 :
|
2. **Vérification Logs** : Cherchez ces messages d'erreur :
|
||||||
- `❌ Password hashing failed`
|
- `❌ Password hashing failed`
|
||||||
- `❌ Storage createUser error`
|
- `❌ Storage createUser error`
|
||||||
- Database connection errors
|
- `duplicate key value violates unique constraint`
|
||||||
|
|
||||||
### Logs de Débogage Disponibles
|
### Logs de Débogage Disponibles
|
||||||
**Récupération Utilisateurs :**
|
**Récupération Utilisateurs :**
|
||||||
|
|||||||
+201
@@ -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
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 311 KiB |
@@ -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;
|
||||||
+2
-2
@@ -921,7 +921,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
const createUserSchema = z.object({
|
const createUserSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
username: z.string().min(1, "L'identifiant est obligatoire"),
|
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(),
|
firstName: z.string().optional(),
|
||||||
lastName: z.string().optional(),
|
lastName: z.string().optional(),
|
||||||
password: z.string().min(1, "Le mot de passe est obligatoire"),
|
password: z.string().min(1, "Le mot de passe est obligatoire"),
|
||||||
@@ -952,7 +952,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
const userToCreate = {
|
const userToCreate = {
|
||||||
id: newUserId,
|
id: newUserId,
|
||||||
username: userData.username,
|
username: userData.username,
|
||||||
email: userData.email || '',
|
email: userData.email && userData.email.trim() !== '' ? userData.email : null, // Use NULL instead of empty string
|
||||||
firstName: userData.firstName || '',
|
firstName: userData.firstName || '',
|
||||||
lastName: userData.lastName || '',
|
lastName: userData.lastName || '',
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
|
|||||||
Reference in new issue
Block a user