From f497a051443bd45135fb887514d7f3851d8120df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20PENHO=C3=8BT?= Date: Wed, 21 Oct 2020 16:45:34 +0200 Subject: [PATCH] =?UTF-8?q?Modification=20page=20et=20script=20de=20cr?= =?UTF-8?q?=C3=A9ation=20de=20compte=20pour=20prendre=20en=20compte=20simp?= =?UTF-8?q?lification=20(uniquement=20e-mail=20+=20validation=20CGU=20dura?= =?UTF-8?q?nt=20premi=C3=A8re=20=C3=A9tape)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/user.js | 45 ++++++++------------- front/public/inscription.html | 34 ++++------------ front/src/groupElement.js | 2 +- front/src/subscribe.js | 74 +++++++---------------------------- 4 files changed, 41 insertions(+), 114 deletions(-) diff --git a/controllers/user.js b/controllers/user.js index d03d8fa..83bd518 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -62,7 +62,7 @@ exports.getGodfatherId = async (req, res, next) => } // Contrôleur traitant les données envoyées pour une inscription -// Il peut n'y avoir qu'une adresse e-mail ou des données plus complètes (pseudo, parrain, etc.) dès l'inscription +// Les CGU doivent être acceptées et une adresse e-mail envoyée. Le reste peut être adapté sur la page de validation. exports.signup = async (req, res, next) => { try @@ -70,34 +70,22 @@ exports.signup = async (req, res, next) => const db = require("../models/index"); if(req.body.cguOk !== "true") res.status(400).json({ errors: [txt.needUGCOk] }); - else if((req.body.password !== undefined) && (req.body.password.length < config.passwordMinLength)) - res.status(400).json({ errors: [txt.needLongPassWord.replace("MIN_LENGTH", config.passwordMinLength)] }); else if(tool.isEmpty(req.body.email)) res.status(400).json({ errors: [txt.needEmail] }); else { - // Dans le cas d'une inscription simplifiée, seule l'adresse e-mail est demandée : - if(tool.isEmpty(req.body.password)) - req.body.password=tool.getPassword(8, 12); - req.body.password=await bcrypt.hash(req.body.password, config.bcryptSaltRounds); - // Si pas de pseudo envoyé, on utilise la partie de l'e-mail précédant le "@" - if(tool.isEmpty(req.body.name)) - { - const lastIndex=req.body.email.indexOf("@"); - if(lastIndex === -1) - lastIndex=1; - req.body.name=req.body.email.substring(0,lastIndex); - } - req.body.GodfatherId=null; - if(req.body.codeGodfather!=="") - { - const godfather=await searchIdGodfather(req.body.codeGodfather); - if(godfather) - req.body.GodfatherId=godfather.id; - } - const user=await db["User"].create({ ...req.body }, { fields: ["name", "email", "password", "newsletterOk", "GodfatherId", "timeDifference"] }); - req.body.UserId=user.id;/// revoir si noticeOk et newsletterOk toujours utiles ? - // si l'utilisateur a répondu à un quiz avant de créer son compte, on enregistre son résultats. + // Un mot de passe temporaire et non communiqué est généré : + req.body.passwordTemp=tool.getPassword(8, 12); + console.log(req.body.passwordTemp); + req.body.password=await bcrypt.hash(req.body.passwordTemp, config.bcryptSaltRounds); + // Un pseudo temporaire est créé en utilisant la partie de l'e-mail précédant le "@" : + const lastIndex=req.body.email.indexOf("@"); + if(lastIndex === -1)// possible car validité de l'e-mail testé par le modèle lors de l'enregistrement + lastIndex=1; + req.body.name=req.body.email.substring(0, lastIndex); + const user=await db["User"].create({ ...req.body }, { fields: ["name", "email", "password", "timeDifference"] }); + req.body.UserId=user.id; + // si l'utilisateur a répondu à un quiz avant de créer son compte, on enregistre son résultat : if(req.body.QuestionnaireId) { await Promise.all([ @@ -123,6 +111,7 @@ exports.signup = async (req, res, next) => } } +// Contrôleur testant le lien de validation du compte et envoyant un message de bienvenue si tout est ok exports.signupValidation = async (req, res, next) => { try @@ -137,7 +126,7 @@ exports.signupValidation = async (req, res, next) => { const now=new Date(); await Promise.all([ - db["Subscription"].create({ numberOfDays: config.freeAccountTimingInDays, numberOfDays: config.defaultReceiptDays, noticeOk: datas.User.newsletterOk, UserId: datas.User.id }),/// revoir si noticeOk et newsletterOk toujours utiles ? + db["Subscription"].create({ numberOfDays: config.freeAccountTimingInDays, numberOfDays: config.defaultReceiptDays, UserId: datas.User.id }), db["User"].update({ connectedAt: now }, { where: { id : datas.User.id }, limit:1 }) ]); const newUser=await creaUserJson(datas.User.id); @@ -189,7 +178,7 @@ exports.signUpCompletion = async (req, res, next) => res.status(400).json({ errors: txt.needLongPassWord.replace("MIN_LENGTH", config.passwordMinLength) }); else { - if(!tool.isEmpty(req.body.newPassword)) + if(!tool.isEmpty(req.body.newPassword))// dans ce cas, l'utilisateur n'a pas choisi de mot de passe, mais pourra se connecter via les tokens de connexion req.body.password=await bcrypt.hash(req.body.newPassword, config.bcryptSaltRounds); req.body.GodfatherId=null; if(req.body.codeGodfather !== "") @@ -203,7 +192,7 @@ exports.signUpCompletion = async (req, res, next) => db["Subscription"].update({ ...req.body }, { where: { UserId : req.connectedUser.User.id }, fields: ["receiptDays"], limit:1 }) ]); const user=await creaUserJson(req.connectedUser.User.id); - // si un parrain a été désigné, on prévient l'heureux élu :) : + // Si un parrain a été désigné, on prévient l'heureux élu :) : if(user!==false && req.body.GodfatherId !== null) { const godfather=await searchUserById(req.body.GodfatherId); diff --git a/front/public/inscription.html b/front/public/inscription.html index aebc7ab..107c1f6 100644 --- a/front/public/inscription.html +++ b/front/public/inscription.html @@ -4,7 +4,7 @@ - S'inscrire à WikiLerni + Créer son compte WikiLerni @@ -36,47 +36,29 @@

Créer votre compte WIKILERNI

-
-
- -
- +
- -
- -
Au moins 8 caractères. Générer un mot de passe.
-
- -
- -
Facultatif.
-
-
- +

Besoin d'aide ?

-

La saisie d'un pseudonyme, d'une adresse e-mail et d'un mot de passe est obligatoire et vous devez accepter les Conditions Générales d'Utilisation.

-

Votre pseudonyme est complétement libre, mais servira à personnaliser certains affichages.

+

Votre compte vous permettra de recevoir régulièrement de nouvelles "graines de culture" directement sur votre adresse e-mail. Vous pourrez aussi sauvegarder vos résultats aux quizs.

+

La saisie d'une adresse e-mail est obligatoire et vous devez accepter les Conditions Générales d'Utilisation.

Vous recevrez un lien sur l'adresse e-mail saisie sur lequel vous devrez cliquer pour valider la création de votre compte.

-

Votre mot de passe doit compter au moins 8 caractères. Si vous manquez d'inspiration, cliquez sur le lien "Générer un mot de passe" pour en obtenir un.

-

Si vous connaissez une personne déjà inscrite à WikiLerni, vous pouvez fournir son code parrain ou encore son adresse e-mail. Dans le cas où vous optez ensuite pour un abonnement prémium, il sera alors allongé de 30 jours grâce à ce parrainage.

+

Une fois cliqué sur ce lien, vous serez invité à compléter vos informations (pseudo, mot de passe...) ou encore à désigner votre "parrain" (si c'est le cas).

+

La création de votre compte est gratuite et sans engagement. Elle vous permet de tester WikiLerni durant une période de 15 jours. Libre à vous ensuite de vous abonner ou pas.

diff --git a/front/src/groupElement.js b/front/src/groupElement.js index 015688c..043906e 100644 --- a/front/src/groupElement.js +++ b/front/src/groupElement.js @@ -123,7 +123,7 @@ myForm.addEventListener("submit", function(e) if(datas) { datas.timeDifference=getTimeDifference(configUsers); - // si l'utilisateur a précédement répondu à un quiz, on ajoute les données de son résultat : + // Si l'utilisateur a précédement répondu à un quiz, on ajoute les données de son résultat : datas=checkAnswerDatas(datas); xhr.send(JSON.stringify(datas)); } diff --git a/front/src/subscribe.js b/front/src/subscribe.js index c4b4eef..af423be 100644 --- a/front/src/subscribe.js +++ b/front/src/subscribe.js @@ -1,7 +1,8 @@ // -- GESTION DU FORMULAIRE PERMETTANT DE CRÉER SON COMPTE /// L'utilisateur peut avoir répondu à un quiz avant d'arriver sur la page d'inscription -/// Des ce cas il faut enregistrer son résultat en même temps que les informations de son compte +/// Des ce cas il faut enregistrer son résultat en même temps que les premières informations de son compte (email, ok CGU) +/// Les infos du compte sont complétées (mot de passe, code parrain...) au moment de la validation. // Fichier de configuration tirés du backend : import { apiUrl, availableLangs, theme } from "../../config/instance.js"; @@ -15,25 +16,18 @@ import { getLocaly, removeLocaly, saveLocaly } from "./tools/clientstorage.js"; import { addElement } from "./tools/dom.js"; import { helloDev } from "./tools/everywhere.js"; import { getDatasFromInputs, setAttributesToInputs } from "./tools/forms.js"; -import { getPassword } from "../../tools/main"; import { loadMatomo } from "./tools/matomo.js"; import { checkAnswerDatas, checkSession, getTimeDifference } from "./tools/users.js"; // Dictionnaires : -const { notRequired, serverError } = require("../../lang/"+lang+"/general"); -const { alreadyConnected, godfatherFound, godfatherNotFound, needUniqueEmail, passwordCopied } = require("../../lang/"+lang+"/user"); +const { serverError } = require("../../lang/"+lang+"/general"); +const { alreadyConnected, needUniqueEmail } = require("../../lang/"+lang+"/user"); // Principaux éléments du DOM manipulés : -const myForm=document.getElementById("subscription"); -const divResponse=document.getElementById("response"); -const passwordInput=document.getElementById("password"); -const passwordLink=document.getElementById("getPassword"); -const passwordHelp=document.getElementById("passwordMessage"); -const emailInput=document.getElementById("email"); const btnSubmit=document.getElementById("submitDatas"); -const codeGodfatherInput=document.getElementById("codeGodfather"); - -helloDev(); +const divResponse=document.getElementById("response"); +const emailInput=document.getElementById("email"); +const myForm=document.getElementById("subscription"); // Test de connexion de l'utilisateur + affichage formulaire d'inscription. const initialise = async () => @@ -43,7 +37,7 @@ const initialise = async () => const isConnected=await checkSession(); if(isConnected) { - saveLocaly("message", { message: alreadyConnected, color:"info" });// pour l'afficher sur la page suivante + saveLocaly("message", { message: alreadyConnected, color:"info" }); const user=getLocaly("user", true); const homePage=user.status+"HomePage"; window.location.assign("/"+configTemplate[homePage]); @@ -62,25 +56,10 @@ const initialise = async () => } } initialise(); +helloDev(); -// Générateur de mot de passe "aléatoire" -passwordLink.addEventListener("click", function(e) -{ - e.preventDefault(); - passwordInput.type="text"; - passwordInput.value=getPassword(8, 12); - // Copie du mot de passe généré dans le "presse-papier" de l'ordinateur : - passwordInput.select(); - document.execCommand("copy"); - addElement(passwordHelp, "div", passwordCopied, "", ["success"]); -}); - -// Test si l'e-mail saisi est déjà utilisé par un autre compte. +// Teste si l'e-mail saisi est déjà utilisé par un autre compte. // Si c'est le cas, la validation du formulaire est bloquée. -emailInput.addEventListener("focus", function(e) -{ - document.getElementById("emailMessage").innerHTML="";// pour supprimer l'éventuel message d'erreur déjà affiché -}); emailInput.addEventListener("blur", function(e) { const emailValue=emailInput.value.trim(); @@ -93,7 +72,7 @@ emailInput.addEventListener("blur", function(e) if (this.readyState == XMLHttpRequest.DONE) { let response=JSON.parse(this.responseText); - if (this.status === 200 && response.free!==undefined && response.free === false) + if (this.status === 200 && response.free !== undefined && response.free === false) { addElement(document.getElementById("emailMessage"), "div", needUniqueEmail.replace("#URL", configTemplate.connectionPage), "", ["error"]); btnSubmit.setAttribute("disabled", true); @@ -107,33 +86,10 @@ emailInput.addEventListener("blur", function(e) xhr.send(JSON.stringify(datas)); } }); - -// Vérification que le code/e-mail de parrainage saisi est valide. -codeGodfatherInput.addEventListener("focus", function(e) -{ // on efface l'éventuel message d'erreur si on revient sur le champ pour tester un autre code. - addElement(document.getElementById("codeGodfatherMessage"), "i", notRequired); -}); -codeGodfatherInput.addEventListener("blur", function(e) +// Supprime l'éventuel message d'erreur déjà injecté si l'utilisateur revient dans le champ : +emailInput.addEventListener("focus", function(e) { - const codeValue=codeGodfatherInput.value.trim(); - if(codeValue!=="") - { - const xhr = new XMLHttpRequest(); - xhr.open("POST", apiUrl+configUsers.userRoutes+configUsers.getGodfatherRoute); - xhr.onreadystatechange = function() - { - if (this.readyState == XMLHttpRequest.DONE) - { - if (this.status === 204) - addElement(document.getElementById("codeGodfatherMessage"), "div", godfatherNotFound, "", ["error"]); - else - addElement(document.getElementById("codeGodfatherMessage"), "div", godfatherFound, "", ["success"]); - } - } - xhr.setRequestHeader("Content-Type", "application/json"); - const datas={ codeTest:codeValue }; - xhr.send(JSON.stringify(datas)); - } + document.getElementById("emailMessage").innerHTML=""; }); // Traitement de l'envoi des données d'inscription : @@ -169,7 +125,7 @@ myForm.addEventListener("submit", function(e) if(datas) { datas.timeDifference=getTimeDifference(configUsers); - // si l'utilisateur a précédement répondu à un quiz, j'ajoute les infos de son résultat : + // Si l'utilisateur a précédement répondu à un quiz, j'ajoute les infos de son résultat : datas=checkAnswerDatas(datas); xhr.send(JSON.stringify(datas)); }