TP1 – Mise en pratique : Express & Prisma
Créez votre première API backend avec Express et Prisma, en appliquant une architecture propre et maintenable.
🎯 Contexte
Vous développez une API backend pour la bibliothèque de l’ULCO.
Cette API devra permettre :
- de gérer des auteurs
- de gérer des livres
- d’associer un livre à un auteur
L’objectif est de manipuler une base de données relationnelle via un ORM, sans écrire de SQL, tout en respectant les bonnes pratiques vues en cours.
✅ Attendus pédagogiques
À l’issue de ce TP, vous devez être capables de :
- mettre en place une API REST avec Express
- utiliser Prisma comme couche d’accès aux données
- structurer votre projet en routes / controllers / services / repositories
- gérer les codes HTTP de manière cohérente
- raisonner en termes de logique métier, indépendamment du framework
👉 Vous êtes guidés sur la structure, mais pas sur les implémentations détaillées : à vous de mobiliser vos compétences.
🚀 Initialisation du projet
1️⃣ Création du projet
- Créez un nouveau dossier :
TP1_NOM_PRENOM_TPX
- Initialisez un projet Node.js :
npm init -y
2️⃣ Dépendances à installer
Installez les dépendances nécessaires au projet :
- express → serveur HTTP
- prisma → ORM
- typescript (tsc) → typage statique
- nodemon → rechargement automatique du serveur
- sqlite → base de données (recommandée pour ce TP)
💡 Astuce : distinguez dépendances et dépendances de développement.
3️⃣ Initialisation de Prisma
- Initialisez Prisma :
npx prisma init
Vous devez obtenir :
-
un dossier
prisma/ -
un fichier
schema.prisma -
Configurez la datasource (SQLite recommandée).
⚠️ Pensez à générer le client Prisma après chaque modification du schéma.
4️⃣ Serveur Express
- Créez un serveur Express minimal
- Activez le parsing JSON
- Écoutez sur un port configurable
💡 Indice : votre serveur ne doit contenir aucune logique métier.
👤 Création du modèle Auteur
Dans schema.prisma, créez un modèle Auteur avec :
id: clé primaire auto-incrémentéenom: Stringprenom: StringanneeNaissance: Number
📌 Réfléchissez dès maintenant à :
- l’unicité logique d’un auteur
- la future relation avec les livres
🧩 Architecture Auteur
Pour la gestion des auteurs, vous devez respecter strictement l’architecture suivante :
auteur.route.ts → définition des routes
│
auteur.controller.ts → gestion HTTP (req / res / status)
│
auteur.service.ts → logique métier
│
auteur.repository.ts → accès Prisma uniquement
💡 Règle d’or :
- une couche n’appelle que la couche située juste en dessous
- Prisma n’est jamais utilisé ailleurs que dans le repository
🌐 Routes Auteur à implémenter
| Méthode | URL | Description |
|---|---|---|
| GET | /authors | Récupérer tous les auteurs |
| GET | /authors/:id | Récupérer un auteur par id |
| POST | /authors | Créer un auteur |
| DELETE | /authors/:id | Supprimer un auteur |
Cas à gérer obligatoirement
- ❌ Aucun auteur trouvé → 404 Not Found
- ❌ Auteur déjà existant (nom, prénom, année identiques) → 409 Conflict
📌 Indice important :
La vérification des doublons doit être faite dans le service, jamais dans la route.
📚 Création du modèle Livre (niveau intermédiaire)
Ajoutez un modèle Livre avec :
id: clé primaire auto-incrémentéetitre: StringauthorId: clé étrangère- relation avec
Auteur
⚠️ Rappel relationnel :
- un livre → un seul auteur
- un auteur → plusieurs livres
💡 Vérifiez que votre schéma reflète correctement cette cardinalité.
🌐 Routes Livre à implémenter
| Méthode | URL | Description |
|---|---|---|
| GET | /books | Récupérer tous les livres |
| GET | /books/:id | Récupérer un livre |
| POST | /books | Créer un livre |
| DELETE | /books/:id | Supprimer un livre |
📌 Réfléchissez à :
- la validation de l’auteur lors de la création d’un livre
- la cohérence des réponses HTTP
⭐ Pour aller plus loin
Implémentez la route suivante :
GET /authors/:id/books
Elle doit retourner un auteur avec la liste de ses livres.
Exemple de réponse attendue
{
"id": 1,
"nom": "Hugo",
"prenom": "Victor",
"livres": [
{ "id": 1, "titre": "Les Misérables" },
{ "id": 2, "titre": "Notre-Dame de Paris" }
]
}
💡 Indice : cette fonctionnalité se gère principalement au niveau du repository.
🔐 Authentification (extension du TP)
Cette partie correspond au cours suivant et vise à enrichir votre API avec un système d’authentification JWT.
L’objectif n’est pas de tout réécrire, mais d’intégrer l’authentification dans l’architecture existante, en respectant les mêmes règles (routes / controllers / services / repositories).
🎯 Objectifs pédagogiques
À l’issue de cette extension, vous devez être capables de :
- comprendre le fonctionnement global d’une authentification par JWT
- stocker des mots de passe hashés en base de données
- générer un token lors du login
- protéger certaines routes avec un middleware
- exploiter les informations du token côté backend
👤 Modèle User
Ajoutez un nouveau modèle User dans votre schéma Prisma.
Il devra contenir :
- un
id(clé primaire auto-incrémentée) - un
name - un
emailunique - un
password(hashé)
📌 Rappel fondamental :
Les mots de passe ne doivent JAMAIS être stockés en clair.
Vous devrez :
- créer une migration
- vérifier que Prisma génère bien le client
🔑 Principes de l’authentification JWT
-
Lorsqu’un utilisateur se connecte, il fournit email + mot de passe
-
Le serveur vérifie :
- que l’utilisateur existe
- que le mot de passe est correct (via
bcrypt.compare)
-
Si tout est valide, le serveur génère un JWT
-
Ce token est renvoyé au client
-
Pour accéder à des routes protégées, le client doit fournir ce token dans l’en-tête :
Authorization: Bearer <TOKEN>
🧩 Architecture Auth
Vous devez respecter la même logique que pour les autres modules :
auth.route.ts → endpoints d’authentification
auth.controller.ts → gestion HTTP
auth.service.ts → logique de login
auth.repository.ts → accès Prisma (User)
auth.middleware.ts → vérification du JWT
⚠️ Le middleware ne contient aucune logique métier, uniquement de la validation de token.
🌐 Endpoint à implémenter
POST /auth/login
Cette route doit :
- recevoir un
emailet unpassword - vérifier que l’utilisateur existe
- vérifier le mot de passe
- générer un JWT signé avec une clé secrète
- renvoyer le token et les informations publiques de l’utilisateur
📌 Codes HTTP attendus :
200→ connexion réussie401→ identifiants invalides500→ erreur serveur
🛡️ Middleware d’authentification
Créez un middleware chargé de :
- récupérer le token depuis l’en-tête
Authorization - vérifier sa validité
- extraire les informations utiles (ex:
userId) - bloquer l’accès si le token est manquant, invalide ou expiré
📌 Indice :
Vous devrez étendre le type
Requestd’Express pour y attacher l’identifiant utilisateur.
🔒 Protéger certaines routes
Appliquez le middleware d’authentification sur :
- au moins une route existante (par exemple la création d’un utilisateur ou d’une ressource)
Exemple de réflexion attendue :
- Quelles routes doivent être publiques ?
- Quelles routes doivent être réservées aux utilisateurs authentifiés ?
⭐ Pour aller plus loin (optionnel)
- Ajouter une durée d’expiration au token
- Centraliser la gestion des erreurs d’authentification
- Associer certaines actions à l’utilisateur connecté
🏁 Fin du TP
Lorsque vous avez terminé :
- assurez-vous que votre projet est fonctionnel et proprement structuré
- testez vos routes (Postman, Insomnia, etc.)
📣 Contactez-moi pour validation.
👉 Un bonus pourra être accordé sur le projet final en fonction :
- de la qualité de l’architecture
- de la rigueur du code
- de la gestion des erreurs
Bon courage 🚀