Skip to content

3. Chapitre 2 - Installation du serveur [NestJS]

Le client [Kotlin] de ce document a besoin d’un serveur à interroger : le serveur [NestJS] de l’application [RdvMedecins], livré avec ce document dans le dossier [rdvmedecins-nestjs-server]. Ce document étant consacré à [Kotlin], ce serveur y est traité comme une « boîte noire » : ce chapitre explique comment l’installer, le configurer, créer sa base de données [MySQL], le lancer et le tester, mais n’en étudie pas le code. Le lecteur qui souhaite apprendre [NestJS] pourra lire le document Introduction au langage TypeScript et au framework NestJS (2026).

Ce chapitre reprend à l’identique le chapitre 2 du cours Un exemple de client / serveur - Flutter / NestJS (2026) : le serveur, sa base de données et ses tests sont exactement les mêmes. Le lecteur qui a déjà installé ce serveur pour le cours Flutter peut passer directement à la dernière section de ce chapitre, « Lancer le client Kotlin pour la première fois ».

3.1. Installation de Laragon

Pour créer la base de données [MySQL] utilisée par le serveur [NestJS], nous allons utiliser l’outil Laragon. En septembre 2026, Laragon est disponible à l’URL [Download Laragon – Fast & Modern Dev Environment ]. Laragon amène avec lui des outils qui permettent d’installer un serveur PHP et le SGBD [MySQL] :

Image

  • en [1], un serveur web Apache ;
  • en [2], le SGBD [MySQL] ;
  • en [3], un outil de messagerie que nous n’utiliserons pas ;
  • en [4], lance tous les services (Apache, [MySQL], MailPit) ;
  • en [5], affiche la page web d’URL [http://localhost]. Par défaut, cette URL désigne le dossier <laragon-install>\www où <laragon-install> est le dossier d’installation de Laragon ;
  • en [6], lance l’Outil HeidiSQL qui permet de gérer des bases de données MySQL. C’est avec cet outil que nous créerons la base de données utilisée par le serveur [RdvMedecins] ;
  • en [7], ouvre un terminal dans lequel tous les binaires utiles à Laragon sont dans le PATH ;
  • en [8], ouvre un explorateur windows dans le dossier associé à l’URL [http://localhost] ;

Le dossier d’installation de Laragon comporte les éléments suivants :

 
  • En [1], le dossier [bin] contient de nombreuses applications :
  • En [1], le serveur web Apache ;
  • en [2], un terminal de commandes ;
  • en [3], un client [git] permettant de versionner les différentes versions d’un projet ;
  • en [4], un gestionnaire de bases de données ;
  • en [5], un gestionnaire courrier ;
  • en [6], le SGBD [MySQL] ;
  • en [7], un autre serveur web ;
  • en [8], [node.js] pour exécuter des scripts Javascript ;
  • en [9], un éditeur de texte ;
  • en [10], l’interpréteur PHP ;
  • en [11], l’interpréteur [Python] ;
  • en [12], un serveur de cache ;

Laragon ramène avec lui un environnement de développement conséquent. Dans ce cours, nous n’utiliserons que le SGBD [MySQL] [6] et l’outil [heidisql] pour le gérer graphiquement ;

3.2. Installation et configuration du serveur [NestJS]

Le dossier [rdvmedecins-nestjs-server] a l’arborescence suivante :

rdvmedecins-nestjs-server/
├── package.json                  # dépendances et scripts npm
├── tsconfig.json                 # configuration du compilateur TypeScript
├── nest-cli.json                 # configuration du CLI NestJS
├── .env.example                  # modèle du fichier de configuration .env
├── database/
│   └── dbrdvmedecins.sql         # script de création de la base de données
└── src/
    ├── main.ts                   # point d'entrée du serveur
    ├── app.module.ts             # module racine
    ├── config/                   # connexion à la base de données
    ├── entities/                 # entités TypeORM (une classe par table)
    ├── domain/                   # objets métier
    ├── repositories/             # accès aux données (couche DAO)
    ├── metier/                   # couche métier
    ├── web/                      # contrôleur JSON et modèles de réponse
    └── auth/                     # authentification JWT et rôles

Chaque sous-dossier de [src/] contient son propre [README.md], qui résume le rôle des fichiers qu’il contient. Le code source de ces fichiers n’est pas étudié dans ce document.

Dans le dossier [rdvmedecins-nestjs-server], tapez les commandes suivantes dans un terminal :

npm install
cp .env.example .env

Le fichier [.env] fixe des variables d’environnement :

# -----------------------------------------------------------------------
# Fichier d'exemple de configuration.
# Copier ce fichier en [.env] puis adapter les valeurs à votre machine.
# Le fichier [.env] ne doit jamais être partagé ou commité (mots de passe).
# -----------------------------------------------------------------------

# port d'écoute du serveur NestJS (le serveur Spring original écoutait sur 8080)
PORT=8080

# paramètres de connexion à la base de données MySQL [dbrdvmedecins]
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=
DB_DATABASE=dbrdvmedecins

# en développement uniquement : TypeORM peut créer/mettre à jour automatiquement
# les tables à partir des entités. On le désactive ici car nous fournissons notre
# propre script SQL [database/dbrdvmedecins.sql], comme le faisait le projet Spring original.
DB_SYNCHRONIZE=false

# -----------------------------------------------------------------------
# authentification (cf. src/auth/)
# -----------------------------------------------------------------------
# clé secrète utilisée pour signer/vérifier les jetons JWT - à changer
# impérativement en production (une longue chaîne aléatoire, jamais commitée).
JWT_SECRET=change-moi-en-une-longue-chaine-aleatoire
# durée de validité d'un jeton JWT (cf. la documentation de la librairie [ms] :
# "60", "2h", "7d"...)
JWT_EXPIRES_IN=2h

Adaptez le fichier [.env] fraîchement créé à votre installation [MySQL] (utilisateur, mot de passe, port). Ce fichier contient aussi, depuis l’ajout de l’authentification, une clé JWT_SECRET : la valeur d’exemple convient pour suivre ce document, mais devra impérativement être remplacée par une chaîne aléatoire propre à vous avant tout usage réel.

3.3. Création de la base de données

La base de données [dbrdvmedecins] reprend, dans sa structure, celle du document original (2014, Spring 4 / [MySQL] 5) : mêmes tables [medecins], [clients], [creneaux], [rv], mêmes clés étrangères, même contrainte d’unicité. Seule nouveauté, apportée par l’étape « authentification » de ce portage : la table [users]. Les relations entre ces tables sont les suivantes : un médecin ([medecins]) possède plusieurs créneaux horaires ([creneaux], clé étrangère [id_medecin]) ; un rendez-vous ([rv]) associe un jour, un créneau (donc un médecin) et un client ([clients]) ; la table [users] est indépendante des quatre autres : elle ne sert qu’à l’authentification.

3.3.1. [database/dbrdvmedecins.sql]

Image

-- =========================================================================
-- Base de données [dbrdvmedecins] - MySQL 8
--
-- Ce script reprend EXACTEMENT le schéma relationnel du document original
-- (2014, Spring 4 / Spring Data / MySQL 5) : mêmes tables, mêmes colonnes,
-- mêmes clés étrangères, même contrainte d'unicité. Seul le moteur de base
-- de données change de nom (MySQL 5 -> MySQL 8), pas la structure.
--
-- La table [users] apparaît maintenant (étape "authentification" de ce
-- portage). Le document original utilisait TROIS tables (users, roles,
-- users_roles) pour permettre à un utilisateur d'avoir PLUSIEURS rôles.
-- Puisque cette application ne connaît que deux rôles mutuellement
-- exclusifs (ADMIN, USER), nous simplifions ici à une seule colonne [role]
-- sur la table [users] plutôt que de reconstruire la relation plusieurs-à-
-- plusieurs d'origine - une simplification pédagogique assumée, documentée
-- dans le chapitre "Authentification" du cours.
-- =========================================================================


CREATE DATABASE IF NOT EXISTS dbrdvmedecins CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE dbrdvmedecins;

-- on repart d'une base vide à chaque exécution du script (pratique en développement)
DROP TABLE IF EXISTS rv;
DROP TABLE IF EXISTS creneaux;
DROP TABLE IF EXISTS clients;
DROP TABLE IF EXISTS medecins;
DROP TABLE IF EXISTS users;

-- -------------------------------------------------------------------------
-- table [medecins] : les médecins du cabinet
-- -------------------------------------------------------------------------
CREATE TABLE medecins (
  id      INT AUTO_INCREMENT PRIMARY KEY,      -- clé primaire (identifiant technique)
  version INT NOT NULL DEFAULT 0,               -- n° de version de la ligne (verrou optimiste)
  titre   VARCHAR(5)  NOT NULL,                 -- Melle, Mme, Mr
  nom     VARCHAR(20) NOT NULL,
  prenom  VARCHAR(20) NOT NULL
);

-- -------------------------------------------------------------------------
-- table [clients] : les patients des médecins
-- -------------------------------------------------------------------------
CREATE TABLE clients (
  id      INT AUTO_INCREMENT PRIMARY KEY,
  version INT NOT NULL DEFAULT 0,
  titre   VARCHAR(5)  NOT NULL,
  nom     VARCHAR(20) NOT NULL,
  prenom  VARCHAR(20) NOT NULL
);

-- -------------------------------------------------------------------------
-- table [creneaux] : les créneaux horaires de chaque médecin
-- -------------------------------------------------------------------------
CREATE TABLE creneaux (
  id         INT AUTO_INCREMENT PRIMARY KEY,
  version    INT NOT NULL DEFAULT 0,
  id_medecin INT NOT NULL,                      -- clé étrangère -> medecins(id)
  hdebut     INT NOT NULL,                       -- heure de début du créneau
  mdebut     INT NOT NULL,                       -- minute de début du créneau
  hfin       INT NOT NULL,                       -- heure de fin du créneau
  mfin       INT NOT NULL,                       -- minute de fin du créneau
  CONSTRAINT fk_creneaux_medecin FOREIGN KEY (id_medecin) REFERENCES medecins(id)
);

-- -------------------------------------------------------------------------
-- table [rv] : les rendez-vous pris par les clients
-- -------------------------------------------------------------------------
CREATE TABLE rv (
  id         INT AUTO_INCREMENT PRIMARY KEY,
  version    INT NOT NULL DEFAULT 0,
  jour       DATE NOT NULL,                      -- jour du rendez-vous
  id_creneau INT NOT NULL,                        -- clé étrangère -> creneaux(id)
  id_client  INT NOT NULL,                        -- clé étrangère -> clients(id)
  CONSTRAINT fk_rv_creneau FOREIGN KEY (id_creneau) REFERENCES creneaux(id),
  CONSTRAINT fk_rv_client  FOREIGN KEY (id_client)  REFERENCES clients(id),
  -- un même créneau, un même jour, ne peut être réservé qu'une seule fois
  CONSTRAINT unq1_rv UNIQUE (jour, id_creneau)
);

-- -------------------------------------------------------------------------
-- table [users] : les utilisateurs autorisés à se connecter à l'application
-- -------------------------------------------------------------------------
CREATE TABLE users (
  id       INT AUTO_INCREMENT PRIMARY KEY,
  version  INT NOT NULL DEFAULT 0,
  login    VARCHAR(30) NOT NULL UNIQUE,          -- identifiant de connexion
  password VARCHAR(100) NOT NULL,                -- mot de passe HACHÉ (bcrypt) - jamais en clair
  nom      VARCHAR(40) NOT NULL,                 -- nom affiché une fois connecté
  role     VARCHAR(10) NOT NULL                  -- 'ADMIN' ou 'USER'
);

-- =========================================================================
-- Données de démonstration
-- =========================================================================

INSERT INTO medecins (titre, nom, prenom) VALUES
  ('Mme', 'PELISSIER', 'Marie'),
  ('Mr',  'TATOU',      'Paul'),
  ('Melle','DUPONT',    'Sophie');

INSERT INTO clients (titre, nom, prenom) VALUES
  ('Mr',   'MARTIN',   'Jean'),
  ('Mme',  'DURAND',   'Alice'),
  ('Melle','BISTROU',  'Brigitte'),
  ('Mr',   'GERMAN',   'Luc');

-- créneaux du docteur PELISSIER (id_medecin = 1) : de 8h00 à 12h00 par tranches de 20 minutes
INSERT INTO creneaux (id_medecin, hdebut, mdebut, hfin, mfin) VALUES
  (1, 8, 0, 8, 20), (1, 8, 20, 8, 40), (1, 8, 40, 9, 0),
  (1, 9, 0, 9, 20), (1, 9, 20, 9, 40), (1, 9, 40, 10, 0),
  (1, 10, 0, 10, 20), (1, 10, 20, 10, 40), (1, 10, 40, 11, 0),
  (1, 11, 0, 11, 20), (1, 11, 20, 11, 40), (1, 11, 40, 12, 0);

-- créneaux du docteur TATOU (id_medecin = 2) : de 14h00 à 18h00 par tranches de 20 minutes
INSERT INTO creneaux (id_medecin, hdebut, mdebut, hfin, mfin) VALUES
  (2, 14, 0, 14, 20), (2, 14, 20, 14, 40), (2, 14, 40, 15, 0),
  (2, 15, 0, 15, 20), (2, 15, 20, 15, 40), (2, 15, 40, 16, 0),
  (2, 16, 0, 16, 20), (2, 16, 20, 16, 40), (2, 16, 40, 17, 0),
  (2, 17, 0, 17, 20), (2, 17, 20, 17, 40), (2, 17, 40, 18, 0);

-- un rendez-vous déjà pris, pour voir tout de suite un créneau occupé dans l'agenda
INSERT INTO rv (jour, id_creneau, id_client) VALUES
  (CURDATE(), 2, 3);

-- deux utilisateurs de démonstration : admin/admin (rôle ADMIN, tous droits)
-- et user/user (rôle USER, lecture seule) - les mots de passe sont hachés
-- avec bcrypt (10 tours de salage), jamais stockés en clair.
INSERT INTO users (login, password, nom, role) VALUES
  ('admin', '$2b$10$YSNBJXXHX9mp13nPZb6YGu8M1jR6uvPwO1s2X73z0QAqBR7TOQjoq', 'Administrateur', 'ADMIN'),
  ('user',  '$2b$10$6Cvoion7AgJkpYHw5N0jMuWPf8T90J28En56kWBL9PT0bXt7lwW7.', 'Utilisateur',    'USER');

Commentons ce code :

  • lignes 20-21 : [CREATE DATABASE IF NOT EXISTS dbrdvmedecins …] puis [USE dbrdvmedecins] — crée la base si elle n’existe pas encore (jeu de caractères [utf8mb4], qui accepte tous les caractères Unicode, accents compris), puis la sélectionne : toutes les instructions qui suivent s’appliquent à elle. Ces deux lignes doivent impérativement venir EN PREMIER : exécutées après les [DROP TABLE …], celles-ci échoueraient faute de base sélectionnée (erreur [No database selected]) ;
  • lignes 24-28 : [DROP TABLE IF EXISTS …] — le script repart d’une base vide à chaque exécution, dans l’ordre inverse des dépendances (rv d’abord, qui référence [creneaux] et clients, jusqu’à users, qui n’est référencée par personne) : [MySQL] refuserait de supprimer une table encore référencée par une clé étrangère ;
  • ligne 58 : [id_medecin INT NOT NULL] puis ligne 63 : [CONSTRAINT fk_creneaux_medecin FOREIGN KEY …] — un créneau appartient toujours à un médecin ;
  • ligne 78 : [CONSTRAINT unq1_rv UNIQUE (jour, id_creneau)] — la règle de gestion centrale de l’application : un même créneau, un même jour, ne peut être réservé qu’une seule fois. C’est cette contrainte, et elle seule, qui empêche un double rendez-vous - ni le contrôleur ni la couche métier ne la revérifient explicitement ;
  • lignes 84-91 : [CREATE TABLE users (…)] — la table ajoutée par cette étape. login est UNIQUE (deux utilisateurs ne peuvent pas partager le même identifiant de connexion) ; password stocke un mot de passe haché par bcrypt (jamais en clair) ; role vaut 'ADMIN' ou 'USER' - une simple colonne texte, là où le document original utilisait trois tables (users, roles, users_roles) pour autoriser plusieurs rôles par utilisateur. Cette application n’ayant besoin que de deux rôles mutuellement exclusifs, la relation plusieurs-à-plusieurs d’origine serait allée au-delà du nécessaire ;
  • lignes 129-131 : [INSERT INTO users …] — deux comptes de démonstration, admin/admin (rôle ADMIN) et user/user (rôle USER), avec leurs mots de passe déjà hachés par bcrypt (10 tours de salage) - jamais en clair, y compris dans ce script de démonstration.

3.3.2. Exécution du script avec HeidiSQL

Pour créer la base de données [MySQL] nécessaire au serveur [NestJS], nous procédons de la façon suivante :

 
  • En [1], tous les services doivent être lancés ;
  • en [2], l’option [Database] vous permet de gérer la base de données ;

L’option [Database] lance un utilitaire appelé HeidiSQL :

  • En [1], vous pouvez sélectionner divers SGBD. La valeur par défaut proposée est le SGBD MySQL. Cela convient ;
  • en [2], vous ouvrez une session de HeidiSQL ;
  • En [1-2], exécutez un fichier SQL puis choisissez le fichier [dbrdvmedecins.sql] que vous trouverez dans le dossier [rdvmedecins-nestjs-server/database] :

Image

L’exécution du fichier [3] va créer la base [dbrdvmedecins] utilisée par le serveur [NestJS]. Pour le voir, faites F5 dans HeidiSQL pour rafraîchir l’affichage :

Image

La base de données [dbrdvmedecins] a été créée. On peut en voir le contenu :

Image

  • en [1-3], la table [clients] ;
    • [id] est la clé primaire de la table ;
    • [version] est le numéro de version de la ligne. Ce numéro augmente à chaque modification de la ligne ;
    • [titre, nom, prenom] identifient la personne ;

Image

  • en [1-3], la table [medecins] ;
    • [id] est la clé primaire de la table ;
    • [version] est le numéro de version de la ligne ;
    • [titre, nom, prenom] identifient la personne ;

Image

  • en [1-3], la table des créneaux horaires de consultation des médecins :
    • [id] : clé primaire ;
    • [version] : numéro de version de la ligne ;
    • [id-medecin] : clé étrangère ciblée sur la clé primaire du médecin ;
    • [hdebut, mdebut] : heure et minutes de début de la consultation. Ainsi [8,20] signifie 8h20.
    • [hfin, mfin] : heure et minutes de fin de la consultation.

Image

  • En [1-3], la table [rv] des rendez-vous pris ;
    • [id] : clé primaire ;
    • [version] : numéro de version ;
    • [jour] : jour du rendez-vous ;
    • [id_creneau] : clé étrangère vers la clé primaire du créneau horaire du rendez-vous. Comme un créneau horaire est lié à un médecin, on sait quel médecin assure ce rendez-vous ;
    • [id_client] : clé étrangère vers le numéro (clé primaire) du client qui consulte ;

Image

  • en [1-3], la table [users] qui liste les utilisateurs autorisés à utiliser l’application [NestJS] ;
    • [id, version] : clé primaire, numéro de version ;
    • [login, password] : identifiants de l’utilisateur ;
    • [nom] : nom donné à l’utilisateur ;
    • [role] : son rôle. [ADMIN] a tous les droits. [USER] n’a que des droits de lecture. Il pourra consulter l’agenda d’un médecin mais pas prendre / annuler un rendez-vous ;

3.4. Lancement du serveur [NestJS]

Lancez tous les services de Laragon [Start All], si ce n’est déjà fait. Puis démarrez le serveur NestJS dans un terminal VSCode du projet NestJS :

npm install
npm run start:dev

La console affiche, dans l’ordre : le démarrage du module [NestJS], la liste des routes exposées par le contrôleur, puis la confirmation du démarrage :

[Nest] RoutesResolver AuthController {/}:
[Nest] RouterExplorer Mapped {/login, POST} route
[Nest] RoutesResolver RdvMedecinsController {/}:
[Nest] RouterExplorer Mapped {/getAllMedecins, GET} route
[Nest] RouterExplorer Mapped {/getAllClients, GET} route
[Nest] RouterExplorer Mapped {/getAllCreneaux/:idMedecin, GET} route
[Nest] RouterExplorer Mapped {/getRvMedecinJour/:idMedecin/:jour, GET} route
[Nest] RouterExplorer Mapped {/getAgendaMedecinJour/:idMedecin/:jour, GET} route
[Nest] RouterExplorer Mapped {/getMedecinById/:id, GET} route
[Nest] RouterExplorer Mapped {/getClientById/:id, GET} route
[Nest] RouterExplorer Mapped {/getCreneauById/:id, GET} route
[Nest] RouterExplorer Mapped {/getRvById/:id, GET} route
[Nest] RouterExplorer Mapped {/ajouterRv, POST} route
[Nest] RouterExplorer Mapped {/supprimerRv, POST} route
[Nest] NestApplication Nest application successfully started
[RdvMedecins] serveur NestJS démarré sur http://localhost:8080

Ce relevé de console confirme que le serveur écoute bien sur le port 8080 - exactement le même port que le serveur Spring Boot du document original, choisi volontairement pour cette raison.

Ces routes constituent l’API JSON que le client [Kotlin] consommera au chapitre 4. [POST /login] est la seule route publique : elle renvoie un jeton JWT que toutes les autres routes exigent dans l’entête [Authorization: Bearer <jeton>]. Les routes de consultation ([GET …]) sont accessibles aux rôles ADMIN et USER ; les deux routes qui modifient des données, [POST /ajouterRv] et [POST /supprimerRv], sont réservées au rôle ADMIN. Les réponses métier sont enveloppées dans un objet [{ status, data }] où [status] vaut 0 en cas de succès.

3.5. Tester le serveur avec un navigateur

Depuis l’ajout de l’authentification, toutes les routes de [RdvMedecinsController] exigent un jeton JWT valide : un navigateur, seul, ne permet donc plus de les tester directement. Par exemple :

http://localhost:8080/getAllMedecins

renvoie désormais, sans jeton, une erreur 401 Unauthorized :

Image

C’est le comportement attendu : cette réponse confirme que le serveur protège bien ses routes. Postman (section suivante) est nécessaire pour obtenir un jeton, puis pour l’utiliser.

3.6. Tester le serveur [NestJS] avec Postman

L’outil Postman est disponible à l’URL [https://www.postman.com/downloads/]. Vous aurez peut-être à créer un compte.

Lancez tous les services de Laragon, puis ouvrez l’application de bureau Postman :

  • En [1-2], créez une requête HTTP pour interroger le serveur de gestion des rendez-vous des médecins ;

3.6.1. Se connecter et obtenir un jeton

  1. créer une nouvelle requête Postman, méthode POST, URL http://localhost:8080/login ;
  1. dans l’onglet [Body], choisir raw puis le format JSON, et saisir : {"login": "admin", "password": "admin"} (ou user/user pour tester le rôle USER) ;
  2. envoyer la requête.

Image

  • en [1-2], la requête POST au serveur [NestJS] qui oeuvre sur le port 8080 ;
  • en [3-5], le corps de la requête. Celle-ci transmet au serveur la chaîne JSON des identifiants de l’utilisateur qui veut se connecter, ici admin/admin ;
  • en [6], la réponse du serveur ;
  • en [7], le jeton d’authentification que les requêtes ultérieures doivent envoyer au serveur pour dire “je me suis déjà authentifié” ;

Copiez la valeur de accessToken : c’est ce jeton qu’il faut désormais présenter à chaque requête suivante. Ci-dessus le jeton à copier est “eyJ...zoM” (sans les “).

3.6.2. Appeler une route protégée avec le jeton

Pour GET /getAllMedecins (ou toute autre route de RdvMedecinsController), ajouter dans Postman, onglet Authorization, le type Bearer Token, et coller le jeton copié ci-dessus (Postman ajoute alors lui-même l’entête Authorization: Bearer <jeton>).

Image

  • en [1-2], la requête envoyée au serveur. Elle demande la liste des médecins en base de données ;
  • en [3-5], la requête doit envoyer le jeton d’authentification. En [4], choisissez [Bearer Token] et en [5] collez le jeton d’authentification que vous avez copié précédemment ;
  • en [7], la réponse du serveur ;

3.6.3. Tester les routes POST (/ajouterRv, /supprimerRv)

Même démarche que ci-dessus (méthode POST, corps JSON, jeton en Bearer Token), exactement comme le document original utilisait le complément Chrome « Advanced Rest [Client] » pour les mêmes routes.

Note : vous pouvez retrouver les requêtes Postman qui suivent dans la collection [rdvmedecins-nestJS.postman_collection.json] :

Image

Dans Postman, faire Ctrl-0 pour charger la collection :

Image

  • cliquez sur [1] pour charger la collection et sélectionnez le fichier de la collection. Une fois chargée la collection, celle-ci expose ses requêtes :

Image

Pour tester /ajouterRv avec le jeton d’un compte ADMIN :

  1. requête Postman, méthode POST, URL http://localhost:8080/ajouterRv ;
  2. onglet Authorization : Bearer Token, jeton de admin ;
  3. onglet [Body], raw, JSON : {"jour": "2026-09-13", "idClient": 1, "idCreneau": 5} ;
  4. envoyer la requête.

Image

  • en [3-5], le corps de la requête ;

Image

Vous pouvez vérifier avec HeidiSQL qu’un rendez-vous a été ajouté en base :

Image

Pour tester /supprimerRv, la même démarche s’applique avec le corps {"idRv": 2} (l’identifiant du rendez-vous à annuler (8) ci-dessus).

Image

  • en [4], ci-dessus le numéro du rendez-vous à supprimer ;

Image

  • en [5-7], le jeton d’authentification ;
  • en [9], la réponse du serveur. [status=0] signifie que l’opération s’est bien déroulée. Vous pouvez le vérifier avec HeidiSQL :

Image

  • en [3], le rendez-vous n° 2 n’existe plus ;

À essayer : refaire cette même requête /ajouterRv avec le jeton du compte USER (user/user) plutôt que celui de admin : la réponse devient 403 Forbidden, avec le message le rôle [USER] ne permet pas cette action (rôle requis : ADMIN) - la démonstration concrète du contrôle d’accès par rôle mis en place par le serveur.

3.7. Lancer le client Kotlin pour la première fois

Le serveur [NestJS] étant démarré, ouvrir le projet [rdvmedecins-kotlin-client] dans Android Studio (cf. chapitre 1) et démarrer l’émulateur. Dans la barre d’outils d’Android Studio, la liste déroulante des appareils doit afficher l’émulateur (par exemple [Pixel 8 API 37]) ; le bouton [Run] (le triangle vert), à côté, compile l’application, l’installe dans l’émulateur et la lance.

Sans Android Studio, les mêmes étapes s’écrivent en ligne de commande : la tâche Gradle [installDebug] compile et installe l’application, puis [adb] la lance :

1
2
3
$env:JAVA_HOME = "C:\Program Files\Android\Android Studio\jbr"
.\gradlew.bat installDebug
adb shell am start -n fr.rdvmedecins.client/.MainActivity
  • [installDebug] : construit l’application (comme [assembleDebug], cf. chapitre 1), puis l’installe sur l’appareil connecté - émulateur ou téléphone ;
  • [adb shell am start -n <application>/<activité>] : demande au gestionnaire d’activités d’Android ([am], Activity Manager) de lancer l’activité [MainActivity] de l’application [fr.rdvmedecins.client] - ce que fait le système quand on touche l’icône de l’application.

Image

L’écran de connexion s’affiche en premier, comme pour les clients précédents de ce cours : deux comptes de démonstration sont fournis avec la base de données du serveur, [admin]/[admin] (rôle [ADMIN], accès complet) et [user]/[user] (rôle [USER], lecture seule). Les boutons « FR »/« EN », en haut à droite, basculent l’interface en anglais, y compris avant toute connexion.

Le champ « URL du serveur » contient par défaut [http://10.0.2.2:8080] : dans l’émulateur, l’adresse spéciale [10.0.2.2] désigne l’ordinateur qui exécute l’émulateur, donc le serveur [NestJS]. Si la connexion échoue après une dizaine de secondes (message « Login ou mot de passe incorrect. »), c’est le plus souvent que cette adresse ne répond pas : c’est arrivé sur le poste qui a servi à écrire ce document. La solution est décrite au chapitre 5 : la commande [adb reverse tcp:8080 tcp:8080], puis l’URL [http://localhost:8080].