# Correction des erreurs 400 lors de la création d'utilisateurs ## Problème identifié Un administrateur (fk_role=2) rencontrait des erreurs 400 répétées lors de tentatives de création de membre, menant à un bannissement par fail2ban : - 17:09:39 - POST /api/users HTTP/1.1 400 (Bad Request) - 17:10:44 - POST /api/users/check-username HTTP/1.1 400 (Bad Request) - 17:11:21 - POST /api/users HTTP/1.1 400 (Bad Request) ## Causes identifiées ### 1. Conflit de routage (CRITIQUE) **Problème:** La route `/api/users/check-username` était déclarée APRÈS la route générique `/api/users` dans Router.php, causant une mauvaise interprétation où "check-username" était traité comme un ID utilisateur. **Solution:** Déplacer la déclaration de la route spécifique AVANT les routes avec paramètres. ### 2. Messages d'erreur non informatifs **Problème:** Les erreurs 400 retournaient des messages génériques sans détails sur le champ problématique. **Solution:** Ajout de messages d'erreur détaillés incluant : - Le champ en erreur (`field`) - La valeur problématique (`value`) - Le format attendu (`format`) - La raison de l'erreur (`reason`) ### 3. Manque de logs de débogage **Problème:** Aucun log n'était généré pour tracer les erreurs de validation. **Solution:** Ajout de logs détaillés à chaque point de validation. ## Modifications apportées ### 1. Router.php (ligne 36-44) ```php // AVANT (incorrect) $this->post('users', ['UserController', 'createUser']); $this->post('users/check-username', ['UserController', 'checkUsername']); // APRÈS (correct) $this->post('users/check-username', ['UserController', 'checkUsername']); // Route spécifique en premier $this->post('users', ['UserController', 'createUser']); ``` ### 2. UserController.php - Amélioration des validations #### Validation de l'email ```php // Réponse améliorée Response::json([ 'status' => 'error', 'message' => 'Email requis', 'field' => 'email' // Indique clairement le champ problématique ], 400); ``` #### Validation du username manuel ```php // Réponse améliorée Response::json([ 'status' => 'error', 'message' => 'Le nom d\'utilisateur est requis pour cette entité', 'field' => 'username', 'reason' => 'L\'entité requiert la saisie manuelle des identifiants' ], 400); ``` #### Format du username ```php // Réponse améliorée Response::json([ 'status' => 'error', 'message' => 'Format du nom d\'utilisateur invalide', 'field' => 'username', 'format' => '10-30 caractères, commence par une lettre, caractères autorisés: a-z, 0-9, ., -, _', 'value' => $username // Montre la valeur soumise ], 400); ``` ### 3. Ajout de logs détaillés Chaque point de validation génère maintenant un log avec : - Le type d'erreur - L'utilisateur qui fait la requête - Les données reçues (sans données sensibles) - Le contexte de l'erreur Exemple : ```php LogService::log('Erreur création utilisateur : Format username invalide', [ 'level' => 'warning', 'createdBy' => $currentUserId, 'email' => $email, 'username' => $username, 'username_length' => strlen($username) ]); ``` ## Cas d'erreur 400 possibles ### Pour /api/users (création) 1. **Email manquant ou vide** - Message: "Email requis" - Field: "email" 2. **Nom manquant ou vide** - Message: "Nom requis" - Field: "name" 3. **Format email invalide** - Message: "Format d'email invalide" - Field: "email" - Value: [email soumis] 4. **Username manuel requis mais manquant** (si chk_username_manuel=1) - Message: "Le nom d'utilisateur est requis pour cette entité" - Field: "username" - Reason: "L'entité requiert la saisie manuelle des identifiants" 5. **Format username invalide** - Message: "Format du nom d'utilisateur invalide" - Field: "username" - Format: "10-30 caractères, commence par une lettre..." - Value: [username soumis] 6. **Mot de passe manuel requis mais manquant** (si chk_mdp_manuel=1) - Message: "Le mot de passe est requis pour cette entité" - Field: "password" - Reason: "L'entité requiert la saisie manuelle des mots de passe" ### Pour /api/users/check-username 1. **Username manquant** - Message: "Username requis pour la vérification" - Field: "username" 2. **Format username invalide** - Message: "Format invalide" - Field: "username" - Format: "10-30 caractères, commence par une lettre..." - Value: [username soumis] ## Test de la solution Un script de test a été créé : `/tests/test_user_creation.php` Il teste tous les cas d'erreur possibles et vérifie que : 1. Les codes HTTP sont corrects 2. Les messages d'erreur sont informatifs 3. Les champs en erreur sont identifiés ## Recommandations pour éviter le bannissement fail2ban 1. **Côté client (application Flutter)** : - Valider les données AVANT l'envoi - Afficher clairement les erreurs à l'utilisateur - Implémenter un délai entre les tentatives (rate limiting côté client) 2. **Côté API** : - Les messages d'erreur détaillés permettent maintenant de corriger rapidement les problèmes - Les logs permettent de diagnostiquer les problèmes récurrents 3. **Configuration fail2ban** : - Considérer d'augmenter le seuil pour les erreurs 400 (ex: 5 tentatives au lieu de 3) - Exclure certaines IP de confiance si nécessaire ## Suivi des logs Les logs sont maintenant générés dans : - `/logs/geosector-[environment]-[date].log` : Logs généraux avec détails des erreurs Format des logs : ``` timestamp;browser;os;client_type;level;metadata;message ``` Les erreurs de validation sont loggées avec le niveau "warning" pour permettre un suivi sans être critiques.