From e0b26b633b3078f212f0f00527038830ce80d0f4 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer <kraemer@unistra.fr> Date: Thu, 26 Nov 2020 10:12:43 +0100 Subject: [PATCH] ajout sujet 3 --- sujets/sujet3.md | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 sujets/sujet3.md diff --git a/sujets/sujet3.md b/sujets/sujet3.md new file mode 100644 index 000000000..c38b5afd1 --- /dev/null +++ b/sujets/sujet3.md @@ -0,0 +1,53 @@ +Authentification, routage et contextes +=== + +Ecrire une application qui gère la connexion d'un utilisateur en lien avec une API HTTP distante. + +Lire la [doc de `react-router`](https://reacttraining.com/react-router/web/guides/quick-start). + +V1 +--- + +L'application affiche un menu (donné par un composant `Menu`) contenant les entrées suivantes : + - Home (qui mène à la route "/") + - si l'utilisateur n'est pas connecté : + - Signin (qui mène à la route "/signin") + - Signup (qui mène à la route "/signout") + - si l'utilisateur est connecté : + - le nom de l'utilisateur connecté ("Connected as ...") + - Signout (qui appelle la logique de déconnexion) + +A chaque route ("/", "/signin", "/signup") correspond le rendu d'un composant particulier (`Home`, `Signin`, `Signup`). + +Les informations relatives à l'utilisateur connecté sont maintenues dans le composant principal (seul à contenir la logique de connexion ainsi que la connaissance de l'API) : + - Un objet `user` dans le state (initialisé à `null`) contenant l'utilisateur actuellement connecté + - Une fonction `signin` qui permet de soumettre un couple (identifiant, mot de passe) à l'API distante qui, en cas de succès, renvoie un JSON Web Token (JWT) ainsi qu'un objet correspondant au `user` authentifié. Le token doit alors être stocké en `localStorage` et l'utilisateur peut être emmené vers la route "/". + - Une fonction `signup` qui permet de soumettre un couple (identifiant, mot de passe) pour inscription. En cas de succès, on emmène l'utilisateur vers la route "/signin". + +Les composants `Signin` et `Signup` proposent un formulaire adéquat et font appel, lors de la soumission du formulaire, à une fonction `onSubmit` reçue en prop qui fait à son tour appel respectivement aux fonctions `signin` et `signup` du composant principal. +Faire en sorte qu'en cas d'échec des requêtes, le message d'erreur reçu s'affiche sous le formulaire. + +Au lancement de l'application, faire en sorte de restaurer l'utilisateur connecté en exploitant le JSON Web Token présent en `localStorage` si il existe (voir la route `/whoami` de l'API). +En attendant la réponse du serveur, ne rendre qu'un message d'attente. + +API +--- + +L'API HTTP fournie comprend les routes suivantes : + - `POST /signin` : reçoit un objet de la forme `{ username: '...', password: '...' }`. En cas de succès, renvoie une réponse HTTP code 200 avec un objet de la forme `{ token: '...', user: { id: 42, username: '...' } }`. En cas d'échec, renvoie une réponse HTTP code 401 avec un message d'erreur. + - `POST /signup` : reçoit un objet de la forme `{ username: '...', password: '...' }`. En cas de succès, renvoie une réponse HTTP code 200. En cas d'échec, renvoie une réponse HTTP code 500 avec un message d'erreur. + - `GET /whoami` : lit l'en-tête `Authorization` de la requête HTTP au format `"Bearer [JSON Web Token]"`. En cas de succès du décodage du token, renvoie une réponse HTTP code 200 avec un objet de la forme `{ id: 42, username: '...' }`. En cas d'échec, renvoie une réponse HTTP code 404 avec un message d'erreur. + +V2 +--- + +Les données concernant l'utilisateur connecté sont potentiellement utiles à différents niveaux de l'application. +Pour éviter d'avoir à passer ces informations manuellement au travers de nombreuses couches de composants ("props drilling"), on peut mettre en place un contexte, qui donnera accès aux données souhaitées dans tout le sous-arbre de l'application. + +Dans un module séparé (`auth.js` par exemple), créer un contexte `AuthContext`, et exporter 2 éléments : + - un composant `AuthProvider` dans lequel on va déplacer les données et la logique liées à la gestion de l'utilisateur. Ce composant rend le `Provider` du contexte `AuthContext` en lui passant comme valeur un objet contenant les champs `user`, `signup`, `signin` et `signout`. Le contenu du `Provider` est les éléments fils reçus par le composant `AuthProvider` (`children`). + - un custom hook `useAuth` qui retourne simplement le résultat de `useContext(AuthContext)` + +Nettoyer le composant principal de l'application qui ne devrait plus contenir que la déclaration du `AuthProvider`, le menu et les routes. + +Dans les composants `Menu`, `Signin` et `Signup`, récupérer les données nécessaires du contexte d'authentification grâce à la fonction `useAuth`. -- GitLab