---
# System prepended metadata

title: 1. Backend (Fastify + MongoDB)

---

<h1 style="text-align: center">
Gestion de QCM en ligne sécurisé
</h1>

> Groupe 2 : Hugo B, Déogracia D, Quentin E, Quentin L, Louis P



# 1. Backend (Fastify + MongoDB)

## 1.1. Base de données (`db/`)

Pour la base de données nous nous sommes orientés vers MongoDB qui permet d'échanger aisément les données entre l'API et le frontend directement sous forme JSON en supprimant toutes conversions de format.
Dans l'API, la base de données est déclarée globalement grâce au plugin `fastify-mongodb` puis la base de donnée est accédée via `fastify.mongo.db`.

Nous avons deux collections, `users` et `exams`, ces collections sont construites de la façon suivante : 

**users**
```js
{
   _id: mongodb.ObjectId,
   firstName: String,
   lastName: String,
   email: String, // index: unique
   role: String, // "student", "professor", "admin"
   password: String,
   extraTime: 20, // Percentage
}
```

<p style="page-break-after: always;">&nbsp;</p>

**exams**
```js
{
  _id: mongodb.ObjectId,
  ownerId: mongodb.ObjectId,
  title: String,
  startDate: String, // Date ISO
  duration: Integer, // Minutes
  maxTimeAway: Integer, // Seconds
  questions: [
    {
      id_question: mongodb.ObjectId,
      question: String,
      availableAnswers: ["list", "of", "answers"],
      correctAnswers: ["list", "of", "correct", "answers"],
      studentAnswers: {
        studentID: ["list", "of", "student", "answers"]
      }
    }
  ],
  studentTimeAway: {
    studentID: Integer // Seconds
  }
}
```

La base de données est dockerisée et est accompagnée d'un fichier `init.js` dans lequel on a défini un index sur les emails afin d'empêcher l'utilisation d'une même adresse sur plusieurs comptes utilisateurs. Dans ce même fichier un premier compte utilisateur est créé, c'est l'administrateur par défaut, si on souhaite créer d'autres compte lors du déploiement de l'API, il suffira simplement de les ajouter dans ce fichier sur le même modèle que celui déjà présent.


## 1.2. API (`back/`)

L'API est développé en JavaScript via le framework Fastify pour Node.JS, nous avons choisit ce framework car il présente de bonnes performances et dispose d'un bon nombre de plugins officiellement maintenus nous permettant de vérifier le corps d'une requête et de générer une documentation interactive assez facilement.

L'API communique en JSON et ses retours suivent le format suivant :

```js
{
	/* 'message' est toujours présent */
	message: "Si la réponse est OK ou sinon une erreur"
	/*
	objet contenant les éventuelles données retournées,
	présent uniquement si on retourne des données
	*/
	data: {

	}
}
```


### 1.2.1. Pre-handlers

Les pre-handlers sont des fonctions exécutées avant la fonction d'une route et permettent d'effectuer un pré-traitement ou de bloquer l'accès à une route.

Dans notre cas nous avons deux fonctions situés dans le fichier `back/utils/middlewares.js` :
- `checkJWT`: cette fonction nous permet de vérifier le jeton JWT présente dans les headers de la requêtes pour les routes nécessitant une authentification, si la signature du jeton est valide, alors celui-ci n'a pas été altéré et son contenu est placé dans `req.jwt` nous permettant d'y accéder dans la fonction qui suit et l'accès est autorisé, si le jeton n'est pas présent ou que sa signature est erronée alors on retourne une erreur.
- `checkRights`: cette fonction nous permet de vérifier le rôle d'un utilisateur, certains routes sont restreintes à certains rôles, quand c'est le cas on appelle `checkRights` après avoir vérifié le jeton JWT, pour simplifier le code cette fonction n'est pas appelée directement mais via les alias pré-remplis `checkProfessorRights`, `checkAdminRights`


### 1.2.2. Validation

Une des fonctionnalités inclues dans Fastify est la validation, la validation permet de vérifier le contenu d'un requête avant d'exécuter la fonction y étant liée, si un champ est manquant l'API retourne une erreur, par exemple si on essaie d'oublier l'email pour la route `/register` on obtient le message suivant : `body should have required property 'email'`, en plus de supporter l'existence d'un champ on vérifie aussi le type de la valeur (`string`, `number`, etc.) ou son format (`email`, etc.).

<p style="page-break-after: always;">&nbsp;</p>

### 1.2.3. Documentation

Liée à la validation car Fastify lie intelligemment les deux, la documentation est spécifiée via l'objet `schema`, à partir de ces informations le plugin `fastify-swagger` va générer une documentation interactive basée sur la spécification OpenApi (anciennement Swagger) et la rendre disponible sur la route `/documentation`. Cette documentation en plus d'être complète et agréable à lire permet via son interface web de tester les routes soi-même à partir d'exemples modifiables.

Cette documentation étant présente sur chacune des routes, elle fait aussi office de remplacement pour les traditionnels commentaires.


### 1.2.4. Tests

Pour réaliser les tests, nous avons utilisé le populaire framework de tests `jest`, les tests sont présents dans le dossier `back/tests`. La base de données utilisée pour les tests est une base de donnée mongodb en mémoire : `mongodb-memory-server`.

Chaque route a été testée et on peux lancer les tests avec les commandes :
- Depuis le dossier de développement `back/` : `npm run test`, en supposant que les dépendances ont étés installés via `npm install`.
- Directement sur le docker : `docker exec g2API /bin/sh -c "cd /usr/src/app && npm install --also=dev && npm run test"`, dans ce cas les dépendances de développement seront ajoutés au Docker.


# 2. Frontend (Vue Js + Vuetify)

Pour réaliser l'interface utilisateur (UI), nous avons utilisé Vue JS en version 2.6, couplé à la librairie Vuetify. Cette dernière nous a permis de gérer la responsivité du site tout en nous fournissant des composants prêt à l'emploi (formulaire, carte, barre de navigation), nous facilitant grandement la tâche pour l'ergonomie de l'application.

### 2.1 Les routes
Les routes nous permettent de naviguer depuis l'interface utilisateur. Voici les routes que nous avons implémenté :
```js
const routes = [{
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/exams',
    name: 'Exams',
    component: Exams
  },
  {
    path: '/exam/:exam_id',
    name: 'Exam',
    component: TakeExam
  },
  {
    path: '/exam/questions/:exam_id',
    name: 'Questions',
    component: Questions
  },
  {
    path: '/admin',
    name: 'Admin',
    component: Admin
  }
]
```
### 2.2 Les composants et vues
Il s'agit du fonctionnement de Vue JS. L'utilisateur affiche sur son navigateur des vues dans lesquelles se trouvent un ou plusieurs composants. Cela rend le framework très modulable et facile d'utilisation.

```
APP
├── components
│   ├── AdminBoard.vue
│   ├── Auth.vue
│   ├── Exams
│   ├── Footer.vue
│   └── NavBar
└── views
    ├── Admin.vue
    ├── Exams.vue
    ├── Home.vue
    └── NavBar.vue
```


### 2.3 Les services
Contrairement aux vues et composants qui se chargent d'afficher les données, les services permettent de déléguer l'accès aux données.
Ce sont eux qui permettent au frontend de requêter l'api (ici Fastify)
```
├── AdminService.js
├── AnswersService.js
├── AuthService.js
├── ExamsService.js
└── QuestionsService.js
```

# 4. Conteneurisation (Docker)
Dans le cadre de notre travail nous avons choisi de mettre l'application sous docker afin de faciliter son déploiement auprès du client et gérer les dépendances liées à l'application peu importe le langage utilisé.
Pour démarrer docker il faut se mettre à la racine du projet et taper la commande suivante: 
`docker-compose up --build`

> NB: il se peut qu'une erreur survienne, veillez à ce que le port 8000 soit disponible, le cas échéant arrêtez le vpn de l'école pour libérer la plage d'adresse.
> 
>  Pour libérer le port tapez la commande suivante: **sudo netstat -ap | grep :8000,** 
>  ensuite **sudo kill -9 "Numéro de l'ID"** écoutant sur ce port (Numéro à droite du terminal suivi d'un /) **ex: sudo kill -9 30749**
> 

<p style="page-break-after: always;">&nbsp;</p>

# 5. Architecture de l'application

![](https://i.imgur.com/bZyIGQm.png)


# 6. Architecture FrontEnd

![](https://i.imgur.com/CDJDcfO.png)
