Skip to content

TP1 : Mini-cahier des charges

I. Intro

On veut une SPA de voting/sondage via QRCode.

Donnez lui un ptit nom fancy. On suppose dans la suite du document que le nom c'est quizzy.

L'application doit permettre à des utilisateurs de visualiser une question, et de pouvoir voter pour une réponse en scannant un QRCode.

II. Flow d'utilisation

  1. Un utilisateur visite l'URL de l'application Web
  2. Il s'enregistre puis s'authentifie
  3. Il voit une question, 3 QRCodes, le résultat actuel des votes et le temps restant pour voter
  4. Il scanne un QRCode pour voter
  5. Le résultat actuel des votes se met à jour pour inclure sa voix
  6. Il ne peut pas voter une nouvelle fois

III. Archi logicielle

1. Global

Un front sexy

Langage/framework de votre choix. Show me ur skillz.

Un back API HTTP qui contient toute la logique

Langage/framework de votre choix, je recommande NodeJS.

Une database PostgreSQL

Structure de dépôt git attendu :

├── compose.yml
├── .gitignore # ignore notamment le dossier db/
├── back
│   ├── Dockerfile
│   ├── .env.sample
│   ├── package.json
│   └── src
│       └── app.js
└── front
    ├── Dockerfile
    ├── .env.sample
    ├── package.json
    └── src
        └── app.js

2. Spec API Backend

Document dédié aux specs API Backend.

3. Schéma de DB

Document dédié au schéma de DB.

IV. Contraintes

1. Config

A. Backend

L'application doit pouvoir être configurée via variables d'environnement, à l'aide d'un fichier .env :

  • VOTE_QUESTION : la question qui s'affichera
  • QR1_LABEL : le label qui s'affichera en dessous du premier QRCode
  • QR2_LABEL : le label qui s'affichera en dessous du deuxième QRCode
  • QR3_LABEL : le label qui s'affichera en dessous du troisième QRCode
  • QR_STORAGE_PATH=/var/lib/quizzy/qrcodes
  • gestion de la durée du sondage :

    • SOIT VOTE_DURATION : la durée du sondage (en jours, heures, à votre guise), à l'issue de cette durée, il n'est plus possible de voter
    • SOIT VOTE_EXPIRY_DATE : la date d'expiraton du sondage
    • SOIT vous gérez les deux (et on ne définit que l'une des deux au lancement)
  • DB_XXX : infos de connexion à la database

    • soit une chaîne de connexion unique, genre DB_URL
    • soit plusieurs variables (une pour le user, une pour le password, une pour la db, etc)

Faites clean, et dédiez un fichier au chargement de ces variables, qui est exécuté très tôt, avant de lancer le serveur HTTP.

Un ptit config.js qui s'occupe notamment de ça, à la racine du back/src/ ce serait pas choquant 🐈

B. Frontend

Une seule variable ici : BACKEND_URL.

Permet de définir l'URL du backend : le front utiliser cette variable pour construire l'URL de l'API sur laquelle il tape.

Hint

Je rappelle qu'avec docker compose, vous utilisez juste les noms des services définis dans votre compose.yml.
Si tu as défini ton conteneur backend avec le nom back, alors la variable BACKEND_URL peut être définie à http://back.

2. QRCode

Les QRCodes sont générés au lancement de l'application (back).

Ils sont stockés sur disque dans un dossier réservé : /var/lib/quizzy/qrcodes/.

Info

Sur Linux, et donc dans vos conteneurs, le dossier standard pour stocker les données d'une application c'est /var.
Plus spécifiquement, pour les données "chaudes" de l'application : qui sont amenées à changer, on choisit /var/lib.
La bonne pratique est de créer un sous-dossier dans /var/lib/ qui porte le nom de l'application.

Le layout de fichiers attendu est :

/var/lib/quizzy/
├── qrcodes/
│   ├── choice-1.png
│   ├── choice-2.png
│   └── choice-3.png

3. Authentication

L'authentification doit être sur une base de username/password.

Gérée avec JWT signé.

Certaines des routes API nécessitent un JWT valide.

Ui ui on peut créer 40 comptes, on va pas gérer ça ici. Enfin, pas maintenant ;)

4. Continuous Integration

Le projet Git doit disposer d'une pipeline de CI Gitlab qui, au minimum :

  • vérifie que le code back et front est lint
  • vérifie que votre codebase passe un npm audit (ou équivalent si vous avez choisi autre chose que Node)
  • build une image Docker pour le front + push dans le Gitlab registry
  • build une image Docker pour le back + push dans le Gitlab registry

5. Mise à jour du front

Pour les informations dynamiques du front (votes comptabilisés actuel), on utilisera du HTTP polling.

Le front doit query à intervalles réguliers le back pour obtenir des informations (voir la spec API) et les mettre à jour côté WebUI.

6. Healthcheck

Vos applications doivent démarrer dans l'ordre, étant dépendantes les unes des autres.

Implémentez à la main dans le code une mécanique de retry de connexion à la base de données, avec un intervalle raisonnable.

Hint

Vous pouvez aussi utiliser les healthcheck: de compose.yml pour avoir un ordre de démarrage géré par compose.yml.
Quoiqu'il arrive, votre code soit supporter le retry de connexion à la base de données.

Au démarrage, le flow doit être :

  1. la database démarre
  2. une fois la database ready, le back démarre
  3. le back démarre : il charge les variables d'env, génère les QRCode, les stocke sur disque, enfin, il lance le serveur HTTP
  4. une fois le back démarré, le front peut démarrer
Note

Le front peut être démarré très tôt, tant qu'il n'y a pas de visites, y'a pas de requêtes sur le back.
Ce serait même ptet cool d'implémenter une vue "Waiting for backend to boot", truc du genre 🐈

V. Livraison

Toute la stack doit être conteneurisée avec Docker.

1. Version Développement

Une version de développement doit être livrée.

Le dépôt contient donc :

  • des Dockerfile de dév :

    • où votre npm i a été déroulé, pour pas se le taper à chaque run
  • un compose-dev.yml qui permet de lancer toute la stack

    • la base de données monte le dosseir db/ pour du dév
    • les images sont build localement
    • le code de votre PC est monté avec un volume au moment du run pour back et front : hot-reload !

2. Version Production

Une version de production doit être livrée.

Le dépôt contient donc :

  • des Dockerfile-prod de production :

    • en production, on hardcode le code dans l'image Docker
    • le code n'est PAS monté avec un volume au moment du lancement
  • un compose-prod.yml qui permet de lancer toute la stack

    • la base de données monte un volume Docker pour les données persistentes
    • les images build en CI sont lancées

VI. Bonus features

1. Multiple sondages

Gérer le fait qu'on peut relancer la stack, ou via un bouton de la WebUI, pour lancer un nouveau sondage.

On garde tous les anciens sondages en db. Un bouton est dispo sur la WebUI pour voir l'historique des sondages + leurs résultats.

Y'a donc notamment une bonne gestion d'ID à intégrer pour avoir plusieurs sondages, qui comportent chacun leurs 3 réponses possibles (labels + QRCode).

On doit aussi pouvoir avoir un moyen d'accéder en une seule URL à un sondage donné (comme ça on peut filer au user une URL unique à visiter et ils votent direct).

Note

Les variables d'environnement servent donc toujours à utiliser la solution one-shot pour lancer un unique sondage.
Gérer plusieurs sondages correspond à un use-case plus pérenne : on laisse le machin tourner, et les gens viennent créer leur sondage.

2. Dark mode

Gestion d'un dark mode.

3. Admin mode

Gestion d'un mode admin.

Un utilisateur admin est créé au démarrage de la stack.

La vue admin permet de :

  • interrompre précocémment un sondage
  • lancer de nouveaux sondages