Compare commits

...

5 commits

Author SHA1 Message Date
dd0f5f9534 fix dns issue stress-test 2024-12-09 22:17:27 -05:00
a2d83f4f77 Merge branch 'dev-it3-PFEA2024' into dev-it3-it4-PFEA2024 2024-12-09 21:37:29 -05:00
b97454d9a9 Adds logs back in docker 2024-12-09 21:34:23 -05:00
fserres
75e669b8b4 Add deployment with opentofu 2024-12-09 14:58:48 -05:00
fserres
3ef37f6dc4 Ajout de la doc opentofu 2024-12-09 12:55:13 -05:00
30 changed files with 872 additions and 86 deletions

9
.gitignore vendored
View file

@ -130,6 +130,15 @@ dist
.pnp.* .pnp.*
db-backup/ db-backup/
.env
.venv .venv
deployments deployments
/test/stressTest/output /test/stressTest/output
# Opentofu state
opentofu/*/.terraform
opentofu/*/.terraform.lock*
opentofu/*/terraform.tfstate*
opentofu/*/terraform.tfvars
# Opentofu auth config
opentofu/auth_config.json

View file

@ -2,17 +2,23 @@
## Introduction ## Introduction
Le but du module d'authentification est de pouvoir facilement faire des blocks de code permettant une authentification personalisée. Il est possible de le faire grâce a cette architecture. Pour la première version de cette fonctionalitée, l'introduction de OICD et de OAuth sont priorisé ainsi que la migration du module d'authentification simple. Le but du module d'authentification est de pouvoir facilement faire des blocs de code permettant une authentification
personalisée. Il est possible de le faire grâce à cette architecture. Pour la première version de cette fonctionalité,
l'introduction de OIDC et de OAuth sont priorisé ainsi que la migration du module d'authentification simple.
## Déconstruction simple de la structure ## Déconstruction simple de la structure
La structure est la suivante : La structure est la suivante :
Le AuthManager s'occupe de centraliser les requetes d'authentifications. Ce qui veux dire d'initialiser les autres modules et d'être la source de véritée dans au sujet de l'authentification. Les modules sont automatiquement chargé par l'utilisation de variables d'environment. Le AuthManager s'occupe de centraliser les requêtes d'authentification. Ce dernier initialise les autres modules et est
la source de vérité dans les aspects liés à l'authentification. Les modules sont automatiquement chargés par
l'utilisation de variables d'environment.
Le module s'occupe de creer les routes nécéssaires pour son fonctionnement et de créer les utilisateurs. Ces modules vont appeller le AuthManager afin de confirmer leurs actions avec le login/register de celui-ci Le module s'occupe de créer les routes nécessaires pour son fonctionnement et de créer les utilisateurs. Ces modules
vont appeller le AuthManager afin de confirmer leurs actions avec le login/register de celui-ci.
Dans le cas de modules plus complexe, tels que le module Passport, la chaine peut être prolongée afin de maintenir centralisée les actions. Chaque connecteur de PassportJs est initialisé par le module de PassportJs. Dans le cas de modules plus complexe, tels que le module Passport, la chaine peut être prolongée afin de maintenir
les actions centralisée . Chaque connecteur de PassportJs est initialisé par le module de PassportJs.
## Besoins exprimés ## Besoins exprimés
@ -20,32 +26,38 @@ Dans le cas de modules plus complexe, tels que le module Passport, la chaine peu
Modularité et généricité : Modularité et généricité :
- Le système d'authentification doit être adaptable à diverses configurations, notamment pour répondre aux exigences spécifiques des différentes universités ou institutions. - Le système d'authentification doit être adaptable à diverses configurations, notamment pour répondre aux exigences
spécifiques des différentes universités ou institutions.
Utilisation de différentes méthodes d'authentification : Utilisation de différentes méthodes d'authentification :
- L'application doit permettre de gérer plusieurs fournisseurs d'authentification (SSO, LDAP, OAuth, etc.) de manière centralisée et flexible. - L'application doit permettre de gérer plusieurs fournisseurs d'authentification (SSO, LDAP, OAuth, etc.) de manière
centralisée et flexible.
Facilité de configuration : Facilité de configuration :
- Le système doit permettre une configuration simple et flexible, adaptée à différents environnements (développement, production, etc.). - Le système doit permettre une configuration simple et flexible, adaptée à différents environnements (développement,
production, etc.).
Gestion des permissions : Gestion des permissions :
- Il doit être possible de définir et de mapper facilement les permissions et les rôles des utilisateurs pour sécuriser laccès aux différentes fonctionnalités de lapplication. - Il doit être possible de définir et de mapper facilement les permissions et les rôles des utilisateurs pour sécuriser
laccès aux différentes fonctionnalités de lapplication.
Maintien de la connexion : Maintien de la connexion :
- Le système doit garantir la persistance de la connexion pendant toute la durée de l'utilisation de l'application (exemple : quiz), avec la possibilité de se reconnecter sans perte de données en cas de déconnexion temporaire. - Le système doit garantir la persistance de la connexion pendant toute la durée de l'utilisation de l'application
(exemple : quiz), avec la possibilité de se reconnecter sans perte de données en cas de déconnexion temporaire.
## Recis utilisateurs pris en comptes ## Recits utilisateurs pris en comptes
- En tant qu'utilisateur de projet FOSS, je veux que le module d'authentifcation soit modulaire et générique afin de l'adapter a mes besoins. - En tant qu'utilisateur de projet FOSS, je veux que le module d'authentification soit modulaire et générique afin de
l'adapter à mes besoins.
- En tant qu'administrateur, je veux que les droits des utilisateurs soient inférés par l'authentificateur de l'établissement. - En tant qu'administrateur, je veux que les droits des utilisateurs soient inférés par l'authentificateur de l'établissement.
- En tant qu'administrateur, je veux que la configuration des authentificateur soit simple - En tant qu'administrateur, je veux que la configuration des authentificateurs soit simple
- En tant qu'administrateur, je veux configurer les connections a partir de variables d'env ou fichier de config. - En tant qu'administrateur, je veux configurer les connexions à partir de variables d'environnement ou fichier de config.
- En tant qu'utilisateur, je veux que ma connexion soit stable. - En tant qu'utilisateur, je veux que ma connexion soit stable.
- En tant qu'utilisateur, je veux pouvoir me reconnecter a une salle s'il y arrive un problème de connexion. - En tant qu'utilisateur, je veux pouvoir me reconnecter à une salle s'il survient un problème de connexion.
## Diagrammes ## Diagrammes
@ -349,7 +361,7 @@ Example de configuration du fichier : `server/auth_config.json` :
"OAUTH_USERINFO_URL": "https://auth.gmatte.xyz/application/o/userinfo/", "OAUTH_USERINFO_URL": "https://auth.gmatte.xyz/application/o/userinfo/",
"OAUTH_CLIENT_ID": "--redacted--", "OAUTH_CLIENT_ID": "--redacted--",
"OAUTH_CLIENT_SECRET": "--Redacted--", "OAUTH_CLIENT_SECRET": "--Redacted--",
"OAUTH_ADD_SCOPE": "groups", // scopes supplémentaire nécéssaire pour le pivot "OAUTH_ADD_SCOPE": "groups", // scopes supplémentaire nécessaire pour le pivot
"OAUTH_ROLE_TEACHER_VALUE": "groups_evaluetonsavoir-prof", // valeur de pivot afin de définir un enseignant "OAUTH_ROLE_TEACHER_VALUE": "groups_evaluetonsavoir-prof", // valeur de pivot afin de définir un enseignant
"OAUTH_ROLE_STUDENT_VALUE": "groups_evaluetonsavoir" // valeur de pivot afin de définir un étudiant "OAUTH_ROLE_STUDENT_VALUE": "groups_evaluetonsavoir" // valeur de pivot afin de définir un étudiant
} }

View file

@ -1,5 +1,5 @@
# Type de base de données # Type de base de données
La base de données est une mongoDB La base de données est une MongoDB.
# Collections disponibles # Collections disponibles
* Files : Ceci est la collection qui contient les différents quiz et leurs questions. * Files : Ceci est la collection qui contient les différents quiz et leurs questions.

View file

@ -10,12 +10,14 @@ alors que les formules entourées de $ s'afficheront sur la même ligne
`.replace(/\$(.*?)\$/g, (_, inner) => katex.renderToString(inner, { displayMode: false }))` `.replace(/\$(.*?)\$/g, (_, inner) => katex.renderToString(inner, { displayMode: false }))`
La configuration du formatage peut être trouvée dans le fichier TextType.ts situé dans le dossier EvalueTonSavoir/client/src/components/GiftTemplate/templates La configuration du formatage peut être trouvée dans le fichier TextType.ts situé dans le dossier
EvalueTonSavoir/client/src/components/GiftTemplate/templates
C'est aussi dans ce fichier que le format markdown est pris en charge. C'est aussi dans ce fichier que le format markdown est pris en charge.
## Éditeur de quiz ## Éditeur de quiz
Pour l'affichage dans l'éditeur de quiz, on peut retrouver la classe TextType être appliquée sur différents éléments du dossier templates, par exemple la classe Numerical.ts. Pour l'affichage dans l'éditeur de quiz, on peut retrouver la classe TextType être appliquée sur différents éléments
du dossier templates, par exemple la classe Numerical.ts.
On peut voir ici que le TextType est appliqué sur le contenu de la question: On peut voir ici que le TextType est appliqué sur le contenu de la question:
```typescript ```typescript
@ -26,14 +28,16 @@ Selon ce qui avait été écrit dans la question, la classe s'occupera de format
## Affichage de questions ## Affichage de questions
Le module React-latex était utilisé pour le formatage des questions durant un quiz, mais cela a apporté le problème de disparité d'affichage entre la création et l'affichage des questions avec des formules mathématiques. Le module React-latex était utilisé pour le formatage des questions durant un quiz, mais cela a apporté un problème
de disparité d'affichage entre la création et l'affichage des questions avec des formules mathématiques.
Les classes affichant les questions durant un quiz peuvent utiliser ce format, mais avec une manipulation de plus. Les classes affichant les questions durant un quiz peuvent utiliser ce format, mais avec une manipulation de plus.
Les variables contenant la question doivent d'abord avoir un type TextFormat pour pouvoir faire appel à la classe qui s'occupe du format sous le module KaTeX. Les variables contenant la question doivent d'abord avoir un type TextFormat pour pouvoir faire appel à la classe qui
Puis, étant sur un environnement React, il faut utiliser la propriété dangerouslySetInnerHTML pour afficher la question correctement. s'occupe du format sous le module KaTeX. Puis, étant sur un environnement React, il faut utiliser la propriété
dangerouslySetInnerHTML pour afficher la question correctement.
`<div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} /> `<div dangerouslySetInnerHTML={{ __html: TextType({text: questionContent}) }} />
` `
Ce type de manipulation peut être utilisé dans d'autre environnement React si on veut éviter d'utiliser React-latex. Ce type de manipulation peut être utilisé dans d'autres environnements React si on veut éviter d'utiliser React-latex.

View file

@ -2,44 +2,51 @@
## Introduction ## Introduction
Les salles de quiz ont été extraites dans leur propre container afin de limiter les dégats liés soit a une surutilisation d'une salle ou une attaque sur le logiciel. Les salles de quiz ont été extraites dans leur propre conteneur afin de limiter les dégâts liés soit à une
surutilisation d'une salle soit à une attaque sur le logiciel.
En éffet, le découplement permet a un quiz de: En effet, le découplement permet a un quiz de:
- Survivre même si le backend est non-fonctionnel - Survivre même si le backend est non-fonctionnel
- Mourir sans entrainer toute l'application avec elle - Mourir sans entrainer toute l'application avec elle
- Créer/Supprimer des salles automatiquement dépendant de la demande - Créer/Supprimer des salles automatiquement dépendant de la demande
Pour éffectuer ceci il faut éffectuer une petite gymnastique. Il y a une route dans l'api servant à gerer les salles. Lorsqu'un utilisateur demande le socket d'une salle : "/api/rooms/{id}/socket", la requette rebondit sur le proxy Nginx. Celui-ci contacte le backend afin d'obtenir l'addresse de l'ordinateur auquel envoyer la requette et redirige le socket vers ce pc. Pour effectuer ceci, il faut faire une petite gymnastique. Il y a une route dans l'api servant à gérer les salles.
Lorsqu'un utilisateur demande le socket d'une salle : "/api/rooms/{id}/socket", la requête rebondit sur le proxy Nginx.
Celui-ci contacte le backend afin d'obtenir l'adresse de l'ordinateur auquel envoyer la requête et redirige le socket
vers cette adresse.
## Déconstruction simple de la structure ## Déconstruction simple de la structure
Un module supplémnetaire a été ajouté à la structure : Rooms. Un module supplémentaire a été ajouté à la structure : Rooms.
L'objet `room` est la définition d'une salle de façon minimaliste, cette définission est aggrandie avec l'information récotlé du "provider". L'objet `room` est la définition d'une salle de façon minimaliste. Cette définition est aggrandie avec l'information
Le `provider` est le système gérant les différentes salles. Dans l'implémentation éffectuée, il s'agit de docker. récoltée du "provider".
Le `provider` est le système gérant les différentes salles. Dans l'implémentation effectuée, il s'agit de docker.
Lorsque l'api des salles est instantié, celui-ci est lié avec un "provider", définissant comment les salles seront créées. Lorsque l'api des salles est instantié, celui-ci est lié avec un "provider", définissant comment les salles seront créées.
L'api des salles permet de les ajouter, les supprimer, et les consulter les salles. L'api des salles permet de les ajouter, les supprimer, et les consulter.
L'api lance deux "jobs": L'api lance deux "jobs":
- Une vérification de l'état de santé des salles. Celle-ci roule tous les 10 secondes et met a jour les salles. - Une vérification de l'état de santé des salles. Celle-ci roule tous les 10 secondes et met a jour les salles.
- Une suppression des salles. Celle-ci roule tous les 30 secondes et supprimme automatiquement les salles ayant la mention de suppression. - Une suppression des salles. Celle-ci roule tous les 30 secondes et supprimme automatiquement les salles ayant la
mention de suppression.
## Besoins exprimés ## Besoins exprimés
Fiabilite : Fiabilite :
- Nous voulons s'assurer qu'il soit possible d'avoir un grand nombre d'élèves présent sans qu'il y ait des problèmes de déconnexions - Nous voulons s'assurer qu'il soit possible d'avoir un grand nombre d'élèves présent sans qu'il y ait des problèmes de
- Nous voulons que le temps de réponse soit bas déconnexions
- Nous voulons que le temps de réponse soit faible
- Nous voulons que le système soit capable de fonctionner de facon indépendante - Nous voulons que le système soit capable de fonctionner de facon indépendante
## Recis utilisateurs pris en comptes ## Recis utilisateurs pris en comptes
- En tant qu'enseignant, je veux que tous mes élèves soient capable de se connecter a la salle de classe rapidement - En tant qu'enseignant, je veux que tout mes élèves soient capable de se connecter à la salle de classe rapidement
- En tant qu'enseignant, je veux que la salle de quiz puisse survivre des pannes liées aux autres modules de l'aplication - En tant qu'enseignant, je veux que la salle de quiz puisse survivre des pannes liées aux autres modules de l'aplication
- En tant qu'administrateur, je veux que les salles soient indépendantes et qui ne touche pas aux performances des autres salles - En tant qu'administrateur, je veux que les salles soient indépendantes et n'impactent pas les performances des autres salles
- En tant qu'administrateur, je veux que les salles puissent être hébergées séparément du projet - En tant qu'administrateur, je veux que les salles puissent être hébergées séparément du projet
## Diagrammes ## Diagrammes
@ -114,7 +121,8 @@ class QuizRoom{
} }
@enduml @enduml
``` ```
Remarque: Les signatures de fonctions semblent un peu partout car il y a des fonctions de classes standard, des appels HTTPS et des appels de sockets dans le même diagramme. Remarque: Les signatures de fonctions semblent un peu partout car il y a des fonctions de classes standard, des appels
HTTPS et des appels de sockets dans le même diagramme.
### Diagramme de séquence démontrant les communications ### Diagramme de séquence démontrant les communications
```plantuml ```plantuml

View file

@ -1,4 +1,4 @@
# Documentation de Déploiement avec Ansible # Documentation de déploiement avec Ansible
Ce guide explique comment utiliser **Ansible** pour déployer facilement le projet **ÉvalueTonSavoir**. Ce guide explique comment utiliser **Ansible** pour déployer facilement le projet **ÉvalueTonSavoir**.
@ -42,14 +42,14 @@ ansible-playbook -i inventory.ini deploy.yml
``` ```
### Structure des fichiers utilisés ### Structure des fichiers utilisés
- **`inventory.ini`** : Définit les cibles du déploiement. Par défaut, il est configuré pour un déploiement local. - **`inventory.ini`** : Défini les cibles du déploiement. Par défaut, il est configuré pour un déploiement local.
- **`deploy.yml`** : Playbook contenant les instructions pour installer, configurer et déployer l'application. - **`deploy.yml`** : Playbook contenant les instructions pour installer, configurer et déployer l'application.
### Étapes effectuées par Ansible ### Étapes effectuées par Ansible
1. **Installation des dépendances** : 1. **Installation des dépendances** :
- Vérifie et installe Docker si nécessaire. - Vérifie et installe Docker si nécessaire.
2. **Démarrage des services** : 2. **Démarrage des services** :
- Télécharge le fichier `docker-compose.yaml` depuis le dépôt. - Télécharge le fichier `docker-compose.yaml` depuis le dépôt Github.
- Lance les services définis avec Docker Compose. - Lance les services définis avec Docker Compose.
3. **Vérification des conteneurs** : 3. **Vérification des conteneurs** :
- Vérifie que les conteneurs sont en cours d'exécution et fonctionnent correctement. - Vérifie que les conteneurs sont en cours d'exécution et fonctionnent correctement.
@ -72,4 +72,6 @@ Un code de réponse `200 OK` indiquera que le déploiement est réussi.
## Résumé ## Résumé
Le déploiement avec **Ansible** simplifie la gestion des configurations et l'installation des dépendances nécessaires pour le projet **ÉvalueTonSavoir**. Avec cette méthode, vous pouvez déployer rapidement l'application dans un environnement local tout en assurant une configuration cohérente. Le déploiement avec **Ansible** simplifie la gestion des configurations et l'installation des dépendances nécessaires
pour le projet **ÉvalueTonSavoir**. Avec cette méthode, vous pouvez déployer rapidement l'application dans un
environnement local tout en assurant une configuration cohérente.

View file

@ -11,14 +11,15 @@
git clone https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git git clone https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
``` ```
## Étape 1 - démarrage du backend ## Étape 1 - Démarrage du backend
1. Naviguez vers le répertoire du projet en utilisant la commande suivante : 1. Naviguez vers le répertoire du projet en utilisant la commande suivante :
``` ```
cd .\EvalueTonSavoir\server\ cd .\EvalueTonSavoir\server\
``` ```
2. Assurez-vous de créer le fichier .env et d'y ajouter les paramètres appropriés. Vous pouvez vous inspirer du fichier .env.example pour connaître les paramètres nécessaires. 2. Assurez-vous de créer le fichier .env et d'y ajouter les paramètres appropriés. Vous pouvez vous inspirer du fichier
.env.example pour connaître les paramètres nécessaires.
[[Voir ici la documentation des configurations|Configurations]] [[Voir ici la documentation des configurations|Configurations]]
@ -44,7 +45,8 @@
> Assurez-vous que le backend est en cours d'exécution avant de démarrer le frontend. \ > Assurez-vous que le backend est en cours d'exécution avant de démarrer le frontend. \
> Notez également l'URL du serveur pour le fichier `.env`. > Notez également l'URL du serveur pour le fichier `.env`.
2. Assurez-vous de créer le fichier .env et d'y ajouter les paramètres appropriés. Vous pouvez vous inspirer du fichier .env.example pour connaître les paramètres nécessaires. 2. Assurez-vous de créer le fichier .env et d'y ajouter les paramètres appropriés. Vous pouvez vous inspirer du fichier
.env.example pour connaître les paramètres nécessaires.
[[Voir ici la documentation des configurations|Configurations]] [[Voir ici la documentation des configurations|Configurations]]

View file

@ -0,0 +1,41 @@
# Documentation de déploiement avec OpenTofu
Ce guide explique comment **OpenTofu** est utilisé pour déployer facilement le projet **ÉvalueTonSavoir**.
## Déploiement
### Étapes à réaliser pour faire le déploiement
Pour déployer à l'aide de OpenTofu, il suffit de suivre les étapes du fichier [README.md](https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir/blob/main/opentofu/README.md).
### Structure des fichiers utilisés pour le déploiement sur Azure
- **`app.tf`** : Défini les configurations de la machine virtuelle qui exécute l'application.
- **`database.tf`** : Défini les configurations de la base de données.
- **`main.tf`** : Défini le fournisseur utilisé pour le déploiement, dans ce cas-ci Azure.
- **`network.tf`** : Défini les configurations réseau et les règles de sécurité réseau.
- **`resource_group.tf`** : Défini les configurations du groupes de ressources dans Azure.
- **`storage.tf`** : Défini les configurations pour stocker et pouvoir utiliser le fichier auth_config.json.
- **`terraform.tfvars`** : Défini les valeurs des variables à utiliser lors du déploiement.
- **`variables.tf`** : Défini toutes les variables qui sont utilisées lors du déploiement.
### Étapes effectuées par OpenTofu
1. **Création des éléments du réseau** :
- Création d'un réseau virtuel.
- Création d'un sous-réseau.
- Création d'une adresse ip publique.
- Création d'un groupe de sécurité réseau.
- Création d'une interface réseau.
2. **Création de la base de données** :
- Création du serveur de base de données.
- Création de la base de données (collection puisqu'on utilise MongoDB)
3. **Création de la machine virtuelle** :
- Création de la machine virtuelle.
- Installation de Docker
- Récupération du fichier `docker-compose.yaml` depuis le dépôt Github.
- Exécution de l'application avec le fichier `docker-compose.yaml`
## Résumé
Le déploiement avec **OpenTofu** simplifie la gestion des éléments nécessaires pour déployer le projet
**ÉvalueTonSavoir**. dans l'infonuagique. Avec cette méthode, vous pouvez déployer rapidement et facilement
l'application dans un environnement infonuagique.

View file

@ -1,9 +1,11 @@
## Introduction ## Introduction
Nous avons choisi d'exécuter les composantes de cette application avec Docker, car cela simplifie le processus de gestion des processus d'application. Nous avons choisi d'exécuter les composantes de cette application avec Docker, car cela simplifie le processus de
gestion des processus d'application.
Voici un diagramme de déploiement expliquant la relation des composantes et comment les images Docker sont créées et déployées dans un serveur. Voici un diagramme de déploiement expliquant la relation des composantes et comment les images Docker sont créées et
déployées dans un serveur.
```plantuml ```plantuml
@startuml @startuml
@ -70,9 +72,11 @@ Les STI nous a fourni un serveur avec les spécifications suivantes :
- HDD : 100 Go - HDD : 100 Go
- Certificat SSL - Certificat SSL
Les STI ont déjà effectué la configuration initiale de la machine selon leurs normes de mise en place d'un serveur pour assurer la bonne maintenance et sécurité au sein de leur infrastructure. Cette configuration inclut un utilisateur non root. Les STI ont déjà effectué la configuration initiale de la machine selon leurs normes de mise en place d'un serveur pour
assurer la bonne maintenance et sécurité au sein de leur infrastructure. Cette configuration inclut un utilisateur non root.
Vous aurez également besoin d'un compte Docker Hub, ou vous pouvez simplement créer une PR sur le projet principal et elle sera déployée automatiquement. Vous aurez également besoin d'un compte Docker Hub, ou vous pouvez simplement créer une PR sur le projet principal et
elle sera déployée automatiquement.
## Étape 1 - Installation de Docker ## Étape 1 - Installation de Docker
@ -207,7 +211,9 @@ curl -SL https://raw.githubusercontent.com/ets-cfuhrman-pfe/EvalueTonSavoir/main
``` ```
> [!NOTE] > [!NOTE]
> Avant de continuer, veuillez noter qu'il est crucial de mettre à jour les variables d'environnement dans le script, car les valeurs actuelles sont des modèles génériques. Assurez-vous de personnaliser ces variables selon les besoins spécifiques de votre environnement avant d'exécuter le script. > Avant de continuer, veuillez noter qu'il est crucial de mettre à jour les variables d'environnement dans le script,
> car les valeurs actuelles sont des modèles génériques. Assurez-vous de personnaliser ces variables selon les besoins
> spécifiques de votre environnement avant d'exécuter le script.
Avec le fichier docker-compose.yml en place, vous pouvez maintenant exécuter Docker Compose pour démarrer votre environnement : Avec le fichier docker-compose.yml en place, vous pouvez maintenant exécuter Docker Compose pour démarrer votre environnement :
``` ```

View file

@ -4,20 +4,25 @@
Pour lancer la documentation, il faut installer python et entrer dans le dossier documentation. Pour lancer la documentation, il faut installer python et entrer dans le dossier documentation.
Il faut ensuite installer les dépendances avec `pip install -r requirements.txt`. Il faut ensuite installer les dépendances avec `pip install -r requirements.txt`.
Pour lancer le mode développement il faut executer `python -m mkdocs serve` Pour lancer le mode développement il faut executer `python -m mkdocs serve`
Afin d'accellerer le déploiement et ne pas être touché par des érreurs de "rate-limiting", il est préférable d'utiliser une image docker de plantuml. Pour cela, il faut utiliser la commande suivante : `docker run -d --name plantuml -p 8080:8080 plantuml/plantuml-server:tomcat` Afin d'accélérer le déploiement et ne pas être touché par des erreurs de "rate-limiting", il est préférable d'utiliser
une image docker de plantuml. Pour cela, il faut utiliser la commande suivante :
`docker run -d --name plantuml -p 8080:8080 plantuml/plantuml-server:tomcat`
## Deploiement ## Déploiement
Le code est automatiquement déployé par la github-action `create-docs.yaml` Le code est automatiquement déployé par la github-action `create-docs.yaml`
Celle-ci ouvre le repo et fait les memes étapes que "lancer la documentation". Celle-ci ouvre le repo et fait les mêmes étapes que "lancer la documentation".
Il y a une différence, elle utilise `build` au lieu de `serve` pour ensuite publier avec l'outil [`ghp-import`](https://github.com/c-w/ghp-import). Il y a une différence, elle utilise `build` au lieu de `serve` pour ensuite publier avec l'outil [`ghp-import`](https://github.com/c-w/ghp-import).
La page est poussée sur la branche [`gh-pages`](https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir/tree/gh-pages) et ensuite publié en tant que [gh-page](https://pages.github.com/) La page est poussée sur la branche [`gh-pages`](https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir/tree/gh-pages) et ensuite publié en tant que [gh-page](https://pages.github.com/)
## Themes et Plugins ## Themes et Plugins
Si vous ajoutez des plugins, veuillez mettre a jour le fichier `requirements.txt`. Si vous ajoutez des plugins, veuillez mettre a jour le fichier `requirements.txt`.
La documentation utilise [MkDocs](https://www.mkdocs.org/) avec [le theme matérial]((https://squidfunk.github.io/mkdocs-material/)). Il y a bien des fonctionalitées tel que les code-blocks qui peuvent être activés. La documentation utilise [MkDocs](https://www.mkdocs.org/) avec [le theme matérial]((https://squidfunk.github.io/mkdocs-material/)). Il y a bien des fonctionalités tel que les c
ode-blocks qui peuvent être activés.
Vous pouvez avoir accès a la documentation ici : [https://squidfunk.github.io/mkdocs-material/reference/code-blocks/](https://squidfunk.github.io/mkdocs-material/reference/code-blocks/) Vous pouvez avoir accès a la documentation ici : [https://squidfunk.github.io/mkdocs-material/reference/code-blocks/](https://squidfunk.github.io/mkdocs-material/reference/code-blocks/)
## Autre méthode de lancement (virtuel) ## Autre méthode de lancement (virtuel)
Si vous avez un probleme avec votre environement et vous avez besoin d'un environement virtuel, il s'agit de faire `python -m venv .venv` dans le dossier document et d'activer cet environemment avec le fichier activate (changeant depedant de votre invite de commande) : `.venv\script\activate` Si vous avez un probleme avec votre environement et vous avez besoin d'un environement virtuel, il s'agit de faire
vous pouvez ensuite continuer les autres étapes. `python -m venv .venv` dans le dossier document et d'activer cet environemment avec le fichier activate (changeant
dépendant de votre invite de commande) : `.venv\script\activate`.
Vous pouvez ensuite continuer les autres étapes.

View file

@ -8,12 +8,13 @@ Le code original a été développé pour créer une extension VS afin de prendr
Le code peut être trouvé ici: [https://codesandbox.io/s/gift-templates-iny09](https://codesandbox.io/s/gift-templates-iny09) Le code peut être trouvé ici: [https://codesandbox.io/s/gift-templates-iny09](https://codesandbox.io/s/gift-templates-iny09)
Nous avons décidé de réutiliser ce code car il fournit un aperçu proche de ce à quoi ressemblent les quiz dans Moodle. Ce qui est une plateforme bien connue à l'École de technologie supérieure (ÉTS). Nous avons décidé de réutiliser ce code car il fournit un aperçu proche de ce à quoi ressemblent les quiz dans Moodle,
étant une plateforme bien connue à l'École de Technologie Supérieure (ÉTS).
Pour réutiliser le code, nous avons dû installer les packages NPM suivants: Pour réutiliser le code, nous avons dû installer les packages NPM suivants:
- [katex](https://www.npmjs.com/package/katex) : Une bibliothèque JavaScript rapide et facile à utiliser pour le rendu mathématique TeX sur le web. - [katex](https://www.npmjs.com/package/katex) : Une bibliothèque JavaScript rapide et facile à utiliser pour le rendu mathématique TeX sur le web.
- [marked](https://www.npmjs.com/package/marked) : Un analyseur syntaxique et un compilateur de markdown. Construit pour la vitesse. - [marked](https://www.npmjs.com/package/marked) : Un analyseur syntaxique et un compilateur de markdown construit pour la vitesse.
- [nanoid](https://www.npmjs.com/package/nanoid) : Un générateur d'identifiants de chaîne unique, sécurisé, convivial pour les URL et minuscule (108 octets) pour JavaScript. - [nanoid](https://www.npmjs.com/package/nanoid) : Un générateur d'identifiants de chaîne unique, sécurisé, convivial pour les URL et minuscule (108 octets) pour JavaScript.
- [gift-pegjs](https://www.npmjs.com/package/gift-pegjs) : Un analyseur GIFT pour JavaScript utilisant PEG.js. - [gift-pegjs](https://www.npmjs.com/package/gift-pegjs) : Un analyseur GIFT pour JavaScript utilisant PEG.js.
- [@types/katex](https://www.npmjs.com/package/@types/katex) : Définitions TypeScript pour katex. - [@types/katex](https://www.npmjs.com/package/@types/katex) : Définitions TypeScript pour katex.

View file

@ -1,22 +1,24 @@
# Structure haut niveau # Structure haut niveau
## But du projet ## But du projet
ÉvalueTonSavoir a été créer dû aux gros coûts des versions entreprises des logiciels similaires tels que Socrative et Kahoot. Le bût principal est dêtre capable davoir une plateforme auto-hébergée et bien intégrée dans les systèmes déjà présents des établissements scolaire. ÉvalueTonSavoir a été créé dû aux coûts importants des versions entreprises des logiciels similaires tels que Socrative et
Kahoot. Le but principal est dêtre capable davoir une plateforme auto-hébergée et bien intégrée dans les systèmes
déjà présents des établissements scolaire.
## Requis ## Requis
Le but du projet étant un outils gratuis/libre afin d'améliorer l'apprentissage, celui-ci a les bûts suivants : Le but du projet est d'avoir un outil gratuit et libre afin d'améliorer l'apprentissage avec les fonctionnalités suivantes :
- Permettre aux personnels enseignant de créer des tests - Permettre aux personnel enseignant de créer des quizs
- Permettre aux enseignant de collecter les résultats des tests - Permettre aux enseignant de collecter les résultats des quizs
- Permettre aux étudiants de prendre ces tests - Permettre aux étudiants de faire ces quizs
- Permettre aux étudiants d'avoir une rétroaction - Permettre aux étudiants d'avoir une rétroaction
Afin de limiter le niveau de difficulté d'intégration du personnel enseignant: Afin de limiter le niveau de difficulté d'intégration du personnel enseignant:
- L'utilisation du format [`GIFT`](https://docs.moodle.org/405/en/GIFT_format) déja présent dans moodle doit être utilisé - L'utilisation du format [`GIFT`](https://docs.moodle.org/405/en/GIFT_format) déja présent dans moodle doit être utilisé
- Le personnel et les étudiants doivent être capable de s'authentifier avec le portail de l'école - Le personnel et les étudiants doivent être capable de s'authentifier avec le portail de l'école
- Le démarage du quiz doit se faire de facon rapide et éfficace. - Le démarrage du quiz doit se faire de façon rapide et efficace.
Afin de faciliter le déploiement de masse : Afin de faciliter le déploiement de masse :
@ -59,13 +61,16 @@ Frontend --up-> Nginx
### Details techniques ### Details techniques
Le tableau ci-dessus est simplifié grandement car toutes les composantes sont individuelles. Ce qui veux dire qu'une toutes les parties pouraient être déployé sur un serveur différent et tout de même fonctionner, permettant de distribuer la charge de travail facilement. Le tableau ci-dessus est simplifié grandement car toutes les composantes sont individuelles. Ce qui veut dire que chacune
des parties pouraient être déployées sur un serveur différent et tout de même fonctionner. Ceci permettrai de distribuer
la charge de travail facilement entre plusieurs serveurs.
Le proxy Nginx permet de camoufler la séparation du backend et frontend en réunissant les deux parties sous la même url. Il a aussi la tache de diriger les appels de sockets vers leurs machine interne dans le provider. Le proxy Nginx permet de camoufler la séparation du backend et frontend en réunissant les deux parties sous la même url.
Il a aussi la tâche de diriger les appels de sockets vers leur machine interne dans le provider.
Le frontend déssert la partie visuel de l'application. Le frontend dessert la partie visuelle de l'application.
Le backend s'occupe de tous les services tel quel : Le backend s'occupe de tout les services suivants :
- La gestion des utilisateurs - La gestion des utilisateurs
- La gestion des quizs - La gestion des quizs

View file

@ -1,5 +1,6 @@
> [!NOTE] > [!NOTE]
> Chaque projet contient un fichier `.env.example` fournissant des exemples de configuration. Assurez-vous de consulter ce fichier pour vous inspirer des paramètres nécessaires à votre configuration. > Chaque projet contient un fichier `.env.example` fournissant des exemples de configuration.
> Assurez-vous de consulter ce fichier pour vous inspirer des paramètres nécessaires à votre configuration.
> [!NOTE] > [!NOTE]
> Ce sont toutes les options de configuration. N'hésitez pas à ouvrir une PR si vous en voyez qui manquent. > Ce sont toutes les options de configuration. N'hésitez pas à ouvrir une PR si vous en voyez qui manquent.

View file

@ -6,8 +6,13 @@ Ansible est utilisés afin de faire un déploiement sur un serveur local, opento
## Ansible ## Ansible
Le déploiement avec ansible est un déploiement simplifié. Le déploiement avec ansible est un déploiement simplifié.
Il vous suffis d'avoir un ordinateur linux/mac ou pouvant faire exécuter [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) dans le cas de windows. Il faut ensuite utiliser le gestionnaire de paquet (souvent apt) afin d'installer le paquet `ansible-core`, d'autres méthodes sont indiquées dans la [documentation officielle de ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html). Une fois le tout fais, vous pouvez telécharger [les fichiers nécéssaire](https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir/ansible) et lancer la commande `ansible-playbook -i inventory.ini deploy.yml` Il vous suffit d'avoir un ordinateur linux/mac ou pouvant faire exécuter [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install)
dans le cas de windows. Il faut ensuite utiliser le gestionnaire de paquet (souvent apt) afin d'installer
le paquet `ansible-core`, d'autres méthodes sont indiquées dans la [documentation officielle de ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html).
Une fois le tout fait, vous pouvez telécharger [les fichiers nécéssaire](https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir/ansible) et lancer la commande
`ansible-playbook -i inventory.ini deploy.yml`
## OpenTofu ## OpenTofu
Le déploiement avec OpenTofu est un peu plus complexe mais il permet d'héberger la solution sur votre cloud préféré. Le déploiement avec OpenTofu est un peu plus complexe mais il permet d'héberger la solution sur votre cloud préféré.
Il suffit [d'installer OpenTofu](https://opentofu.org/docs/intro/install/) et de téléchgarger [les fichiers nécéssaires](https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir/opentofu). Un Readme est inclus afin d'organiser votre grape de serveurs. Il suffit [d'installer OpenTofu](https://opentofu.org/docs/intro/install/) et de téléchgarger [les fichiers nécéssaires](https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir/opentofu).
Un Readme est inclus afin d'organiser votre grappe de serveurs.

View file

@ -6,5 +6,10 @@ envsubst '${PORT} ${FRONTEND_HOST} ${FRONTEND_PORT} ${BACKEND_HOST} ${BACKEND_PO
< /etc/nginx/templates/default.conf \ < /etc/nginx/templates/default.conf \
> /etc/nginx/conf.d/default.conf > /etc/nginx/conf.d/default.conf
# Adds logs for docker
ln -sf /dev/stdout /var/log/nginx/access.log
ln -sf /dev/stderr /var/log/nginx/error.log
ln -sf /dev/stderr /var/log/nginx/debug.log
# Start nginx # Start nginx
exec nginx -g "daemon off;" exec nginx -g "daemon off;"

44
opentofu/README.md Normal file
View file

@ -0,0 +1,44 @@
# Déploiement avec Opentofu
## Microsoft Azure
### Installer opentofu
https://opentofu.org/docs/intro/install/
### Installer Azure CLI
https://learn.microsoft.com/en-us/cli/azure/install-azure-cli#install
### Se connecter à Azure et récupérer l'id de l'abonnement Azure
Pour se connecter à Azure, faites la commande suivante
`az login`
Avec cette commande, vous allez sélectionner un abonnement Azure. Copiez l'id de l'abonnement, vous en aurez besoin
dans l'étape suivant.
### Modifier les configurations
Créer un fichier **terraform.tfvars** sur la base du fichier **terraform.tfvars.example** dans le répertoire **azure**.
Vous pouvez changer toutes les variables utilisée lors du déploiement dans ce fichier.
Toutes les variables, leur description et leur valeur par défaut sont disponibles dans le fichier **variables.tf**.
Créer un fichier **auth_config.json** sur la base du fichier **auth_config.json.example** dans le répertoire **opentofu**.
L'url est défini comme suit: http://<container_group_app_dns>.<location>.cloudapp.azure.com.
Par défaut, l'url est http://evaluetonsavoir.canadacentral.cloudapp.azure.com/
### Lancer le déploiement
Pour lancer le déploiement, faites les commandes suivantes
`cd azure`
`az login`
`tofu init`
`tofu apply`
Ensuite, opentofu va afficher toutes les actions qu'il va effectuer avec les valeurs configurées.
Entrez `yes` pour appliquer ces actions et lancer le déploiement.

View file

@ -0,0 +1,35 @@
{
auth: {
passportjs: [
{
provider1: {
type: "oauth",
OAUTH_AUTHORIZATION_URL: "https://www.testurl.com/oauth2/authorize",
OAUTH_TOKEN_URL: "https://www.testurl.com/oauth2/token",
OAUTH_USERINFO_URL: "https://www.testurl.com/oauth2/userinfo/",
OAUTH_CLIENT_ID: "your_oauth_client_id",
OAUTH_CLIENT_SECRET: "your_oauth_client_secret",
OAUTH_ADD_SCOPE: "scopes",
OAUTH_ROLE_TEACHER_VALUE: "teacher-claim-value",
OAUTH_ROLE_STUDENT_VALUE: "student-claim-value",
},
},
{
provider2: {
type: "oidc",
OIDC_CLIENT_ID: "your_oidc_client_id",
OIDC_CLIENT_SECRET: "your_oidc_client_secret",
OIDC_CONFIG_URL: "https://your-issuer.com",
OIDC_ADD_SCOPE: "groups",
OIDC_ROLE_TEACHER_VALUE: "teacher-claim-value",
OIDC_ROLE_STUDENT_VALUE: "student-claim-value",
},
},
],
"simpleauth": {
enabled: true,
name: "provider3",
SESSION_SECRET: "your_session_secret",
},
},
}

67
opentofu/azure/app.tf Normal file
View file

@ -0,0 +1,67 @@
# Create Virtual Machine
resource "azurerm_linux_virtual_machine" "vm" {
name = var.vm_name
resource_group_name = azurerm_resource_group.resource_group.name
location = azurerm_resource_group.resource_group.location
size = var.vm_size
admin_username = var.vm_user
admin_password = var.vm_password
disable_password_authentication = false
network_interface_ids = [azurerm_network_interface.nic.id]
os_disk {
name = var.vm_os_disk_name
caching = "ReadWrite"
storage_account_type = var.vm_os_disk_type
}
source_image_reference {
publisher = var.vm_image_publisher
offer = var.vm_image_offer
sku = var.vm_image_plan
version = var.vm_image_version
}
custom_data = base64encode(<<-EOT
#!/bin/bash
sudo apt-get update -y
sudo apt-get install -y docker.io
sudo apt-get install -y docker-compose
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker ${var.vm_user}
sudo newgrp docker
su - ${var.vm_user} -c '
curl -o auth_config.json \
"https://${azurerm_storage_account.storage_account.name}.file.core.windows.net/${azurerm_storage_share.backend_storage_share.name}/auth_config.json${data.azurerm_storage_account_sas.storage_access.sas}"
curl -L -o docker-compose.yaml ${var.docker_compose_url}
export VITE_BACKEND_URL=http://${var.dns}.${lower(replace(azurerm_resource_group.resource_group.location, " ", ""))}.cloudapp.azure.com
export PORT=${var.backend_port}
export MONGO_URI="${azurerm_cosmosdb_account.cosmosdb_account.primary_mongodb_connection_string}"
export MONGO_DATABASE=${azurerm_cosmosdb_mongo_collection.cosmosdb_mongo_collection.database_name}
export EMAIL_SERVICE=${var.backend_email_service}
export SENDER_EMAIL=${var.backend_email_sender}
export EMAIL_PSW="${var.backend_email_password}"
export JWT_SECRET=${var.backend_jwt_secret}
export SESSION_Secret=${var.backend_session_secret}
export SITE_URL=http://${var.dns}.${lower(replace(azurerm_resource_group.resource_group.location, " ", ""))}.cloudapp.azure.com
export FRONTEND_PORT=${var.frontend_port}
export USE_PORTS=${var.backend_use_port}
export AUTHENTICATED_ROOMS=${var.backend_use_auth_student}
export QUIZROOM_IMAGE=${var.quizroom_image}
docker-compose up -d
'
EOT
)
depends_on = [
azurerm_cosmosdb_mongo_collection.cosmosdb_mongo_collection,
data.azurerm_storage_account_sas.storage_access]
}

View file

@ -0,0 +1,43 @@
resource "azurerm_cosmosdb_account" "cosmosdb_account" {
name = var.cosmosdb_account_name
resource_group_name = azurerm_resource_group.resource_group.name
location = azurerm_resource_group.resource_group.location
offer_type = "Standard"
kind = "MongoDB"
mongo_server_version = "7.0"
is_virtual_network_filter_enabled = true
virtual_network_rule {
id = azurerm_subnet.subnet.id
}
capabilities {
name = "EnableMongo"
}
consistency_policy {
consistency_level = "Session"
}
geo_location {
failover_priority = 0
location = azurerm_resource_group.resource_group.location
}
depends_on = [azurerm_resource_group.resource_group]
}
resource "azurerm_cosmosdb_mongo_collection" "cosmosdb_mongo_collection" {
name = var.mongo_database_name
resource_group_name = azurerm_resource_group.resource_group.name
account_name = azurerm_cosmosdb_account.cosmosdb_account.name
database_name = var.mongo_database_name
index {
keys = ["_id"]
unique = true
}
depends_on = [azurerm_cosmosdb_account.cosmosdb_account]
}

14
opentofu/azure/main.tf Normal file
View file

@ -0,0 +1,14 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
required_version = ">= 1.0"
}
provider "azurerm" {
features {}
subscription_id = var.subscription_id
}

87
opentofu/azure/network.tf Normal file
View file

@ -0,0 +1,87 @@
# Create Virtual Network
resource "azurerm_virtual_network" "vnet" {
name = var.vnet_name
location = azurerm_resource_group.resource_group.location
resource_group_name = azurerm_resource_group.resource_group.name
address_space = ["10.0.0.0/16"]
}
# Create Subnet
resource "azurerm_subnet" "subnet" {
name = var.subnet_name
resource_group_name = azurerm_resource_group.resource_group.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
service_endpoints = ["Microsoft.AzureCosmosDB"]
}
# Create Public IP Address
resource "azurerm_public_ip" "public_ip" {
name = var.public_ip_name
location = azurerm_resource_group.resource_group.location
resource_group_name = azurerm_resource_group.resource_group.name
allocation_method = "Static"
domain_name_label = var.dns
}
resource "azurerm_network_security_group" "nsg" {
name = var.nsg_name
location = azurerm_resource_group.resource_group.location
resource_group_name = azurerm_resource_group.resource_group.name
security_rule {
name = "SSH"
priority = 1000
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = var.nsg_ssh_ip_range
destination_address_prefix = "*"
}
security_rule {
name = "HTTP"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = var.nsg_http_ip_range
destination_address_prefix = "*"
}
security_rule {
name = "HTTPS"
priority = 1002
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = var.nsg_https_ip_range
destination_address_prefix = "*"
}
}
# Create Network Interface
resource "azurerm_network_interface" "nic" {
name = var.network_interface_name
location = azurerm_resource_group.resource_group.location
resource_group_name = azurerm_resource_group.resource_group.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.public_ip.id
}
}
resource "azurerm_network_interface_security_group_association" "example" {
network_interface_id = azurerm_network_interface.nic.id
network_security_group_id = azurerm_network_security_group.nsg.id
}

View file

@ -0,0 +1,5 @@
# Create Resource Group
resource "azurerm_resource_group" "resource_group" {
name = var.resource_group_name
location = var.location
}

74
opentofu/azure/storage.tf Normal file
View file

@ -0,0 +1,74 @@
resource "azurerm_storage_account" "storage_account" {
name = var.config_volume_storage_account_name
resource_group_name = azurerm_resource_group.resource_group.name
location = azurerm_resource_group.resource_group.location
account_tier = "Standard"
account_replication_type = "LRS"
depends_on = [azurerm_resource_group.resource_group]
}
resource "azurerm_storage_share" "backend_storage_share" {
name = var.backend_storage_share_name
storage_account_name = azurerm_storage_account.storage_account.name
quota = 1
depends_on = [azurerm_storage_account.storage_account]
}
resource "null_resource" "upload_file" {
provisioner "local-exec" {
command = <<EOT
az storage file upload \
--account-name ${azurerm_storage_account.storage_account.name} \
--share-name ${azurerm_storage_share.backend_storage_share.name} \
--source ../auth_config.json \
--path auth_config.json
EOT
}
depends_on = [azurerm_storage_share.backend_storage_share]
}
locals {
# Get the current timestamp (UTC)
current_timestamp = timestamp()
start_time = local.current_timestamp
expiry_time = timeadd(local.current_timestamp, "1h")
}
data "azurerm_storage_account_sas" "storage_access" {
connection_string = azurerm_storage_account.storage_account.primary_connection_string
signed_version = "2022-11-02"
services {
file = true
blob = false
queue = false
table = false
}
resource_types {
object = true
container = false
service = false
}
permissions {
read = true
write = false
delete = false
list = true
add = false
create = false
update = false
process = false
tag = false
filter = false
}
start = local.start_time
expiry = local.expiry_time
depends_on = [null_resource.upload_file]
}

View file

@ -0,0 +1,7 @@
subscription_id = "subscription_id"
backend_session_secret = "secret"
backend_email_sender = "mail@mail.com"
backend_email_password = "password"
backend_jwt_secret = "jwt_secret"
vm_user = "username"
vm_password = "password"

214
opentofu/azure/variables.tf Normal file
View file

@ -0,0 +1,214 @@
variable "subscription_id" {
description = "The azure subscription id"
type = string
}
variable "resource_group_name" {
description = "The name of the resource group"
type = string
default = "evaluetonsavoir"
}
variable "location" {
description = "The location for resources"
type = string
default = "Canada Central"
}
variable "frontend_port" {
description = "The frontend port"
type = number
default = 5173
}
variable "backend_port" {
description = "The backend port"
type = number
default = 3000
}
variable "backend_use_port" {
description = "If true use port in the backend, else no"
type = bool
default = false
}
variable "backend_use_auth_student" {
description = "If true student need to authenticate, else no"
type = bool
default = false
}
variable "backend_session_secret" {
description = "The backend session secret"
type = string
}
variable "backend_email_service" {
description = "The name of the service use for sending email"
type = string
default = "gmail"
}
variable "backend_email_sender" {
description = "The email address used to send email"
type = string
}
variable "backend_email_password" {
description = "The email password"
type = string
}
variable "backend_jwt_secret" {
description = "The secret used to sign the jwt"
type = string
}
variable "backend_storage_share_name" {
description = "The backend volume share name"
type = string
default = "auth-config-share"
}
variable "config_volume_storage_account_name" {
description = "The volume storage account name"
type = string
default = "evaluetonsavoirstorage"
}
variable "mongo_database_name" {
description = "The name of the database"
type = string
default = "evaluetonsavoir"
}
variable "cosmosdb_account_name" {
description = "The name of the cosmosdb account"
type = string
default = "evaluetonsavoircosmosdb"
}
variable "vnet_name" {
description = "The name of the virtual network"
type = string
default = "evaluetonsavoirVnet"
}
variable "subnet_name" {
description = "The name of the subnet"
type = string
default = "evaluetonsavoirSubnet"
}
variable "public_ip_name" {
description = "The name of the public ip"
type = string
default = "evaluetonsavoirPublicIp"
}
variable "nsg_name" {
description = "The name of the network security group"
type = string
default = "evaluetonsavoirnsg"
}
variable "nsg_ssh_ip_range" {
description = "The ip range that can access to the port 22 using the network security group"
type = string
default = "0.0.0.0/0"
}
variable "nsg_http_ip_range" {
description = "The ip range that can access to the port 80 using the network security group"
type = string
default = "0.0.0.0/0"
}
variable "nsg_https_ip_range" {
description = "The ip range that can access to the port 443 using the network security group"
type = string
default = "0.0.0.0/0"
}
variable "network_interface_name" {
description = "The name of the network interface"
type = string
default = "evaluetonsavoirNetworkInterface"
}
variable "dns" {
description = "The dns of the public ip"
type = string
default = "evaluetonsavoir"
}
variable "vm_name" {
description = "The name of the virtual machine"
type = string
default = "evaluetonsavoir"
}
variable "vm_size" {
description = "The size of the virtual machine"
type = string
default = "Standard_B2s"
}
variable "vm_user" {
description = "The username of the virtual machine"
type = string
}
variable "vm_password" {
description = "The password of the virtual machine"
type = string
}
variable "vm_os_disk_name" {
description = "The name of the os disk of the virtual machine"
type = string
default = "evaluetonsavoirOsDisk"
}
variable "vm_os_disk_type" {
description = "The type of the os disk of the virtual machine"
type = string
default = "Standard_LRS"
}
variable "vm_image_publisher" {
description = "The publisher of the image of the virtual machine"
type = string
default = "Canonical"
}
variable "vm_image_offer" {
description = "The id of the image of the virtual machine"
type = string
default = "0001-com-ubuntu-server-jammy"
}
variable "vm_image_plan" {
description = "The plan of the image of the virtual machine"
type = string
default = "22_04-lts"
}
variable "vm_image_version" {
description = "The version of the image of the virtual machine"
type = string
default = "latest"
}
variable "docker_compose_url" {
description = "The url from where the docker compose file is downloaded"
type = string
default = "https://raw.githubusercontent.com/ets-cfuhrman-pfe/EvalueTonSavoir/refs/heads/main/opentofu/docker-compose.yaml"
}
variable "quizroom_image" {
description = "The image of the quiz room"
type = string
default = "ghrc.io/fuhrmanator/evaluetonsavoir-quizroom:latest"
}

View file

@ -0,0 +1,80 @@
services:
frontend:
image: ghcr.io/ets-cfuhrman-pfe/evaluetonsavoir-frontend:latest
container_name: frontend
ports:
- "5173:5173"
environment:
VITE_BACKEND_URL: ${VITE_BACKEND_URL:-http://localhost:3000}
networks:
- quiz_network
restart: always
backend:
image: ghcr.io/ets-cfuhrman-pfe/evaluetonsavoir-backend:latest
container_name: backend
ports:
- "3000:3000"
environment:
PORT: ${PORT:-3000}
MONGO_URI: ${MONGO_URI:-mongodb://mongo:27017/evaluetonsavoir}
MONGO_DATABASE: ${MONGO_DATABASE:-evaluetonsavoir}
EMAIL_SERVICE: ${EMAIL_SERVICE:-gmail}
SENDER_EMAIL: ${SENDER_EMAIL:-infoevaluetonsavoir@gmail.com}
EMAIL_PSW: ${EMAIL_PSW:-'vvml wmfr dkzb vjzb'}
JWT_SECRET: ${JWT_SECRET:-haQdgd2jp09qb897GeBZyJetC8ECSpbFJe}
FRONTEND_URL: ${FRONTEND_URL:-http://localhost:5173}
SESSION_Secret: ${SESSION_Secret:-'lookMomImQuizzing'}
SITE_URL: ${SITE_URL:-http://localhost}
FRONTEND_PORT: ${FRONTEND_PORT:-5173}
USE_PORTS: ${USE_PORTS:-false}
AUTHENTICATED_ROOMS: ${AUTHENTICATED_ROOMS:-false}
QUIZROOM_IMAGE: ${QUIZROOM_IMAGE:-ghrc.io/fuhrmanator/evaluetonsavoir-quizroom:latest}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./auth_config.json:/usr/src/app/serveur/auth_config.json
networks:
- quiz_network
restart: always
quizroom:
image: ghcr.io/ets-cfuhrman-pfe/evaluetonsavoir-quizroom:latest
container_name: quizroom
ports:
- "4500:4500"
depends_on:
- backend
networks:
- quiz_network
restart: always
nginx:
image: ghcr.io/ets-cfuhrman-pfe/evaluetonsavoir-router:latest
container_name: nginx
ports:
- "80:80"
depends_on:
- backend
- frontend
networks:
- quiz_network
restart: always
watchtower:
image: containrrr/watchtower
container_name: watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- TZ=America/Montreal
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_DEBUG=true
- WATCHTOWER_INCLUDE_RESTARTING=true
- WATCHTOWER_SCHEDULE=0 0 5 * * * # At 5 am everyday
restart: always
networks:
quiz_network:
name: evaluetonsavoir_quiz_network
driver: bridge

View file

@ -10,8 +10,6 @@ NUMBER_ROOMS=5
USERS_PER_ROOM=60 USERS_PER_ROOM=60
# Optionnal # Optionnal
MAX_MESSAGES_ROUND=20 MAX_MESSAGES_ROUND=20
CONVERSATION_INTERVAL=1000 CONVERSATION_INTERVAL=1000
MESSAGE_RESPONSE_TIMEOUT=5000 MESSAGE_RESPONSE_TIMEOUT=5000

View file

@ -8,9 +8,18 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: stress-test container_name: stress-test
network_mode: host network_mode: host
env_file: #environment:
- .env # - BASE_URL=http://127.0.0.1
# - USER_EMAIL=admin@admin.com
# - USER_PASSWORD=admin
# - NUMBER_ROOMS=5
# - USERS_PER_ROOM=60
# - MAX_MESSAGES_ROUND=20
# - CONVERSATION_INTERVAL=1000
# - MESSAGE_RESPONSE_TIMEOUT=5000
# - BATCH_DELAY=1000
# - BATCH_SIZE=10
#env_file:
# - .env
volumes: volumes:
- ./output:/app/output - ./output:/app/output
tty: true
stdin_open: true

View file

@ -9,7 +9,7 @@ import generateMetricsReport from './utility/metrics_generator.js';
dotenv.config(); dotenv.config();
const config = { const config = {
baseUrl: process.env.BASE_URL || 'http://localhost', baseUrl: process.env.BASE_URL || 'http://127.0.0.1',
auth: { auth: {
username: process.env.USER_EMAIL || 'admin@admin.com', username: process.env.USER_EMAIL || 'admin@admin.com',
password: process.env.USER_PASSWORD || 'admin' password: process.env.USER_PASSWORD || 'admin'

View file

@ -42,9 +42,13 @@ async function register(baseUrl, email, password) {
// Attempts to log in a user, or registers and logs in if the login fails. // Attempts to log in a user, or registers and logs in if the login fails.
export async function attemptLoginOrRegister(baseUrl, username, password) { export async function attemptLoginOrRegister(baseUrl, username, password) {
console.log(`Authenticating user with server : ${baseUrl}, username: ${username}, password: ${password}`);
try { try {
return await login(baseUrl, username, password); return await login(baseUrl, username, password);
} catch (loginError) { } catch (loginError) {
console.error(`Login failed for ${username}:`, loginError.message);
}
console.log(`Login failed for ${username}. Attempting registration...`); console.log(`Login failed for ${username}. Attempting registration...`);
try { try {
await register(baseUrl, username, password); await register(baseUrl, username, password);
@ -53,7 +57,6 @@ export async function attemptLoginOrRegister(baseUrl, username, password) {
console.error(`Registration and login failed for ${username}:`, registerError.message); console.error(`Registration and login failed for ${username}:`, registerError.message);
return null; return null;
} }
}
} }
// Creates a new room // Creates a new room