Cours Node.js Cours Node.js - Séance 4 - Application Web avancée

Objectifs de cette séance

Afin de savoir développer et maintenir une application Web réaliste et pérenne, nous allons:

Durée estimée cours + exercices: 6 heures.

Pré-requis

Pour effectuer ces exercices, assurez-vous que les pré-requis suivants sont bien installés et accessibles depuis votre terminal Bash (ou compatible):


Exercice 4.1 - Tests automatisés avec Ava

La plupart des applications sont amenées à fonctionner pendant plusieurs années. L’évolution des besoins des utilisateurs, des entreprises, ainsi que l’évolution des technologies et des normes de sécurité implique que le code source de ces applications devra être modifié régulièrement. Notamment pour y ajouter des fonctionnalités et corriger des bugs. Afin d’éviter que la maintenance d’un programme ne devienne de plus en plus coûteuse et risquée, il faut suivre quelques règles d’hygiène, parmi lesquelles: définir des tests.

Pour vérifier que les fonctionnalités d’un programme se comportent comme prévu, il est possible de le tester “à la main”. C’est à dire: d’interagir manuellement avec ce programme, via son (ou ses) interface(s). Par exemple, dans le cas d’un site statique, il suffit de consulter le site à l’aide de plusieurs navigateurs, et d’explorer ses pages pour s’assurer que le contenu s’affiche comme prévu. Dans le cas d’un site dynamique – ou pire: d’un site dynamique avec compte utilisateurs – il y a beaucoup plus de cas à tester. Il faut en effet vérifier que les procédure de création de compte utilisateur, d’identification et d’oubli de mot de passe fonctionnent bien, mais aussi que les informations stockées en base de données ne sont visibles qu’aux utilisateurs qui sont sensés y avoir accès.

L’écriture de tests automatisés permet de définir une fois pour toutes cette liste de vérifications à mener, pour vérifier qu’un site (ou programme) fonctionne comme prévu.

Il existe trois grandes catégories de tests:

Le but de cet exercice est de compléter le site dynamique que nous avons créé lors de la séance précédente, afin d’y intégrer des tests automatisés.

Critères de validation

Étapes proposées

Ces étapes sont décrites moins précisément que celles fournies dans les exercices précédents. Utilisez les ressources disponibles sur Internet pour vous aider: documentation de Node.js, des modules npm utilisés, examples, tutos, etc…

  1. Ajouter le moteur de tests “Ava” à notre projet Node.js.
  2. Créer test.js et y définir un test fonctionnel qui vérifiera que la page d’index du site comprend bien un formulaire HTML.
  3. Compléter package.json et README.md afin d’expliquer comment exécuter ce test.
  4. Ajouter à test.js un test fonctionnel ou d’intégration qui vérifiera que la page “ville” contient bien le nom de la ville qui lui a été passé en paramètre POST.
  5. Versionner le code avec $ git tag v4.1 puis le pousser vers le dépôt distant que vous avez créé pendant la séance précédente.

BONUS:

Pro tip: Vous pouvez utiliser le module nock dans vos tests d’intégration pour intercepter et modifier les réponses de l’API externe geocode.xyz.


Exercice 4.2 - Sessions utilisateur

Certains sites et applications web personnalisent leur contenu et fonctionnalités en fonction de l’utilisateur qui y est connecté. Pour permettre cela, le serveur Web doit permettre l’identification et l’authentification de ces utilisateurs, puis le stockage d’une “session utilisateur” en base de données, pour chacun d’eux.

Une session utilisateur est un ensemble d’informations conservées dans le back-end (la partie serveur de notre application Web) qui permettent de déterminer l’identité d’un utilisateur connu après qu’il se soit identifié auprès de notre application Web (log in / sign in). Quand une session expire (ex: après plusieurs jours), est close ou perdue par l’utilisateur (ex: log out / sign off = déconnexion volontaire, ou perte de cookie), ce dernier devra à nouveau s’identifier pour initier une nouvelle session.

Dans cet exercice, nous allons intégrer la stratégie “passport-local” du module Passport dans notre application Express.js, afin de permettre aux visiteurs de s’identifier au travers d’un compte utilisateur.

Critères de validation

Étapes proposées

Ces étapes sont décrites moins précisément que celles fournies dans les exercices précédents. Utilisez les ressources disponibles sur Internet pour vous aider: documentation de Node.js, des modules npm utilisés, examples, tutos, etc…

  1. Dans un premier temps, nous allons permettre à un seul utilisateur de se connecter à l’aide d’un identifiant et mot de passe stockés en dur dans le code.
    • Suivre le guide “Username & Password” pour installer le module “passport-local” dans notre projet, le configurer et l’intégrer dans l’application Express.js.
    • Modifier la fonction passée à new LocalStrategy() de manière à ce qu’elle vérifie que l’identifiant et le mot de passe saisis par l’utilisateur corresponde bien aux valeurs que vous aurez choisi et stocké en dur dans votre code, au lieu de chercher l’utilisateur en base de données.
    • Vérifier que http://localhost:3000/login vous amène bien vers la page d’accueil du site, seulement si vous saisissez le bon identifiant et le bon mot de passe.
    • Conservez vos modifications: $ git commit -m "user can login with hard-coded credentials"
  2. Maintenant que le login fonctionne, nous allons permettre aux visiteurs de créer leur propre compte utilisateur, avec leurs propres identifiants.
    • Créer un objet users vide. Il sera complété par notre application à chaque fois qu’un utilisateur aura créé son compte. Structure recommandée pour cette objet:
        {
       'user_id_1': { hashedPassword: '92a19566e016ebce288f71113f95f77c' },
       'user_id_2': { hashedPassword: '1fdc0f893412ce55f0d2811821b84d3b' },
       // ...
        }
      
    • Déplacez les identifiants que vous avez défini en dur, dans cet objet users.
    • Pour réduire le risque de fuite de ce mot de passe, le hasher à l’aide de l’algorithme MD5, dans la propriété hashedPassword.
    • Enfin, modifier la fonction de vérification des identifiants (cf étape précédente) de manière à ce qu’elle hashe le mot de passe saisi par l’utilisateur avec MD5, afin de pouvoir le comparer avec le hash stocké dans notre objet.
    • Ajouter et implémenter une route /signup pour permettre aux visiteurs de créer leur propre compte depuis un formulaire Web. Après cela, ils devraient être en mesure de s’identifier.
    • Conservez vos modifications: $ git commit -m "user can create an account"
  3. Maintenant qu’il est possible de créer un compte et de s’identifier avec son compte, nous allons créer une page à accès restreint et un moyen de se déconnecter.
    • Créer et implémenter la route /me. La page retournée devra afficher l’identifiant de l’utilisateur qui est connecté, ou un message d’erreur avec code de status HTTP 401 s’il n’est pas connecté.
    • Ajouter et implémenter la route /logout. Cet endpoint supprimera la session de l’utilisateur qui était connecté puis redirigera vers l’index du site.
    • Vérifier que le page /me se comporte comme prévu dans chaque cas: avant de se connecter (c.a.d. sans session), après s’être connecté (c.a.d. avec session), et après s’être déconnecté (c.a.d. session supprimée).
    • Conservez vos modifications: $ git commit -m "user can see a protected page and sign off"
  4. Actuellement, les sessions sont perdues si on redémarre notre serveur, car elles sont stockées en mémoire. Pour qu’elles soient conservées, nous allons les faire persister en base de données.
    • À l’aide de la documentation de passport.js et de ce que nous avons appris lors de la séance 2, modifier notre code pour maintenir la liste des utilisateurs et de leurs sessions dans une base de données MongoDB.
    • Conservez vos modifications: $ git commit -m "users and sessions are persisted in mongodb"
  5. Versionner le code avec $ git tag v4.2 puis le pousser vers le dépôt distant que vous avez créé pendant la séance précédente.

BONUS:


Pour aller plus loin

Ressources sur la maintenabilité, les tests et la sécurité:

Ressources sur l’identification et l’authentification:

Ressources sur l’architecture et scalabilité d’applications Node.js: