From dd15c89edcb7e29d163f1c0c731fca2c202e4818 Mon Sep 17 00:00:00 2001 From: Marc Beninca Date: Tue, 29 Oct 2024 14:28:35 +0100 Subject: [PATCH] proofreading review --- dossier de projet/main.md | 198 +++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/dossier de projet/main.md b/dossier de projet/main.md index e7d41be..25e0936 100644 --- a/dossier de projet/main.md +++ b/dossier de projet/main.md @@ -103,7 +103,7 @@ Soutenu le : # Abstract -While working on my undergraduate degree with the Wild School, I worked on a project where we had to create a full stack web application from the ground up, from conception to deployment with a group of three other people. We called our fictional rental equipment company Oros, as it means mountain in ancient Greek, and our company specializes in mountain sports. The goal for us was to create a simple and intuitive site to manage rentals as well as the store’s inventory. +While working on my undergraduate degree with the Wild Code School, I worked on a project where we had to create a full stack web application from the ground up, from conception to deployment with a group of three other people. We called our fictional rental equipment company Oros, as it means mountain in ancient Greek, and our company specializes in mountain sports. The goal for us was to create a simple and intuitive site to manage rentals as well as the store’s inventory. Here are the main features of the application: @@ -166,11 +166,11 @@ Pour l'environnement général, nous utilisons : * Typescript, qui est transpilé en Javascript * GraphQL, pour effectuer les requêtes - * Apollo Studio, pour les builds, gestion de optimisation des APIs GraphQL + * Apollo Studio, pour les builds, gestion et optimisation des APIs GraphQL * Jest pour les tests unitaires * Cypress pour les tests end-to-end - * Git et Github, pour le versionnement et hébergement du code - * Docker et Dockerhub, pour les images à déployer et hébergement des images + * Git et Github, pour le versionnement et l’hébergement du code + * Docker et Dockerhub, pour les images à déployer et l’hébergement des images * Visual Studio Code, pour l'édition du code ## Déploiement @@ -204,11 +204,11 @@ Le serveur étant une machine virtuelle mise à disposition temporairement par n Notre formateur nous a proposé plusieurs sujets pendant notre alternance à la Wild Code School. Mon groupe et moi avons fait le choix de travailler un sujet de location, où il fallait développer un site qui met en relation des internautes avec un magasin de location, l’idée étant de faire un site pour un magasin qui fait des locations saisonnières pour les sports de montagne. Pour nous le cœur du sujet était la simplicité, pour rendre la location des biens le plus facile possible. -Notre application permet aux visiteurs de parcourir le catalogue et voir ce que le magasin a de disponible pour louer. Si un visiteur voudrait faire une réservation de matériel, il est obligé de créer un compte. Une fois le compte créé, il peut confirmer la disponibilité des produits, ajouter des produits dans son panier, puis en retirer ou modifier si besoin. Une fois décidé, il peut consulter un récapitulatif de son panier, puis créer une réservation pour les produits sélectionnés et finaliser la réservation par paiement. Pour le magasin, le rôle d’administrateur existe en plus du client. Seul un administrateur peut créer des nouveaux produits, en supprimer ou modifier si besoin, ainsi que consulter toutes les réservations en cours. Un utilisateur ne peut accéder à la partie administrative, mais un administrateur a accès à toutes les rubriques du site. +Notre application permet aux visiteurs de parcourir le catalogue et voir ce que le magasin a de disponible pour louer. Si un visiteur veut faire une réservation de matériel, il est obligé de créer un compte. Une fois le compte créé, il peut confirmer la disponibilité des produits, ajouter des produits dans son panier, puis en retirer ou modifier si besoin. Une fois décidé, il peut consulter un récapitulatif de son panier, puis créer une réservation pour les produits sélectionnés et finaliser la réservation par paiement. Pour le magasin, le rôle d’administrateur existe en plus du client. Seul un administrateur peut créer des nouveaux produits, en supprimer ou modifier si besoin, ainsi que consulter toutes les réservations en cours. Un utilisateur ne peut accéder à la partie administrative, mais un administrateur a accès à toutes les rubriques du site. ## Organisation du groupe et méthodes -Pour notre projet, nous avons fait le choix d’utiliser la méthode AGILE. Nous avons fait une liste des fonctionnalités sur notre Trello partagé, et avons coupé les parties ainsi : Backlog (à faire), en cours (branche perso), prêt à déployer (dev), et on prod (main). +Pour notre projet, nous avons fait le choix d’utiliser la méthode AGILE. Nous avons fait une liste des fonctionnalités sur notre Trello partagé, et avons découpé les parties ainsi : Backlog (à faire), en cours (branche perso), prêt à déployer (dev), et on prod (main). ![Board Trello](images/trello.png) @@ -218,13 +218,13 @@ De cette façon, à tout moment, on pouvait voir qui travaillait sur quoi, et su * dev : code fini qui doit être testé et intégré * branche perso (nommé selon la fonctionnalité) : code qui est en cours -En plus de Git, nous avons utilisé Github, un plateforme pour développer des logiciels collaboratifs et hébergeur du code. +En plus de Git, nous avons utilisé Github, une plateforme collaborative pour développer des logiciels et héberger du code. Afin de communiquer d’une manière fluide, en plus du Trello, nous avons eu à notre disposition un salon discord privé. Le serveur qui en faisait partie était accessible seulement aux personnes qui suivaient la formation, ayant été créé par le formateur de notre alternance. Comme notre salon était accessible seulement par ces personnes là, on a pu avoir l’esprit tranquille concernant nos communications ainsi que la confidentialité, car personne ne pouvait accéder à nos discussions. Nous avons aussi créé un Google Drive afin de centraliser les informations du projet. Pour tous nos modèles, nous avons travaillé ensemble sur Miro dans un board commun afin que tout le monde puisse discuter et faire des modifications si besoin. -Pour la conception de notre wireframe ainsi que la maquette de l’application, nous avons utilisé Figma. +Pour la conception de nos wireframes ainsi que les maquettes de l’application, nous avons utilisé Figma. \newpage @@ -239,11 +239,11 @@ Pour la conception de notre wireframe ainsi que la maquette de l’application, ### Le Back-end : * NodeJs : Un environnement bas niveau qui permet l’exécution du code JavaScript côté serveur. Comme il a un fonctionnement non bloquant, il permet de concevoir des applications en réseau performantes. - * ExpressJs : Un framework pour construire des applications web basées sur NodeJs. C’est pratique pour le développpement dur serveur. Il permet une création d’API simple er robuste. - * TypeORM : Une bibliothèque ORM (Object-Relational Mapping) pour TypeScript/JavaScript qui permet d’interagir avec des bases de données relationnelles en utilisant des principes OOP (object-oriented programming). Elle permet une façon de gérer les connexions de base de données et définir les modèles (entités) qui représente les tables de base de données, facilitant le travail de records de base de données comme objet. - * TypeGraphQL : Une bibliothèque qui construit des APIs graphQL en utilisant TypeScript. Elle utilise les decorators et les classes pour définir les schémas GraphQL. Par exemple, on utilise le décorateur @ObjectType pour définir une classe comme un type GraphQL, et @Field pour déclarer les propriétés de cette classe qui seront mappées aux champs GraphQL. + * ExpressJs : Un framework pour construire des applications web basées sur NodeJs. C’est pratique pour le développpement du serveur. Il permet une création d’API simple er robuste. + * TypeORM : Une bibliothèque ORM (Object-Relational Mapping) pour TypeScript/JavaScript qui permet d’interagir avec des bases de données relationnelles en utilisant des principes OOP (object-oriented programming). Elle permet une façon de gérer les connexions de base de données et définir les modèles (entités) qui représente les tables de base de données, facilitant le travail d’enregistrements de base de données comme objets. + * TypeGraphQL : Une bibliothèque qui construit des APIs GraphQL en utilisant TypeScript. Elle utilise les décorateurs et les classes pour définir les schémas GraphQL. Par exemple, on utilise le décorateur @ObjectType pour définir une classe comme un type GraphQL, et @Field pour déclarer les propriétés de cette classe qui seront mappées aux champs GraphQL. Type-GraphQL rend la création de requêtes, de mutations et de champs plus simple en les définissant comme des méthodes de classe classiques, à l’image des contrôleurs REST. Cela permet une distinction nette entre la logique métier et la couche de transport, tout en facilitant les tests unitaires des résolveurs, qui peuvent être considérés comme de simples services. - * PostgreSQL : Un système de gestion de base de données relationnelle orienté objet, qui dispose également d’une clé étrangère pour rélier les données entre plusieurs tables. + * PostgreSQL : Un système de gestion de base de données relationnelle orienté objet, qui dispose également de clés étrangères pour rélier les données entre plusieurs tables. ### Le Front-end : @@ -256,14 +256,14 @@ Type-GraphQL rend la création de requêtes, de mutations et de champs plus simp * Typescript : Un langage qui ajoute un typage statique à Javascript, ce qui permet la définition des types de données pour les variables, les fonctions, et les objets. * GraphQL : Un langage de requête de données pour API ainsi qu’un environnement d’exécution. Il permet aux clients de demander uniquement les données dont ils ont besoin. Contrairement aux APIs REST, GraphQL organise les requêtes de manière à obtenir des données provenant de plusieurs sources en un seul appel API. Côté serveur, il s’appuie sur un schéma qui décrit les données accessibles et utilise des résolveurs pour générer les valeurs correspondant aux requêtes. - Côté cleint, il s'appuie sur deux opérations principales : les Queries et les Mutations. Les Queries permettent de lire les données (l'équivalent de "Read" dans le modèle CRUD), alors que les Mutations permettent de créer, modifier, ou supprimer des données, qui sont quant à elles équivalentes aux opérations "Create", "Update", et "Delete" dans le modèle CRUD. - * Apollo Studio : Un plateforme de Apollo GraphQL qui aide les développeurs à build, gérer, et optimiser leurs APIs GraphQL. Pour le front-end, il y a Apollo Client, et le back, Apollo Server. Ayant des outils de la même équipe rend les chose plus lisibles. + Côté client, il s'appuie sur deux opérations principales : les Queries et les Mutations. Les Queries permettent de lire les données (l'équivalent de "Read" dans le modèle CRUD), alors que les Mutations permettent de créer, modifier, ou supprimer des données, qui sont quant à elles équivalentes aux opérations "Create", "Update", et "Delete" dans le modèle CRUD. + * Apollo Studio : Une plateforme de Apollo GraphQL qui aide les développeurs à concevoir, gérer, et optimiser leurs APIs GraphQL. Pour le front-end, il y a Apollo Client, et le back-end, Apollo Server. Utiliser des outils de la même équipe rend les chose plus lisibles. * Jest : Un framework de test Javascript qui permet de créer des tests unitaires. * Cypress : Un framework d’automatisation de tests basé sur Javascript, pour les tests end-to-end. - * Git : Un outil de versioning qui permet de développer les fonctionnalités sur des branches : - * Github : Un plateforme pour développer des logiciels collaboratifs et hébergeur du code, où on peut pousser le code versionné avec Git. - * Docker : Un logiciel open-source qui permet de conteuneriser des applications afin de faciliter leur déploiement. - * Dockerhub : Un plateforme pour héberger des images Docker. + * Git : Un outil de versioning qui permet de développer les fonctionnalités sur des branches. + * Github : Une plateforme collaborative pour développer des logiciels et héberger du code, où l’on peut pousser le code versionné avec Git. + * Docker : Un logiciel open-source qui permet de conteneuriser des applications afin de faciliter leur déploiement. + * Dockerhub : Une plateforme pour héberger des images Docker. * Visual Studio Code : Un éditeur de code open source développé par Microsoft. \newpage @@ -272,11 +272,11 @@ Type-GraphQL rend la création de requêtes, de mutations et de champs plus simp ## La Merise -La première chose que nous avons fait, c’était de décider quel type de location nous avions envie de faire, et comment on voulait s’organiser. Comme mentionné ci-dessus, nous avons tout d’abord créé un dossier Google Drive pour centraliser toute information pertinente. Ensuite, nous avons créé un document brainstorming pour nos premières idées pour les technologies que nous pensions utiliser afin de pouvoir créer le projet nécessaire. Afin de travailler sur la Merise et les diagrammes, nous avons utilisé Miro, un plateforme de collaboration numérique qui permet de créer des diagrammes entre autres. +La première chose que nous avons fait, c’était de décider quel type de location nous avions envie de faire, et comment on voulait s’organiser. Comme mentionné ci-dessus, nous avons tout d’abord créé un dossier Google Drive pour centraliser toute information pertinente. Ensuite, nous avons créé un document brainstorming pour nos premières idées pour les technologies que nous pensions utiliser afin de pouvoir créer le projet nécessaire. Afin de travailler sur la Merise et les diagrammes, nous avons utilisé Miro, une plateforme de collaboration numérique qui permet entre autres de créer des diagrammes. ### Modèle Conceptuel de Données -En faisant notre brainstorming, nous avons retenu ces choses clés : +En faisant notre brainstorming, nous avons retenu ces éléments clés : * Un utilisateur se connecte à une session. * Un utilisateur fait au minimum une réservation mais peut en faire plusieurs. @@ -284,15 +284,15 @@ En faisant notre brainstorming, nous avons retenu ces choses clés : * La réservation contient au moins un matériel et au maximum plusieurs matériaux. * Le matériel peut recevoir 0 réservations et au maximum plusieurs réservations. * Chaque matériel appartient à une catégorie. - * Chaque catégorie peut contenir 0 matériaux et au maximum plusieurs matériaux. + * Chaque catégorie peut contenir 0 matériels et au maximum plusieurs matériels. Avec ceci, on a pu créer une phrase qui résume nos idées, et on peut créer le modèle conceptuel de données selon cette phrase : -***Un utilisateur se connecte à une session, et envoie une réservation qui contient du matériel, et qui appartient à une catégorie, et elle contient la date du début, la date de la fin, et si la réservation a été complété.*** +***Un utilisateur se connecte à une session, et envoie une réservation qui contient du matériel, et qui appartient à une catégorie, et elle contient la date de début, la date de fin, et si la réservation a été complétée.*** ![Le Modèle Conceptuel de Données](images/MCD.jpg){width=70%} -On a aussi fait les maximalités (chiffres en bleu dans notre diagramme). Cela nous a permis de voir rapidement que la relation entre réservation et matérial allait avoir un lien Many to Many, alors pour notre MLD, nous avons mis un tableau intermédiaire afin de mieux gérer ce lien. +On a aussi fait les maximalités (chiffres en bleu dans notre diagramme). Cela nous a permis de voir rapidement que la relation entre réservation et material allait avoir un lien Many to Many, alors pour notre MLD, nous avons mis un tableau intermédiaire afin de mieux gérer ce lien. ---- @@ -312,32 +312,32 @@ Après avoir créé le modèle logique de données, nous avons procédé à cré ![Le Modèle Physique de Données](images/MPD.jpg){width=70%} -L’information vraiment pertinente dans le MPD qu’on ne trouve pas dans les autres modèles, c’est le type de données pour chaque objet. La plupart sont des VARCHAR, mais par exemple dans notre entité session, cart sera du JSON. Une autre chose qui change c’est que la plupart de nos ids sont du varchar, car on prévoit d’utiliser UUID, sauf dans le cas de l’id de catégorie, où nous avons prévu de faire des simples integers qui vont s’auto incrémenter. +L’information vraiment pertinente dans le MPD qu’on ne trouve pas dans les autres modèles, c’est le type de données pour chaque objet. La plupart sont des VARCHAR, mais par exemple dans notre entité session, cart sera du JSON. Une autre chose qui change c’est que la plupart de nos ids sont du varchar, car on prévoit d’utiliser UUID, sauf dans le cas de l’id de catégorie, où nous avons prévu de faire de simples entiers qui vont s’auto incrémenter. \newpage ## Unified Modeling Language -Après la création de notre merise, nous avons continué à travailler avec la création de l’UML, ou Unified Modeling Language. Le premier modèle que nous avons travaillé, c’était le diagramme de classe. Vous trouverez le diagramme de classe complet dans l’annexe. +Après la création de notre merise, nous avons continué à travailler avec la création de l’UML, ou Unified Modeling Language. Le premier modèle que nous avons travaillé, c’était le diagramme de classes. Vous trouverez le diagramme de classes complet dans l’annexe. ### Diagramme de classe -Le diagramme de classe reflète la définition des classes transformées en entités via GraphQL, les services, et les méthodes intégrés avec TypeORM, ainsi que les inputs pour les interactions avec le front-end. +Le diagramme de classe reflète la définition des classes transformées en entités via GraphQL, les services, et les méthodes intégrées avec TypeORM, ainsi que les entrées pour les interactions avec le front-end. -Pour le diagramme de classe, nous nous reposons sur ces idées : +Pour le diagramme de classes, nous nous reposons sur ces idées : - * Nous cherchons à développer un système qui gère la location des matériaux à notre magasin. - * Ce magasin contient des matériaux. - * Un matérial est caracterisé par son nom, sa description, son image, son stock initial, son prix. - * Un matérial est attribué à au moins une catégorie, qui a son nom. - * Pour louer un matérial, un utilisateur doit créer un compte sur le site, avec son prénom, nom de famille, son email et un mot de passe. - * Chaque fois qu'un utilisateur se connecte à notre site, cela crée une session, où nous pouvons garder les information de leur panier dans un fichier JSON. + * Nous cherchons à développer un système qui gère la location des matériels à notre magasin. + * Ce magasin contient des matériels. + * Un matériel est caracterisé par son nom, sa description, son image, son stock initial, son prix. + * Un matériel est attribué à au moins une catégorie, qui a son nom. + * Pour louer un matériel, un utilisateur doit créer un compte sur le site, avec son prénom, nom de famille, son email et un mot de passe. + * Chaque fois qu'un utilisateur se connecte à notre site, cela crée une session, où nous pouvons garder les informations de leur panier dans un fichier JSON. \newpage #### Multiplicités -Dans le diagramme de classe, il faut travailler les multiplicités, alors si on prend l’exemple de l’entity User, dans les deux directions, vers Reservation ainsi que Session, on voit qu’il y a une Multiplicité de 1. Pourquoi ? Car un User est relié à une session. Il ne peut en avoir plusieurs. Une Reservation est également relié à seulement un User, alors c’est également 1. +Dans le diagramme de classes, il faut travailler les multiplicités, alors si on prend l’exemple de l’entité User, dans les deux directions, vers Reservation ainsi que Session, on voit qu’il y a une Multiplicité de 1. Pourquoi ? Car un User est relié à une session. Il ne peut en avoir plusieurs. Une Reservation est également reliée à seulement un User, alors c’est également 1. ![Multiplicités entre Session et User, et Reservation et User](images/Reservation User Session.jpg){height=50%} @@ -345,13 +345,13 @@ Dans le diagramme de classe, il faut travailler les multiplicités, alors si on #### Portée -On peut avoir plusieurs types de portées pour les attributs : public, privé, ou protégé par exemple. On a décidé de garder tout public à part les mots de passe pour un utilisateur, qui sont privés, pour les raisons de sécurité. De cette façon, les autres classes ne pourront pas y accéder, et cela protège ces données. +On peut avoir plusieurs types de portées pour les attributs : public, privé, ou protégé par exemple. On a décidé de garder tout public à part les mots de passe pour un utilisateur, qui sont privés, pour des raisons de sécurité. De cette façon, les autres classes ne pourront pas y accéder, et cela protège ces données. -En plus de montrer les liens entre chaque Entity, on a également pris le temps d’imaginer comment ressemble nos services. En prenant User comme exemple encore, on voit comment on a décidé de créer UserService, ainsi qu’un type InputRegister, afin d’éviter de répéter les mêmes informations. +En plus de montrer les liens entre chaque Entity, on a également pris le temps d’imaginer à quoi ressemblent nos services. En prenant User comme exemple encore, on voit comment on a décidé de créer UserService, ainsi qu’un type InputRegister, afin d’éviter de répéter les mêmes informations. ![L'utilisateur dans le diagramme de classe](images/User.jpg) -En utilisant un example de notre code, on voit bien que dans notre UserService, on a pu faire la création de User plus simplement en suivant ce que nous avons prévu de faire dans notre diagramme de classe : +En utilisant un exemple de notre code, on voit bien que dans notre UserService, on a pu faire la création de User plus simplement en suivant ce que nous avons prévu de faire dans notre diagramme de classes : ```typescript // User.entity.ts -- InputType @@ -391,7 +391,7 @@ async create(data: InputRegister) { Afin de clarifier la fonctionnalité de notre site par rapport aux visiteurs, nous avons procédé à un diagramme de cas d’utilisation. Cette étape a été primordiale, car ça nous a permis de décider comment procéder avec la création de compte, le login, et le panier. On a décidé qu’un simple visiteur pourrait regarder le catalogue, mais s’il veut procéder à une réservation, il faut créer un compte et se logger. Alors, seulement un client qui s’est loggé pourrait avoir accès au panier. -Un admin, cependant, a des droits qu’un client n’a pas. Il peut créer, mettre à jour, et supprimer des matériaux si nécessaire. +Un admin, cependant, a des droits qu’un client n’a pas. Il peut créer, mettre à jour, et supprimer des matériels si nécessaire. ![Le Diagramme de cas d'utilisation](images/use case diagram.jpg){width=60%} @@ -401,7 +401,7 @@ Un admin, cependant, a des droits qu’un client n’a pas. Il peut créer, mett ### Diagramme de séquence -Le dernier diagramme UML que nous avons créé était un diagramme de séquence. Nous avons choisi de se concentrer sur comment réagit un client loggé sur le site. On peut voir quand le client fait une requête de l’inventaire du site, il devrait recevoir une réponse avec les résultats de cette recherche. Il pourrait ensuite regarder la description du matériel ainsi que de l’ajouter dans son panier, et puis enfin procéder avec le paiement si désiré. +Le dernier diagramme UML que nous avons créé était un diagramme de séquence. Nous avons choisi de se concentrer sur comment réagit un client loggé sur le site. On peut voir que quand le client fait une requête de l’inventaire du site, il devrait recevoir une réponse avec les résultats de cette recherche. Il pourrait ensuite regarder la description du matériel ainsi que l’ajouter dans son panier, et puis enfin procéder au paiement si désiré. ![Le Diagramme de séquence](images/sequence diagram.jpg){width=60%} @@ -411,9 +411,9 @@ Le dernier diagramme UML que nous avons créé était un diagramme de séquence. Suite à une séance de brainstorming sur notre vision de l'application, en tenant compte des éléments fournis par le client dans le cahier des charges, et après avoir travaillé la Merise et nos diagrammes, nous avons commencé à créer un wireframe avec l'outil Figma. Ce wireframe nous offre une représentation schématique et simplifiée de l'application, nous permettant de visualiser rapidement sa structure, son arborescence ainsi que l'organisation des composants et des interactions. Cela constitue une base solide pour débuter l'élaboration de la maquette. -![Wireframe du page d'accueil et de la recherche](images/accueil et recherche.png) +![Wireframe de page d'accueil et de la recherche](images/accueil et recherche.png) -![Wireframe du modal connexion](images/connexion.png) +![Wireframe de la modale de connexion](images/connexion.png) Ensuite, nous avons créé un moodboard pour définir l'orientation design du site. Nous avons réfléchi à l'expérience utilisateur (UX) et à l'interface utilisateur (UI) afin d'assurer une expérience à la fois efficace, agréable et fonctionnelle, tout en répondant aux attentes du client. Les maquettes intègrent des éléments visuels tels que les couleurs, les typographies, les icônes et les images, afin de représenter le style et l'identité visuelle de l'application. Nous avons également inclus des éléments d'interaction comme des boutons et des formulaires pour illustrer les fonctionnalités de l'application. @@ -429,11 +429,11 @@ Les maquettes finales ont servi de référence visuelle tout au long du processu ## Création et connexion à la base de données et accès aux données -Une fois la modélisation et les maquettes ont été faites, nous avons créé notre base de données avec PostgreSQL, que je vais vous décrire dans les prochaines étapes : +Une fois que la modélisation et les maquettes ont été faites, nous avons créé notre base de données avec PostgreSQL, décrite dans les étapes suivantes : ### Configuration de TypeORM -Nous avon mis en place TypeORM en établissant les paramètres de connexion à la base de données dans un fichier de configuration. Ce dernier inclut des détails tels que le type de base de données (PostgreSQL), l’hôte, le port, l’utilisateur, le mot de passe, et précise également les entités impliquées dans le projet (voir point suivant) : +Nous avons mis en place TypeORM en établissant les paramètres de connexion à la base de données dans un fichier de configuration. Ce dernier inclut des détails tels que le type de base de données (PostgreSQL), l’hôte, le port, l’utilisateur, le mot de passe, et précise également les entités impliquées dans le projet (voir point suivant) : ```typescript // datasource.ts @@ -525,11 +525,11 @@ export default Category; ### Opérations CRUD avec TypeORM -Les opérations de création, lecture, mise à jour et suppression des données s'effectuent dans les services grâce aux méthodes fournies par TypeORM. Cela permet une gestion efficace des données dans PostgreSQL tout en maintenant la logique métier distincte de l’implémentation des requêtes. +Les opérations de création, lecture, mise à jour et suppression de données s'effectuent dans les services grâce aux méthodes fournies par TypeORM. Cela permet une gestion efficace des données dans PostgreSQL tout en maintenant la logique métier distincte de l’implémentation des requêtes. Prenons le service CategoryServices, qui s'occupe de l'entité Category. Ce service utilise TypeORM pour communiquer avec la base de données PostgreSQL, en offrant des méthodes telles que la création (create), la lecture (findById et list), la mise à jour (update) et la suppression (delete) d'une catégorie. De plus, le service est conçu pour gérer les relations entre les catégories et les matériaux associés, en utilisant des décorateurs TypeORM comme @OneToMany. -Ci-dessous un exemple des méthodes CRUD pour l’Entity Category, dans CategoryService : +Ci-dessous un exemple des méthodes CRUD pour l’entité Category, dans CategoryService : ```typescript // category.service.ts @@ -602,9 +602,9 @@ Dans ce contexte, TypeORM facilite la gestion des données de manière efficace ### Intégration avec GraphQL et Apollo -Pour finir, TypeORM est associé à GraphQL et Apollo Server, ce qui simplifie les opérations de requêtes et de mutations sur la base de données. Les resolvers GraphQL interviennent sur le serveur pour gérer ces actions. Ils permettent d’accéder aux entités définies par TypeORM pour les requêtes (queries) et de manipuler les données lors des mutations (création, mise à jour et suppression). Chaque resolver correspond à une opération particulière de l'API GraphQL, garantissant ainsi une communication fluide entre le front-end et le back-end. +Pour finir, TypeORM est associé à GraphQL et Apollo Server, ce qui simplifie les opérations de requêtage et de mutation sur la base de données. Les resolvers GraphQL interviennent sur le serveur pour gérer ces actions. Ils permettent d’accéder aux entités définies par TypeORM pour les requêtes (queries) et de manipuler les données lors des mutations (création, mise à jour et suppression). Chaque résolveur correspond à une opération particulière de l'API GraphQL, garantissant ainsi une communication fluide entre le front-end et le back-end. -Par exemple, le resolver dédié à la gestion des catégories inclut des requêtes telles que createCategory pour créer une catégorie et updateCategory pour en mettre à jour en fonction de son identifiant. On peut voir avec le code ci-dessous qu'il suit les besoins d’une méthode CRUD, selon les méthodes fournies par CategoryServices. +Par exemple, le résolveur dédié à la gestion des catégories inclut des requêtes telles que createCategory pour créer une catégorie et updateCategory pour en mettre une à jour en fonction de son identifiant. On peut voir avec le code ci-dessous qu'il suit les besoins d’une méthode CRUD, selon les méthodes fournies par CategoryServices. ```typescript // category.resolver.ts @@ -666,7 +666,7 @@ L'authentification au sein de l'application repose sur plusieurs méthodes de s ### Hachage des mots de passe -Les mots de passe des utilisateurs sont protégés grâce à la bibliothèque argon2, qui est utilisée pour les hacher avant leur enregistrement dans la base de données. Le processus de hachage s'effectue via des middlewares TypeORM, comme @BeforeInsert et @BeforeUpdate, qui déclenchent le hachage à chaque fois qu'un mot de passe est ajouté ou modifié. Ainsi, même si la base de données venait à être compromise, les mots de passe resteraient inaccessibles. +Les mots de passe des utilisateurs sont protégés grâce à la bibliothèque argon2, qui est utilisée pour les hacher avant leur enregistrement dans la base de données. Le processus de hachage s'effectue via des middleware TypeORM, comme @BeforeInsert et @BeforeUpdate, qui déclenchent le hachage à chaque fois qu'un mot de passe est ajouté ou modifié. Ainsi, même si la base de données venait à être compromise, les mots de passe resteraient inaccessibles. ```typescript // User.entity.ts @@ -685,15 +685,15 @@ export default class User { } ``` -Plus d'information concernant argon2 est fournie dans la section Sécurité. +Plus d'informations concernant argon2 dans la section Sécurité. ---- ### JWT et gestion des cookies -Les JSON Web Tokens (JWT) servent à authentifier les utilisateurs lors de leur connexion et tout au long de leur session. Après la validation du mot de passe par argon2, un JWT est créé avec la bibliothèque jose. Ce token inclut des informations non sensibles, comme l’adresse email et le rôle de l’utilisateur, qui sont intégrées dans le payload du JWT. Cela permet d’éviter de vérifier le rôle en base de données à chaque requête, ce qui allège la charge du serveur. +Les JSON Web Tokens (JWT) servent à authentifier les utilisateurs lors de leur connexion et tout au long de leur session. Après la validation du mot de passe via argon2, un JWT est créé avec la bibliothèque jose. Ce token inclut des informations non sensibles, comme l’adresse email et le rôle de l’utilisateur, qui sont intégrées dans le payload du JWT. Cela permet d’éviter de vérifier le rôle en base de données à chaque requête, ce qui allège la charge du serveur. -Un JWT est composé de trois éléments : le header, le payload et la signature. Le header, fourni automatiquement par la bibliothèque jose, indique l’algorithme de chiffrement utilisé (dans notre cas, HS256). La signature est générée en combinant le header, le payload et une clé secrète (process.env.SECRET_KEY). Cette clé est cruciale pour la sécurité du JWT, car elle assure que le token n’a pas été modifié. Elle doit rester strictement confidentielle et ne jamais être divulguée. +Un JWT est composé de trois éléments : l’en-tête, le payload et la signature. L’en-tête, fourni automatiquement par la bibliothèque jose, indique l’algorithme de chiffrement utilisé (dans notre cas, HS256). La signature est générée en combinant l’en-tête, le payload et une clé secrète (process.env.SECRET_KEY). Cette clé est cruciale pour la sécurité du JWT, car elle assure que le token n’a pas été modifié. Elle doit rester strictement confidentielle et ne jamais être divulguée. Le JWT est ensuite enregistré dans un cookie HTTP-only, ce qui empêche l'accès par des scripts JavaScript malveillants, protégeant ainsi l'application contre les attaques XSS (Cross-Site Scripting). Grâce à ce cookie, l'utilisateur demeure authentifié pour chaque requête HTTP, et si un token valide est détecté, les informations qu'il renferme (comme l'email et le rôle) sont extraites pour établir le contexte de l'utilisateur. @@ -760,7 +760,7 @@ export interface Payload { ### Contexte de l’utilisateur -Le contexte utilisateur est créé dans le middleware Express, où le JWT est récupéré des cookies, vérifié, et l'utilisateur associé est extrait de la base de données. Ce contexte est ensuite disponible dans les résolveurs GraphQL, ce qui permet de limiter l'accès à certaines ressources ou d'adapter les réponses selon l'utilisateur connecté. +Le contexte utilisateur est créé dans le middleware Express, où le JWT est récupéré des cookies, vérifié, et l'utilisateur associé est extrait de la base de données. Ce contexte est ensuite disponible dans les résolveurs GraphQL, ce qui permet de limiter l'accès à certaines ressources ou d'adapter les réponses en fonction de l'utilisateur connecté. ```typescript //index.ts @@ -1184,7 +1184,7 @@ const materials = })) || []; ``` -Dans cette navigation principale, nous modifions dynamiquement l'interface en fonction de la page où se trouve l'utilisateur. Un état local isHomePage (de type booléen) ainsi que !isAdminRoute (aussi un boolean) sont établis selon le pathname fourni par le routeur. Le hook useEffect surveille les changements de route et met à jour cet état en conséquence. Cela nous permet d'afficher ou de masquer les boutons selon quel type d'utilisateur se trouve sur la page d'accueil, en utilisant les données récupérées. +Dans cette navigation principale, nous modifions dynamiquement l'interface en fonction de la page où se trouve l'utilisateur. Un état local isHomePage (de type booléen) ainsi que isAdminRoute (aussi un booléen) sont établis selon le pathname fourni par le routeur. Le hook useEffect surveille les changements de route et met à jour cet état en conséquence. Cela nous permet d'afficher ou de masquer les boutons selon quel type d'utilisateur se trouve sur la page d'accueil, en utilisant les données récupérées. ```typescript // MainNav.tsx @@ -1224,7 +1224,7 @@ useEffect(() => { *Catégorie "Sports d'hiver"* -![Capture d'écran du matérial trié par la catégorie sports d'hiver](images/material sorted by category.png) +![Capture d'écran du matériel trié par la catégorie sports d'hiver](images/material sorted by category.png) Lorsque l'utilisateur se trouve sur la page d'accueil, ces boutons de catégorie sont visibles, offrant un accès direct aux différentes catégories de matériels. Ces boutons sont créés dynamiquement en parcourant les catégories obtenues grâce à la requête GraphQL. Chaque bouton permet de rediriger l'utilisateur vers une page de liste de matériels correspondant à la catégorie choisie. @@ -1510,7 +1510,7 @@ Les tests jouent un rôle essentiel dans la maintenance et l'amélioration d'une * Tests end-to-end (E2E) : Ces tests couvrent l'ensemble du flux d'une application en simulant les actions des utilisateurs. Ils évaluent l'application dans son intégralité, de l'interface à la base de données. Bien qu'ils soient plus lents et moins précis que les tests unitaires, car ils englobent une plus grande surface fonctionnelle, ils sont précieux pour vérifier que l'application fonctionne correctement dans des scénarios réels. -Dans notre projet Oros, nous avons ajouté jest, une bibliothèque de tests pour les applications JavaScript, développé par Facebook. Pour écrire un test, il est nécessaire de suivre certaines règles de nommage pour les fichiers, comme Jest ne comprend que des fichiers basés sur TypeScript ou JavaScript. +Dans notre projet Oros, nous avons ajouté jest, une bibliothèque de tests pour les applications JavaScript, développée par Facebook. Pour écrire un test, il est nécessaire de suivre certaines règles de nommage pour les fichiers, comme Jest ne comprend que des fichiers basés sur TypeScript ou JavaScript. Nous avons procédé ainsi avec les tests : @@ -1617,9 +1617,9 @@ beforeAll(async () => { }); ``` -Le mock store conserve des objets de données, tels que les matériaux, que les résolveurs GraphQL peuvent interroger. Dans ce cas, listMaterials est configuré pour récupérer les matériaux depuis le store, plutôt que depuis une base de données réelle. Cela nous permet de simuler la logique de récupération des données sans nécessiter un environnement de back-end complet. Le serveur Apollo est configuré pour utiliser un schéma GraphQL et des résolveurs fictifs via @graphql-tools/mock, qui fournissent les données du store. +Le mock store conserve des objets de données, tels que les matériaux, que les résolveurs GraphQL peuvent interroger. Dans ce cas, listMaterials est configuré pour récupérer les matériels depuis le store, plutôt que depuis une base de données réelle. Cela nous permet de simuler la logique de récupération des données sans nécessiter un environnement de back-end complet. Le serveur Apollo est configuré pour utiliser un schéma GraphQL et des résolveurs fictifs via @graphql-tools/mock, qui fournissent les données du store. -Ce test vérifie ensuite que la réponse de l'API contient bien les identifiants des matériaux attendus, confirmant ainsi le bon fonctionnement de la requête listMaterials. Ce type de test d'intégration assure que les résolveurs et le schéma GraphQL interagissent correctement avec la logique du store. +Ce test vérifie ensuite que la réponse de l'API contient bien les identifiants des matériels attendus, confirmant ainsi le bon fonctionnement de la requête listMaterials. Ce type de tests d'intégration assure que les résolveurs et le schéma GraphQL interagissent correctement avec la logique du store. ```typescript // __tests__/material.test.ts @@ -1645,9 +1645,9 @@ describe('Test sur les matériels', () => { ### Tests front-end Tests front-end : -Pour ce qui concerne le front, nous avons mis en place deux tests sur notre Main Nav, un test d'unité ainsi qu'un test d'intégration. Mais tout d’abord, comme il y a un import d’un fichier css dans notre nav bar (MainNav.tsx), il fallait trouver un moyen de contourner cela, car comme mentionné ci-dessus, jest ne reconnaît que des fichiers ts ou tsx. +Pour ce qui concerne le front, nous avons mis en place deux tests sur notre Main Nav, un test unitaire ainsi qu'un test d'intégration. Mais tout d’abord, comme il y a un import d’un fichier css dans notre nav bar (MainNav.tsx), il fallait trouver un moyen de contourner cela, car comme mentionné ci-dessus, jest ne reconnaît que des fichiers ts ou tsx. -Pour éviter ce problème, nous avons installé webpack, un module bundler qui permet de traiter différents types de fichiers. Dans notre cas, il est particulièrement utile pour transformer la compréhension des fichiers css pour Jest. Nous avons aussi ajouté une ligne de code supplémentaire dans notre jest.config.ts pour rédiriger et rendre compréhensible le css éxistant dans notre MainNav. +Pour éviter ce problème, nous avons installé webpack, un module bundler qui permet de traiter différents types de fichiers. Dans notre cas, il est particulièrement utile pour transformer la compréhension des fichiers css pour Jest. Nous avons aussi ajouté une ligne de code supplémentaire dans notre jest.config.ts pour rediriger et rendre compréhensible le css existant dans notre MainNav. ```typescript // jest.config.ts @@ -1667,9 +1667,9 @@ Et par conséquent, nous avons créé ce fichier vide pour la redirection : module.exports = {}; ``` -En plus de ce contournement du fichier CSS, nous avons aussi mis en place un MockedProvider, car pour chaque test d'un composant React qui utilise Apollo Client doit l'avoir disponible dans le context de React. Dans le code de l'application, on crée ce context en encapsulant les composants, alors pour imiter au mieux ce schéma, on utilise MockedProvider. +En plus de ce contournement du fichier CSS, nous avons aussi mis en place un MockedProvider, car chaque test d'un composant React qui utilise Apollo Client doit être disponible dans le contexte de React. Dans le code de l'application, on crée ce contexte en encapsulant les composants, alors pour imiter au mieux ce schéma, on utilise MockedProvider. -Pour le premier test (un test d'unité), on teste si notre fichier MainNav.tsx affiche bien notre titre; en utilisant la méthode *`findByText`*, qui peut retourner un élément trouvé dans le DOM ou lancer une erreur si aucun élément correspondant n'est trouvé, ainsi que *`toBeInTheDocument`* comme une manière supplémentaire de s'assurer que l'élement existe dans le DOM au moment du test. +Pour le premier test (un test unitaire), on teste si notre fichier MainNav.tsx affiche bien notre titre ; en utilisant la méthode *`findByText`*, qui peut retourner un élément trouvé dans le DOM ou lancer une erreur si aucun élément correspondant n'est trouvé, ainsi que *`toBeInTheDocument`* comme une manière supplémentaire de s'assurer que l'élement existe dans le DOM au moment du test. ```typescript // Navbar.test.tsx @@ -1720,7 +1720,7 @@ describe("MainNav", () => { }); ``` -Pour le deuxième test (un test d'intégration), on veut s'assurer qu'un des boutons (nous avons choisi le bouton stock) apparaît lorqu'on est connecté en tant qu'admin sur notre application. Comme c'est un bouton qui apparaît seulement lorsqu'on est connecté en tant qu'admin, cela nous assure que l'intéraction entre le login et le MainNav fonctionne correctement. Pour ceci, un crée un mock user concernant les infos nécessaires dans USER_INFOS. +Pour le deuxième test (un test d'intégration), on veut s'assurer qu'un des boutons (nous avons choisi le bouton stock) apparaît lorqu'on est connecté en tant qu'admin sur notre application. Comme c'est un bouton qui apparaît seulement lorsqu'on est connecté en tant qu'admin, cela nous assure que l'intéraction entre le login et le MainNav fonctionne correctement. Pour ce faire, on crée un mock user contenant les infos nécessaires dans USER_INFOS. ```typescript // Navbar.test.tsx @@ -1790,17 +1790,17 @@ Comme on teste notre bouton en utilisant *`findByTestId`*; ce test id doit égal Pour faciliter le déploiement et réduire les interventions manuelles, nous avons instauré un système d'intégration et de déploiement continu (CI/CD) tant en pré-production qu'en production. Ce système utilise divers outils, notamment GitHub Actions, des webhooks, Docker, DockerHub, et Caddy en tant que proxy inverse. * Github Actions : Introduit en 2019, GitHub Actions est une solution CI/CD qui s'intègre directement aux dépôts GitHub. Elle permet d'activer des workflows en fonction d'événements, tels qu'un push sur une branche. Dans le cadre de mon projet, j'ai mis en place deux workflows YAML pour : - * Lancer des tests automatiquement + * lancer des tests automatiquement * envoyer des images Docker à Dockerhub - * Docker & Dockerhub : Les workflows de GitHub Actions créent des images Docker, qui sont ensuite sauvegardées sur DockerHub, un registre en ligne pour les conteneurs Docker. DockerHub facilite la gestion des images Docker en proposant des outils pour les créer, les tester, les stocker et les déployer. - * Caddy : Nous avons choisi Caddy comme reverse proxy pour gérer les requêtes HTTP vers notre domaine. Un reverse proxy est un serveur logiciel qui redirige les requêtes entrantes vers d'autres serveurs et renvoie ensuite la réponse au client. Ce dispositif permet de répartir la charge entre les serveurs et d'améliorer la sécurité.
-En plus de sa fonction de redirection, Caddy facilite la gestion du protocole HTTPS (Hypertext Transfer Protocol Secure). HTTPS assure la confidentialité et l'intégrité des données échangées entre le client et le serveur grâce au protocole Transport Layer Security (TLS), qui remplace l'ancien SSL. Ce protocole offre trois niveaux essentiels de protection : + * Docker & Dockerhub : Les workflows de GitHub Actions créent des images Docker, qui sont ensuite sauvegardées sur DockerHub, un registre en ligne pour les images Docker. DockerHub facilite la gestion des images Docker en proposant des outils pour les créer, les tester, les stocker et les déployer. + * Caddy : Nous avons choisi Caddy comme proxy inverse pour gérer les requêtes HTTP vers notre domaine. Un proxy inverse est un serveur logiciel qui redirige les requêtes entrantes vers d'autres serveurs et renvoie ensuite la réponse au client. Ce dispositif permet de répartir la charge entre les serveurs et d'améliorer la sécurité.
+En plus de sa fonction de redirection, Caddy facilite la gestion du protocole HTTPS (HyperText Transfer Protocol Secure). HTTPS assure la confidentialité et l'intégrité des données échangées entre le client et le serveur grâce au protocole Transport Layer Security (TLS), qui remplace l'ancien SSL. Ce protocole offre trois niveaux essentiels de protection : * Chiffrement des données pour éviter leur interception * Intégrité des données pour garantir qu'elles ne sont pas altérées - * Authentification pour vérifier l'identité des parties en communication + * Authentification pour vérifier l'identité du serveur en communication * Webhooks : Enfin, les webhooks sont configurés pour exécuter des scripts sur le serveur lorsque se produit un événement particulier, comme une mise à jour de branche. Cela permet d'automatiser des actions telles que le déploiement ou la mise à jour d'une application, sans nécessiter d'intervention manuelle. -Nous avons donc mis en place des workflows d'intégration continue (CI) afin d'automatiser les tests et le déploiement Docker de nos applications front-end et back-end. Ces workflows s'activent à chaque push, garantissant ainsi que le code est systématiquement testé et que les images Docker sont construites et publiées en cas de réussite des tests. En suivant la documentation officielle pour la configuration des workflows, le fichier YAML doit être placé à la racine du projet dans le répertoire `.github/workflows`. +Nous avons donc mis en place des workflows d'intégration continue (CI) afin d'automatiser les tests et le déploiement Docker de nos applications front-end et back-end. Ces workflows s'activent à chaque push, garantissant ainsi que le code est systématiquement testé et que les images Docker sont construites et publiées en cas de réussite des tests. En suivant la documentation officielle pour la configuration des workflows, le fichier YAML doit être placé dans le répertoire projet `.github/workflows`. ### Workflow Back-end @@ -1893,20 +1893,20 @@ jobs: Ensuite, nous avons mis en place l'environnement serveur requis pour le déploiement continu, en supposant que le VPS, Docker et Docker Compose ont déjà été installés au préalable. * Organisation des dossiers : Nous avons créé deux dossiers, *staging* et *production*, dans le répertoire principal de notre projet Oros sur le VPS. Chaque dossier renferme plusieurs fichiers de configuration essentiels : - * Docker-compose-prod.yml : Ce fichier indique à Docker comment construire et lancer les services du back-end, du front-end, et de la base de données. Il précise la version des services afin d'assurer des déploiements stables et reproductibles. Ce fichier est destiné à la production (prod), contrairement à *docker-compose.staging.yml*, qui est utilisé uniquement en phase de développement. + * Docker-compose-prod.yml : Ce fichier indique à Docker comment construire et lancer les services du back-end, du front-end, et de la base de données. Il précise la version des services afin d'assurer des déploiements stables et reproductibles. Ce fichier est destiné à la production (prod), contrairement à *docker-compose-staging.yml*, qui est utilisé uniquement en phase de développement. * Nginx.conf : Ce fichier gère la redirection des requêtes /graphql vers notre application Node.js et sert également les fichiers statiques en transmettant les informations à Caddy. * fetch-and-deploy-${{ENV}}.sh : Ce script bash, appelé par la configuration de notre Webhook, redémarre les services via Docker Compose avec les dernières versions des images Docker. Il spécifie également les ports utilisés par Nginx (8000 pour la production et 8001 pour le staging), ce qui permet à Caddy de rediriger correctement les requêtes. * .env : Ce fichier contient les variables d'environnement nécessaires au projet, telles que les secrets utilisés par les services. Il est lu par *docker-compose-prod.yml* pour fournir ces informations aux conteneurs Docker. - * Configuration de Caddy et des webhooks : Nous avons aussi configuré les fichiers de configuration pour Caddy et les webhooks : - * Caddyfile : Ce fichier permet de diriger les requêtes entrantes grâce à la directive reverse_proxy vers les ports appropriés. Les requêtes adressées à staging.1123-jaune-1.wns.wilders.dev sont redirigées vers le port 8001 (staging), celles destinées à 1123-jaune-1.wns.wilders.dev vont vers le port 8000 (production), tandis que les requêtes à ops.1123-jaune-1.wns.wilders.dev sont dirigées vers le port 9000 (service Webhook). + * Configuration de Caddy et des webhooks : Nous avons aussi écrit les fichiers de configuration pour Caddy et les webhooks : + * Caddyfile : Ce fichier permet de rediriger les requêtes entrantes grâce à la directive reverse_proxy vers les ports appropriés. Les requêtes adressées à staging.1123-jaune-1.wns.wilders.dev sont redirigées vers le port 8001 (staging), celles destinées à 1123-jaune-1.wns.wilders.dev vont vers le port 8000 (production), tandis que les requêtes à ops.1123-jaune-1.wns.wilders.dev sont redirigées vers le port 9000 (service Webhook). * Webhook.conf : Ce fichier de configuration au format JSON spécifie les actions à réaliser lors de la réception d'une notification. Nous avons configuré deux webhooks : * update-staging : le premier est déclenché automatiquement par Dockerhub lorqu'une nouvelle image est disponible, comme nous avons fait un lien entre les deux : - ![Webhook referencé sur le dépôt front-end de Dockerhub](images/webhook.png){width=70%} + ![Webhook référencé sur le dépôt front-end de Dockerhub](images/webhook.png){width=70%} - * update-prod : le deuxième peut être lancé en allant à `https://ops.1123-jaune-1.wns.wilders.dev/hooks/update-prod` une fois que les résultats sur `https://staging.1123-jaune-1.wns.wilders.dev` ont été vérifé afin de mettre l'image la plus récente de Dockerhub + * update-prod : le deuxième peut être lancé en allant à `https://ops.1123-jaune-1.wns.wilders.dev/hooks/update-prod` une fois que les résultats sur `https://staging.1123-jaune-1.wns.wilders.dev` ont été vérifé afin de mettre en place l'image la plus récente de Dockerhub * Fichiers Docker Compose et Nginx : Voici un aperçu des fichiers utilisés pour la configuration de nos services et de notre proxy : - * services : backend, frontend, db, nginx : Le fichier docker-compose-staging.yml configure les services du back-end (Node.js), du front-end (Next), de la base de données (Postgres), ainsi que Nginx pour gérer le reverse proxy. Chacun de ces services est surveillé par Docker, avec des vérifications de santé (healthcheck) et des dépendances clairement établies entre eux. + * services : backend, frontend, db, nginx : Le fichier docker-compose-staging.yml configure les services du back-end (Node.js), du front-end (Next), de la base de données (Postgres), ainsi qu’Nginx pour gérer le proxy inverse. Chacun de ces services est surveillé par Docker, avec des vérifications de santé (healthcheck) et des dépendances clairement établies entre eux. ```yml // wns_student@wns-project-server:~/apps/oros/staging$ @@ -1976,7 +1976,7 @@ Ensuite, nous avons mis en place l'environnement serveur requis pour le déploie - 8087:8080 ``` - * nginx.conf : Ce fichier a pour rôle de rediriger les requêtes entrantes. Par exemple, les requêtes adressées à /graphql sont dirigées vers le back-end, tandis que toutes les autres sont envoyées vers le front-end. + * nginx.conf : Ce fichier a pour rôle de rediriger les requêtes entrantes. Par exemple, les requêtes adressées à /graphql sont redirigées vers le back-end, tandis que toutes les autres sont envoyées vers le front-end. ```shell // nginx.conf @@ -1996,7 +1996,7 @@ Ensuite, nous avons mis en place l'environnement serveur requis pour le déploie } ``` - * fetch-and-deploy.sh : Ce script bash automatise le processus de redéploiement en arrêtant les services en cours, en récupérant les dernières versions des images Docker, puis en redémarrant les services sur le port approprié. + * fetch-and-deploy.sh : Ce script bash automatise le processus de redéploiement en arrêtant les services en cours, récupérant les dernières versions des images Docker, puis redémarrant les services sur le port approprié. ```shell #!/bin/sh @@ -2063,36 +2063,36 @@ Ensuite, nous avons mis en place l'environnement serveur requis pour le déploie # Securité de l’application -La securité d’une application est extrêmement importante. On ne peut pas penser à la création d’une application quelconque sans s’en soucier de la protection de l’application, mais surtout les données des clients. Voici ce que nous avons mis en place pour la securité de notre application : +La securité d’une application est extrêmement importante. On ne peut pas penser à la création d’une application quelconque sans se soucier de la protection de l’application, mais surtout des données des clients. Voici ce que nous avons mis en place pour la securité de notre application : - 1. TypeORM : ORM veut dire Object-Relational Mapping, c’est une bibiliothèque pour TypeScript/JavaScript qui permet les développeurs à interagir avec les bases de données en utilisant une méthode orienté-objet. Voici les raisons pour lesquelles elle peut être utile pour la sécurité : + 1. TypeORM : ORM veut dire Object-Relational Mapping, c’est une bibiliothèque pour TypeScript/JavaScript qui permet aux développeurs d’interagir avec les bases de données en utilisant une méthode orientée objet. Voici les raisons pour lesquelles elle peut être utile pour la sécurité : * Prévention d’injection SQL : comme elle sépare les données des commandes, cela aide à éviter les attaques par injection SQL - * Validation des données : TypeORM supporte les decorators pour validation, ce qui permet de mettre des contraintes sur les propriétés Entité (par exemple des champs obligatoires, des valeurs uniques), ce qui aide à se rassurer que seulement des données valides sont sauvegardées dans la base de données. - * Gestion de relation entre Entités : comme elle gère les relations par Entité, cela reduit le risque d’exposer des données sensibles par accident en faisant des quêtes complexes. On peut contrôler quelles données sont récupérées. - * Options de connexion : TypeORM permet de configurer les options de connexion d’une façon secure, y compris l’utilisation de variables d’environnement pour les données sensibles (comme les identifiants de base de données), ce qui permet de les séparer de la source du code. - * Eager / Lazy Loading : TypeORM support eager loading ainsi que lazy loading, ce qui permet de contrôler quand les données sont récupérées, ce qui peut réduire les chances d’exposer des données non nécessaires et la surface d'attaques. - 1. JSX : Comme nous utilisons Next et React pour notre application, nous avons écrit en JSX. Même si le JSX est une extension de syntaxe pour JavaScript avec React pour décrire comment l’UI devrait être, mais il peut également contribuer à la sécurité d’une application : - * Échappe automatique : le JSX échappe automatiquement des valeurs insérées dans le markup. Cela aide à empêcher des attaques Cross-Site Scripting (XSS) car n’importe quel contenu généré par un utilisateur est traité comme texte simple, et pas du code exécutable. - * Architecture basée sur les composants : Comme il encourage une approche modulaire, le JSX encourage une meilleure organisation de code. Cette séparation peut aider en isolant et en gérant les préoccupations de sécurité dans des parties plus petites et gérables. - * Rendu Contrôlé : React permet de contrôler comment les composants se rendent basés sur state et props. Cela veut dire qu’on peut rendre du contenu sous condition, ce qui peut être utile pour implémenter des mesures de sécurité (par exemple cacher des informations sensibles basés sur les rôles d’utilisateur). + * Validation des données : TypeORM supporte les décorateurs pour validation, ce qui permet de mettre des contraintes sur les propriétés Entité (par exemple des champs obligatoires, des valeurs uniques), ce qui assure que seules des données valides sont sauvegardées dans la base de données. + * Gestion de relation entre Entités : comme elle gère les relations par Entité, cela reduit le risque d’exposer des données sensibles par accident en faisant des requêtes complexes. On peut contrôler quelles données sont récupérées. + * Options de connexion : TypeORM permet de configurer les options de connexion d’une façon sûre, y compris l’utilisation de variables d’environnement pour les données sensibles (comme les identifiants de base de données), ce qui permet de les séparer du code source. + * Eager / Lazy Loading : TypeORM supporte eager loading ainsi que lazy loading, ce qui permet de contrôler quand les données sont récupérées, ce qui peut réduire les chances d’exposer des données non nécessaires et la surface d'attaques. + 1. JSX : Comme nous utilisons Next et React pour notre application, nous avons écrit en JSX. Même si le JSX est une extension de syntaxe pour JavaScript avec React pour décrire comment l’UI devrait être, il peut également contribuer à la sécurité d’une application : + * Échappement automatique : le JSX échappe automatiquement les valeurs insérées dans le markup. Cela aide à empêcher des attaques Cross-Site Scripting (XSS) car n’importe quel contenu généré par un utilisateur est traité comme texte simple, et pas du code potentiellement exécutable. + * Architecture basée sur les composants : Comme il encourage une approche modulaire, le JSX encourage une meilleure organisation de code. Cette séparation peut aider en isolant et en gérant les préoccupations de sécurité dans des parties plus petites et maintenables. + * Rendu Contrôlé : React permet de contrôler comment les composants sont rendus en se basant sur state et props. Cela veut dire qu’on peut rendre du contenu sous conditions, ce qui peut être utile pour implémenter des mesures de sécurité (par exemple cacher des informations sensibles en fonction des rôles d’utilisateur). * Validation de Props : Utiliser TypeScript avec JSX peut aider à s’assurer que les composants reçoivent les types de données attendus, ce qui réduit le risque d'erreurs d'exécution ou un fonctionnement inattendu qui peut créer des failles de sécurité. 1. Argon2 : C’est un algorithme de hachage que nous avons utilisé pour les mots de passe utilisateurs, et cela rehausse la sécurité de plusieurs manières : - * Fonction Memory-Hard : Argon2 est créé pour obliger une grande quantité de mémoire pour calculer les hashes, ce qui le rend résistant à des attaques de brute force utilisant du matériel informatique comme des GPUs et ASICs. Cela veut dire que les personne voulant faire une attaque doit investir dans des ressources très coûteuses s’ils veulent faire une attaque. - * Résistance à des attaques par canal auxiliaire : Le design d’Argon2 aide à mitiger les risques d’attaques par canal auxiliaire, comme des attaques temporelles, en rendant moins prévisible et plus consistant dans sa performance. - * Salting intégré : Argon2 incorpore automatiquement un salt dans le processus de hachage, ce qui assure que même si 2 utilisateurs ont le même mot de passe, leur hashes seront différents. Cela évite des attaques pre-calculés de hachage, comme les rainbow tables. - 1. Jose (Javascript Object Signing and Encryption): C’est un module JavaScript qui fournit plusieurs fonctionnalités qui rehaussent la sécurité, particulièrement dans la manipulation des JWT (JSON Web Tokens) et autres protocols de messagerie : + * Fonction Memory-Hard : Argon2 est créé pour obliger une grande quantité de mémoire pour calculer les hachages, ce qui le rend résistant à des attaques de force brute utilisant du matériel informatique dédié comme des GPUs et ASICs. Cela veut dire que les personnes voulant faire une attaque doivent investir dans des ressources très coûteuses s’ils veulent concrétiser une attaque. + * Résistance à des attaques par canal auxiliaire : Le design d’Argon2 aide à mitiger les risques d’attaques par canal auxiliaire, comme des attaques temporelles, en étant moins prévisible et plus consistant dans sa performance. + * Salting intégré : Argon2 incorpore automatiquement un sel dans le processus de hachage, ce qui assure que même si 2 utilisateurs ont le même mot de passe, leur hachages seront différents. Cela évite des attaques de hachages pré-calculés, comme les rainbow tables. + 1. Jose (Javascript Object Signing and Encryption): C’est un module JavaScript qui fournit plusieurs fonctionnalités qui rehaussent la sécurité, particulièrement dans la manipulation des JWT (JSON Web Tokens) et autres protocoles de messagerie : * Création et Vérification des JWTs : Jose permet de créer et vérifier facilement des JWTs pour l’authentification et l'autorisation. - * Signature et Encryption : La bibiliothèque supporte la signature (assurant l’intégrité des données et l’authencitié) et l’encryption (assurant la confidentialité des données). + * Signature et Chiffrement : La bibiliothèque supporte la signature (assurant l’intégrité des données et l’authencitié) et le chiffrement (assurant la confidentialité des données). * Support de Multiples Algorithmes : Les algorithmes cryptographiques comme HMAC, RSA et ECDSA sont disponibles, permettant le choix selon ce qui est le plus approprié. - * Gestion des clés : La bibiliothèque donne des outils pour la gestion des clés, comme le support pour la rotation des clés et diverses formats de clé. + * Gestion des clés : La bibiliothèque fournit des outils pour la gestion des clés, comme le support de la rotation de clés et de divers formats de clés. 1. Express Middleware : C'est un composant d'ExpressJs, un framework pour NodeJs qui facilite le développement d'applications. Le middleware est une fonction qui a accès à l'objet de requête (req), à l'objet de réponse (res) et à la fonction next dans le cycle de traitement des requêtes : - * Validation et Correction des Entrées : Le middleware peut valider et corriger des requêtes pour assurer que les données sont propres et elles sont dans le format attendu, aidant à empêcher des attaques d’injection, comme des injections SQL ou XSS. - * Authentification et Authorisation : Le middleware peut gérer l’authentification d’utilisateur (par exemple en vérifiant des tokens) et l’authorisation en assurant que les utilisateurs ont la permission d’accéder à certaines ressources, et cela aide à sécuriser les endpoints. - * Rate limiting : Le middleware peut limiter le nombre de requêtes un utilisateur peut faire dans un certain intervalle de temps, aidant à éviter l’abus et des attaques DOS. - * Gestion de CORS : Le middleware peut gérer les settings de Cross-Origin Resource Sharing (CORS) pour contrôler quels domaines peuvent accéder les ressources, ce qui empêche des accès non-authorisés. - * Les En-tête de sécurité : Le middleware peut ajouter des en-tête de sécurité HTTP aux réponses, ce qui donne une couche additionnelle de sécurité contre les attaques. - * Gestion des Sessions : Le middleware peut gérer les cookies de session secures et implemente les mesures comme l'expiration des cookies et secure flags pour protéger les données de session. + * Validation et Correction des Entrées : Le middleware peut valider et corriger des requêtes pour assurer que leurs données sont propres et qu’elles sont au format attendu, aidant à empêcher des attaques comme des injections SQL ou XSS. + * Authentification et Autorisation : Le middleware peut gérer l’authentification d’utilisateur (par exemple en vérifiant des jetons) et l’autorisation en assurant que les utilisateurs ont la permission d’accéder à certaines ressources, et cela aide à sécuriser les endpoints. + * Rate limiting : Le middleware peut limiter le nombre de requêtes qu’un utilisateur peut faire dans un certain intervalle de temps, aidant à éviter l’abus et des attaques de type DDOS. + * Gestion de CORS : Le middleware peut gérer les paramètres de Cross-Origin Resource Sharing (CORS) pour contrôler quels domaines peuvent accéder aux ressources, ce qui empêche des accès illégitimes. + * Les En-têtes de sécurité : Le middleware peut ajouter des en-têtes de sécurité HTTP aux réponses, ce qui ajoute une couche supplémentaire de sécurité contre les attaques. + * Gestion des Sessions : Le middleware peut gérer les cookies de session et implémente des mesures de sécurité comme l'expiration des cookies et secure flags pour protéger les données de session. -# Annexe (diagramme de classe) +# Annexe (diagramme de classes) ![](images/class diagram.jpg){height=95%}