API REST de gestion de données et de services liée au campus.
camp-api fournit un point d’entrée central pour enregistrer, consulter et exploiter les informations nécessaires. Le projet est développé avec NestJS et TypeScript.
ou
Lien Youtube Youtube rend la qualité très mauvaise désolé
- vérification de l’état du service;
- gestion des emplacements et ces appréciations;
- gestion d'erreurs globale;
- persistance de données;
- réponses HTTP au format JSON;
- architecture modulaire par domaine;
- contrôles de qualité avec ESLint et Prettier.
- Node.js;
- TypeScript;
- NestJS;
- Jest;
- Supertest;
- ESLint;
- Prettier;
- MongoDB;
- Permit.io.
- une version de Node.js compatible avec le fichier
package.json; - npm;
- Git;
Vérifier l’environnement local :
node --version
npm --version
git --versionCloner le dépôt :
git clone <URL_DU_DEPOT>
cd camp-apiInstaller les dépendances :
npm install
npm ls # vérifier l'installation des dépendancesL’application attend la variable d’environnement suivante dans le fichier .env.<NODE_ENV>.
| Variable | Obligatoire | Description | Exemple local |
|---|---|---|---|
JWT_SECRET |
Oui | Authentification avec JWT | "<hash>" |
MONGO_URI |
Oui | Cluster d'une base de données MongoDB | "mongodb+srv://<username>:<password>@<cluster>/?<dbName>" |
NODE_ENV |
Oui | Fichier .env à utiliser |
"development" |
PERMIT_IO_TOKEN |
Oui | Autorisation avec RBAC | "permit_key_<hash>" |
PORT |
Non | Port d’écoute du serveur HTTP | 3000 |
node -e "console.log(require('crypto').randomBytes64 ? '' : require('crypto').randomBytes(64).toString('hex'))"ou
openssl rand -hex 64- Créer un compte (ou se connecter) sur MongoDB Atlas.
- Créer un projet, puis un cluster (l'offre gratuite M0 suffit).
- Dans Database Access, cliquer sur Add New Database User :
- choisir l'authentification par mot de passe ;
- saisir un nom d'utilisateur et un mot de passe (ou utiliser Autogenerate Secure Password) ;
- donner le rôle Read and write to any database ;
- NOTER LE MOT DE PASSE, il ne sera plus affiché ensuite.
- Dans Network Access, cliquer sur Add IP Address et ajouter votre adresse IP actuelle (Add Current IP Address).
- Dans Database, cliquer sur Connect sur votre cluster, puis Drivers, et copier la chaîne de connexion.
- Coller cette chaîne de connexion dans la variable
MONGO_URIdu fichier.envde votre choix.
ou me contacter et indiquer l'adresse IP privée de votre machine:
2233405@cegepmv.ca
Suivre le guide complet de Permit.io: https://www.permit.io/blog/how-to-protect-a-url-inside-a-nestjs-app-using-rbac-authorization
ou me contacter:
2233405@cegepmv.ca
cp .env.example .env.development
# remplacer les informations entourées de '<...>' et changer les autres variables au besoinnpm run start: devnpm run build
npm run start: prodAvec PORT=3000 (port par défaut), l’API est accessible à l’adresse suivante :
http://localhost:3000/api/v1
Toutes les routes sont exposées sous le préfixe global /api/v1.
Consulter la collection Postman pour une liste technique de toutes les routes.
| Méthode | Route | Statut attendu | Description |
|---|---|---|---|
GET |
/api/v1/health |
200 OK |
Vérifie l’état du service |
| Méthode | Route | Statut attendu | Description |
|---|---|---|---|
POST |
/api/v1/auth/login |
201 Created |
S'authentifier pour accéder au service |
POST |
/api/v1/auth/signin |
200 OK |
Créer un utilisateur pour s'authentifier |
| Méthode | Route | Statut attendu | Description |
|---|---|---|---|
GET |
/api/v1/locations |
200 OK |
Retourne les emplacements |
GET |
/api/v1/locations/{id} |
200 OK |
Retourne un emplacement |
POST |
/api/v1/locations |
201 Created |
Crée un emplacement |
PATCH |
/api/v1/locations/{id} |
200 OK |
Modifie un emplacement |
DELETE |
/api/v1/locations/{id} |
204 No Content |
Supprime un emplacement |
| Méthode | Route | Statut attendu | Description |
|---|---|---|---|
GET |
/api/v1/ratings |
200 OK |
Retourne les appréciations |
GET |
/api/v1/ratings/{id} |
200 OK |
Retourne une appréciation |
POST |
/api/v1/ratings |
201 Created |
Crée une appréciation |
PATCH |
/api/v1/ratings/{id} |
200 OK |
Modifie une appréciation |
DELETE |
/api/v1/ratings/{id} |
204 No Content |
Supprime une appréciation |
curl -i -X GET http://localhost:3000/api/v1/healthRéponse attendue :
CampusRate API is up and running 🚀curl -i -X GET http://localhost:3000/api/v1/locationscurl -i -X POST http://localhost:3000/api/v1/locations \
-H "Content-Type: application/json; charset=utf-8" \
--data-binary @- <<'EOF'
{
"name": "Bibliothèque Centrale",
"description": "Espace de travail calme avec postes informatiques et salles de réunion.",
"category": "STUDY_SPACE",
"address": "1234, rue de l'Université, Montréal, QC",
"services": ["Wi-Fi", "Impression", "Salles d'étude"],
"status": "ACTIVE"
}
EOF$body = @'
{
"name": "Bibliothèque Centrale",
"description": "Espace de travail calme avec postes informatiques et salles de réunion.",
"category": "STUDY_SPACE",
"address": "1234, rue de l'Université, Montréal, QC",
"services": ["Wi-Fi", "Impression", "Salles d'étude"],
"status": "ACTIVE"
}
'@
Invoke-WebRequest -Method Post `
-Uri "http://localhost:3000/api/v1/locations" `
-ContentType "application/json; charset=utf-8" `
-Body ([System.Text.Encoding]::UTF8.GetBytes($body))- Sauvegarder le JSON ci-dessous comme
location.json(encodé avec UTF-8):
{
"name": "Bibliothèque Centrale",
"description": "Espace de travail calme avec postes informatiques et salles de réunion.",
"category": "STUDY_SPACE",
"address": "1234, rue de l'Université, Montréal, QC",
"services": ["Wi-Fi", "Impression", "Salles d'étude"],
"status": "ACTIVE"
}- Exécuter la requête:
curl -i -X POST http://localhost:3000/api/v1/locations ^
-H "Content-Type: application/json; charset=utf-8" ^
--data-binary @location.json| Attribut | Règle |
|---|---|
| services | [0 à 10 éléments de chaîne de caractères] |
| status | "ACTIVE", "TEMPORARILY_CLOSED" ou "CLOSED" |
Les données sont stockées dans un cluster MongoDB (Atlas), à cause de ses caractéristiques suivantes:
- Format JSON natif : les emplacements et appréciations sont des documents JSON, ce qui s'intègre directement avec NestJS et TypeScript;
- Schéma flexible : de nouveaux champs peuvent être ajoutés sans migration pendant le développement actif;
- Persistance : les données survivent aux redémarrages et aux redéploiements;
- Aucune installation locale : seule la variable
MONGO_URIest nécessaire.
À implémenter dans le futur
Uniquement les requêtes ayant l'IP privée de la machine sur laquelle tourne CampusRate ET qui sont incluses dans les listes d'IP autorisées par le cluster MongoDB peuvent effectuer des requêtes vers l'API. Toute autre source sera rejetée comme ceci:
{
"type": "locations",
"title": "Internal Server Error",
"status": 500,
"detail": "An unexpected error occurred",
"instance": "/api/v1/locations"
}- Pull Request: #37
- Commit: https://github.com/KevinEJean/camp_api/pull/37/changes/55359bbf42c00cd67266c78e516b34449473baa3
Les constantes _id et placeId ne sont pas modifiables parce que:
- modifier une constante risque de briser l'indexation de MongoDB et est généralement une mauvaise pratique;
- ils sont auto-générés par le serveur, donc pas besoin de les modifier.
| Variables | Modifiable | Raisonnement |
|---|---|---|
| name | Oui | Il est possible qu'elle soit mal écrite lors de sa création. |
| description | Oui | Donner la possibilité d'ajouter ou de retirer des détails sur les emplacements. |
| category | Non | Un emplacement ne change jamais de catégorie / fonctionnalité. |
| address | Oui | Il est moins probable qu'une adresse change, cependant, il est possible qu'elle soit mal écrite lors de sa création. |
| services | Oui | Il se peut qu'il ajoute des services après la construction. |
| status | Oui | Il est très probable qu'il devienne fermé en raison de la construction. |
| Variables | Modifiable | Raisonnement |
|---|---|---|
| authorName | Non | Afin de faciliter la modération et limiter les privilèges clients. |
| rating | Oui | Donner la chance d'ajuster le score. |
| comment | Oui | Il se peut qu'une revue soit erronée ou que l'auteur désire ajuster son commentaire. |
- Pull Request: #62
- Commit: https://github.com/KevinEJean/camp_api/pull/62/changes/03d1de2fd0e4e15daeec5830c2115c62268452cc
Chaque fois que le serveur reçoit une requête, elle est documentée et stockée dans un fichier log (logs/allRequests.log). Pour faciliter l'analyse du trafic, la modération, le support et la maintenance de l'API, des informations sont affichées dans le terminal.
Exemple de log (dans le terminal):
[Nest] 25688 - 10/12/2026, 7:04:54 PM LOG [RequestLoggerMiddleware] GET /api/v1/locations
[Nest] 25688 - 10/12/2026, 7:04:54 PM LOG [ExecutionTimeInterceptor] GET /api/v1/locations - 75 msDans le fichier log/allRequests.log:
{"level": "info", "message": "GET /api/v1/locations", "timestamp": "2026-10-12T23:04:54.795Z"}- Pull Request: #35
- Commit: https://github.com/KevinEJean/camp_api/pull/35/changes#diff-4fab5baaca5c14d2de62d8d2fceef376ddddcc8e9509d86cfa5643f51b89ce3d
Seules les requêtes valides étaient documentées par les loggers (winston, interceptor, middleware). Désormais, si une requête invalide est reçue ou envoyée (réponse du serveur), elle est affichée dans le terminal pour faciliter la maintenance et le support.
Exemple de log (dans le terminal):
{
"level": "warn",
"message": "Cannot GET /api/v1/locationss",
"method": "GET",
"path": "/v1/locationss",
"possibleSolution": "The requested resource was not found. Verify the ID, URL or Method is correct and that the resource has not been deleted.",
"statusCode": 404,
"timestamp": "2026-10-12T23:12:14.660Z"
}- Pull Request: #57
- Commit: https://github.com/KevinEJean/camp_api/pull/57/changes/e3b836c8921193b16d041a751ca351e035e13ed2
L'API protège ses routes avec un jeton JWT envoyé dans l'en-tête Authorization selon le schéma Bearer. Par défaut, toutes les routes exigent un jeton valide, sauf celles marquées @Public() (actuellement POST api/v1/auth/signin, POST api/v1/auth/login et GET api/v1/health). Cette fonctionnalité est combinée avec l’Autorisation RBAC (A2). D'abord, le serveur vérifie que la requête contient un jeton valide (signature correcte et jeton non expiré), puis il vérifie que l'utilisateur a la permission d'effectuer l'action demandée.
- Créer un utilisateur
(POST /api/v1/auth/signin); - S'authentifier
(POST /api/v1/auth/login);
- un
tokensera retourné en réponse, insérer celui-ci dans Authorization (icône verte):
Authorization: Bearer <access_token>
- Exécuter des requêtes et tester les règles d'autorisation de
RBAC.
Il n'est pas possible de tester d'autres privilèges à ce moment. Cela est mentionné dans la courte vidéo.
- Pull Request: #65
- Commit: https://github.com/KevinEJean/camp_api/pull/65/changes/aaed0a1b8ab0d88bc726a72ebf50781e083703b7
Pas besoin d'autorisation pour lire tous les emplacements et appréciations (GET api/v1/locations et api/v1/ratings). Présentement, les clients (rôle : USER) n'ont pas le droit de modifier ou de supprimer leurs revues, parce qu'il n'y a pas encore de moyen d'associer une appréciation à un usager. Il s'agit d'une fonctionnalité qui devrait être implémentée dans le futur. Aussi, pour préserver l'intégrité de l'API, il est impossible de créer un utilisateur ayant des droits autres que USER.
| Action | Autorisation ADMIN |
Autorisation PARTNER |
Autorisation USER |
|---|---|---|---|
| Lire un emplacement par id | Oui | Oui | Oui |
| Créer un emplacement | Oui | Oui | Non |
| Modifier un emplacement | Oui | Non | Non |
| Supprimer un emplacement | Oui | Non | Non |
| Lire une appréciation par id | Oui | Oui | Oui |
| Créer une appréciation | Oui | Non | Oui |
| Modifier une appréciation | Oui | Non | Non |
| Supprimer une appréciation | Oui | Non | Non |
| Lire un utilisateur par id | Oui | Non | Non |
| Créer un utilisateur | Oui | Non | Non |
| Modifier un utilisateur | Oui | Non | Non |
| Supprimer un utilisateur | Oui | Non | Non |
- Pull Request: #63
- Commit: https://github.com/KevinEJean/camp_api/pull/63/changes/e4d2c7d1ad0cbb07b7336fc520c9ba3054967995
À implémenter dans le futur
À implémenter dans le futur
À implémenter dans le futur
À implémenter dans le futur
src/
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── main.ts
├── permit.module.ts
├── auth/
│ ├── auth.controller.ts
│ ├── auth.module.ts
│ ├── auth.service.ts
│ ├── dto/
│ │ ├── login.dto.ts
│ │ ├── signin.dto.ts
│ └── guard/
│ ├── jwt-auth.guard.ts
│ └── permission.guard.ts
├── configs/
│ ├── configure-swagger.ts
│ ├── configure-winston.ts
│ └── database.config.ts
├── exceptions/
│ ├── exceptions.dto.ts
│ ├── filters/
│ │ ├── http-exception.filter.ts
│ │ └── internal-exception.filter.ts
│ ├── interceptors/
│ │ └── execution-time.interceptor.ts
│ ├── middleware/
│ │ └── request-logger.middleware.ts
│ └── solutions/
│ ├── solutions-logger.ts
│ └── solutions-payload.ts
├── health/
│ ├── health.controller.ts
│ └── health.module.ts
├── locations/
│ ├── locations.controller.ts
│ ├── locations.module.ts
│ ├── locations.repository.ts
│ ├── locations.service.ts
│ ├── dto/
│ │ ├── create-locations.dto.ts
│ │ ├── response-locations.dto.ts
│ │ └── update-locations.dto.ts
│ ├── entities/
│ │ └── locations.entity.ts
│ ├── enums/
│ │ ├── category.enum.ts
│ │ └── status.enum.ts
│ └── schemas/
│ └── locations.schema.ts
├── ratings/
│ ├── ratings.controller.ts
│ ├── ratings.module.ts
│ ├── ratings.repository.ts
│ ├── ratings.service.ts
│ ├── dto/
│ │ ├── create-ratings.dto.ts
│ │ ├── response-ratings.dto.ts
│ │ └── update-ratings.dto.ts
│ ├── entities/
│ │ └── ratings.entity.ts
│ └── schemas/
│ └── ratings.schema.ts
├── users/
│ ├── users.controller.ts
│ ├── users.module.ts
│ ├── users.repository.ts
│ ├── users.service.ts
│ ├── dto/
│ │ ├── create-users.dto.ts
│ │ └── response-users.dto.ts
│ ├── entities/
│ │ └── users.entity.ts
│ └── schemas/
│ └── users.schema.ts
└── utils/
└── utils.ts
Le projet suit une organisation par fonctionnalité :
- les modules regroupent les composants d’un domaine;
- les contrôleurs gèrent les échanges HTTP;
- les services portent la logique applicative;
- les DTO définissent la forme des données échangées;
| Commande | Description |
|---|---|
npm run start |
Démarre l’application |
npm run start:dev |
Démarre l’application en mode surveillance |
npm run build |
Compile l’application |
npm run lint |
Analyse et corrige le code selon les règles configurées |
npm run test |
Exécute les tests unitaires |
npm run test:e2e |
Exécute les tests de bout en bout |
npm run test:cov |
Produit le rapport de couverture des tests |
Pour signaler une vulnérabilité, utiliser le mécanisme de signalement privé du dépôt plutôt qu’une issue publique.
Consulter le fichier LICENSE à la racine du dépôt pour connaître les conditions d’utilisation et de redistribution.