Semaine 2
Le lien du Discord est : https://discord.gg/KERTwSz63
Lors de cette séance, nous allons ajouter une base de données (BDD) à notre service pour stocker les utilisateurs, puis hacher leurs mots de passe. Le contrôleur User utilisera ensuite la BDD et proposera de nouvelles routes.
Changements à apporter au code de la semaine 1
Conservez les modèles User, UserPass, UserPublic et l’énumération UserRole de la semaine 1.
En revanche, la liste static _users et le compteur _nextId disparaissent : la BDD stocke désormais les utilisateurs et leur attribue les identifiants.
Base de données
Lisez le chapitre Base de données, puis :
- Installez les paquets EF Core et l’outil
dotnet ef: voir Installation des dépendances. - Créez une classe
BDDContextdans le dossierModels, avec une propriétéDbSet<User> Users: voir Définir notre connexion à une BDD. La table s’appelleraUsers. - Configurez SQLite avec le fichier
BDD.db(Configurer SQLite), puis enregistrez le contexte dansProgram.cs(Initialiser la BDD au lancement). - Créez la migration initiale, puis appliquez-la : voir Les migrations et Création de la BDD.
L’enregistrement du contexte dans Program.cs ne crée pas la table : tant que la migration n’est pas appliquée, les requêtes échouent.
Hacher les mots de passe
Les mots de passe ne doivent jamais être stockés en clair. Lisez le chapitre Password Hasher, puis :
- Enregistrez un
PasswordHasher<User>dansProgram.cs: voir Injecter le hasher. Register: hachez le mot de passe avant d’enregistrer l’utilisateur.Login: recherchez d’abord l’utilisateur par sonUsername, puis vérifiez le mot de passe reçu avecVerifyHashedPassword: voir Vérifier un mot de passe. Ne comparez jamais le mot de passe reçu au champPassword, et ne cherchez pas un utilisateur à partir de son mot de passe.PUT: si un nouveau mot de passe est fourni, hachez-le avant l’enregistrement. S’il est absent ou vide, conservez le mot de passe actuel.
Si vous avez enregistré des utilisateurs avant de hacher leurs mots de passe, supprimez-les : ils ne pourront plus se connecter.
UserPublic.
Utiliser la BDD dans le contrôleur
Injectez BDDContext et PasswordHasher<User> dans le constructeur de UserController : voir Injection de dépendance et Utiliser la BDD dans un contrôleur. Réécrivez ensuite les actions pour qu’elles utilisent la BDD ; elles deviennent asynchrones (voir Async).
Chapitres utiles pour chaque opération :
- récupérer un utilisateur par son identifiant : Récupérer des données ;
- rechercher par pseudo, par rôle ou par fragment de pseudo : Rechercher des données et LINQ ;
- ajouter, modifier et supprimer : Ajouter des données, Mettre à jour des données et Supprimer des données ;
- choisir les réponses : Codes de retour d’un contrôleur.
Vous pouvez ajouter la contrainte :int aux paramètres {id} de vos routes : voir Annotations.
Routes attendues
| Route | Entrée | Comportement | Réponse HTTP |
|---|---|---|---|
GET /api/User/{id} | Identifiant dans l’URL | Renvoie l’utilisateur correspondant. | 200 + UserPublic, ou 404 |
POST /api/User/Register | Corps JSON UserPass | Crée un utilisateur avec le rôle User et un mot de passe haché. | 200 + UserPublic |
POST /api/User/Login | Corps JSON UserPass | Vérifie le pseudo et le mot de passe. | 200 + UserPublic ; 404 si le pseudo est inconnu ; 401 si le mot de passe est incorrect |
PUT /api/User/{id} | Identifiant dans l’URL et corps JSON UserUpdate | Modifie le pseudo, le rôle et, s’il est fourni, le mot de passe. | 200 + UserPublic, ou 404 |
DELETE /api/User/{id} | Identifiant dans l’URL | Supprime l’utilisateur. | 200 + true, ou 404 |
GET /api/User/All | Aucune | Renvoie tous les utilisateurs. | 200 + liste de UserPublic |
GET /api/User/AllAdmin | Aucune | Renvoie les utilisateurs dont le rôle est Admin. | 200 + liste de UserPublic |
GET /api/User/Search/{name} | Fragment de pseudo dans l’URL | Renvoie les utilisateurs dont le Username contient name, en respectant les majuscules et minuscules. | 200 + liste de UserPublic |
Une liste sans résultat est renvoyée sous la forme [].
UserUpdate est une nouvelle classe, indépendante de UserPass, avec trois propriétés : Username, Password et Role (de type UserRole). Déclarez Password en string? pour qu’il puisse être omis.
L’unicité des pseudos sera traitée en semaine 3.
Vérification finale et livrables
Relancez l’API, ouvrez Scalar et vérifiez que les huit routes apparaissent. Réalisez ensuite le scénario suivant :
- Inscrivez Alice puis Bob avec
Register: vérifiez le code200, l’identifiant attribué, le rôle1et l’absence de mot de passe dans la réponse. - Ouvrez
BDD.db, par exemple avec l’extension SQLite Viewer citée dans le Setup : la colonnePassworddoit contenir un hash, et non le mot de passe saisi. - Redémarrez l’application, puis appelez
All: Alice et Bob doivent toujours apparaître. - Appelez
Loginpour Alice avec le bon mot de passe (200), avec un mauvais mot de passe (401), puis avec un pseudo inexistant (404). - Avec
PUT, donnez le rôle0(Admin) à Alice en conservant son pseudo et sans fournir de mot de passe : Alice doit apparaître dansAllAdminet se connecter avec son ancien mot de passe. - Avec
PUT, changez le mot de passe de Bob : l’ancien mot de passe doit renvoyer401, le nouveau200. - Appelez
SearchavecAli: seule Alice doit apparaître. Avecali, la liste doit être vide. - Supprimez Bob avec
DELETE(200ettrue), puis demandez-le avecGET /api/User/{id}: vous devez recevoir404.
À la fin de la séance, vous devez avoir :
- Les modèles
User,UserPass,UserPublic,UserUpdateet l’énumérationUserRole(Admin = 0,User = 1). - Un
BDDContextenregistré dansProgram.cs, une migration initiale appliquée et un fichierBDD.dbcontenant la tableUsers. - Les huit routes de
UserControllerreposant sur la BDD, sans listestatic. - Des mots de passe hachés en base, et aucun mot de passe dans les réponses.