Modification page et script de création de compte pour prendre en compte simplification (uniquement e-mail + validation CGU durant première étape)

This commit is contained in:
Fabrice PENHOËT 2020-10-21 16:45:34 +02:00
parent e55f9c02bc
commit f497a05144
4 changed files with 41 additions and 114 deletions

View File

@ -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);

View File

@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Formulaire d'inscription à WikiLerni.">
<title>S'inscrire à WikiLerni</title>
<title>Créer son compte WikiLerni</title>
<!-- Version lisible des scripts : https://gitlab.com/lefablab/wikilerni/-/tree/master/front/src -->
<script src="/JS/polyfill.app.js" defer></script>
<script src="/JS/subscribe.app.js" defer></script>
@ -36,47 +36,29 @@
<h1 class="cardboard">Créer votre compte WIKILERNI</h1>
<noscript>Désolé, mais pour l'instant, l'utilisation de WikiLerni nécessite l'activation du JavaScript.</noscript>
<form class="needJS" id="subscription" method="POST">
<fieldset>
<label for="name">Nom ou pseudonyme : </label><input id="name" type="text" name="name" placeholder="Nom de votre choix" class="cardboard" >
</fieldset>
<form class="needJS" id="subscription" method="POST">
<fieldset>
<label for="email">E-mail : </label><input id="email" type="email" name="email" placeholder="Adresse e-mail" class="cardboard">
<div id="emailMessage"></div>
</fieldset>
<fieldset>
<label for="password">Mot de passe : </label><input id="password" type="password" name="password" placeholder="Mot de passe de votre choix" class="cardboard">
<div id="passwordMessage"><span class="info">Au moins 8 caractères. <a href="#password" id="getPassword">Générer un mot de passe</a>.</span></div>
</fieldset>
<fieldset>
<label for="codeGodfather">Code ou e-mail parrain : </label><input id="codeGodfather" type="text" name="codeGodfather" placeholder="Code ou email de votre parrain." class="cardboard">
<div id="codeGodfatherMessage"><span class="info">Facultatif.</span></div>
</fieldset>
<ul class="checkbox_li">
<li class="checkbox_li">
<label for="cguOk" class="check"><input type="checkbox" id="cguOk" name="cguOk" value="true" /><div class="checkbox_override"></div> J'accepte <a href="/CGV-CGU.html" target="_blank" rel="noopener" title="À lire :)">les Conditions Générale d'Utilisation</a> du site (requis).</label>
</li>
<li class="checkbox_li">
<label for="newsletterOk" class="check"><input type="checkbox" id="newsletterOk" name="newsletterOk" value="true" /><div class="checkbox_override"></div> Je souhaite recevoir des suggestions de quiz par e-mail (facultatif et vous pourrez stopper facilement).</label>
<label for="cguOk" class="check"><input type="checkbox" id="cguOk" name="cguOk" value="true" /><div class="checkbox_override"></div> J'accepte <a href="/CGV-CGU.html" target="_blank" rel="noopener" title="À lire :)">les Conditions Générale d'Utilisation</a> du site.</label>
</li>
</ul>
<div class="input_wrapper">
<input id="submitDatas" type="submit" value="Valider." class="cardboard" />
<input id="submitDatas" type="submit" value="Valider" class="cardboard" />
</div>
</form>
<div id="response"></div>
<div id="explanations" class="framed engraved">
<h2>Besoin d'aide ?</h2>
<p>La saisie d'un pseudonyme, d'une adresse e-mail et d'un mot de passe <b>est obligatoire</b> et <b>vous devez accepter les Conditions Générales d'Utilisation</b>.</p>
<p>Votre pseudonyme est complétement libre, mais servira à personnaliser certains affichages.</p>
<p>Votre compte vous permettra de <b>recevoir régulièrement de nouvelles "graines de culture" directement sur votre adresse e-mail</b>. Vous pourrez aussi sauvegarder vos résultats aux quizs.</p>
<p>La saisie d'une adresse e-mail <b>est obligatoire</b> et <b>vous devez accepter les Conditions Générales d'Utilisation</b>.</p>
<p><b>Vous recevrez un lien sur l'adresse e-mail saisie</b> sur lequel vous devrez cliquer pour valider la création de votre compte.</p>
<p><b>Votre mot de passe doit compter au moins 8 caractères.</b> Si vous manquez d'inspiration, cliquez sur le lien "Générer un mot de passe" pour en obtenir un.</p>
<p>Si vous connaissez une personne déjà inscrite à WikiLerni, <b>vous pouvez fournir son code parrain ou encore son adresse e-mail</b>. Dans le cas où vous optez ensuite pour un abonnement prémium, il sera alors allongé de 30 jours grâce à ce parrainage.</p>
<p>Une fois cliqué sur ce lien, <b>vous serez invité à compléter vos informations (pseudo, mot de passe...) ou encore à désigner votre "parrain"</b> (si c'est le cas).</p>
<p>La création de votre compte est <b>gratuite et sans engagement</b>. Elle vous permet de tester WikiLerni durant une période de 15 jours. Libre à vous ensuite de vous abonner ou pas.</p>
</div>
</div>

View File

@ -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));
}

View File

@ -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));
}