Ajout possibilité inscription simplifiée (uniquement email). Déplacement fonction JS générant des mots de passe dans le backend.
This commit is contained in:
parent
9f795e8b63
commit
b3312e9cf8
@ -61,6 +61,8 @@ 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
|
||||
exports.signup = async (req, res, next) =>
|
||||
{
|
||||
try
|
||||
@ -68,10 +70,24 @@ 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.length < config.passwordMinLength) // si le champ est supprimé du formulaire d'inscription, générer un mot de passe ok ici
|
||||
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!=="")
|
||||
{
|
||||
@ -79,7 +95,6 @@ exports.signup = async (req, res, next) =>
|
||||
if(godfather)
|
||||
req.body.GodfatherId=godfather.id;
|
||||
}
|
||||
req.body.password=await bcrypt.hash(req.body.password, config.bcryptSaltRounds);
|
||||
const user=await db["User"].create({ ...req.body }, { fields: ["name", "email", "password", "newsletterOk", "GodfatherId", "timeDifference"] });
|
||||
req.body.UserId=user.id;
|
||||
// si l'utilisateur a répondu à un quiz avant de créer son compte, on enregistre son résultats.
|
||||
|
@ -1,51 +1,42 @@
|
||||
// -- GESTION DU FORMULAIRE PERMETTANT DE CRÉER SON COMPTE
|
||||
// -- PAGE AFFICHANT L'ÉLÉMENT D'UN GROUPE DE QUIZ ET PROPOSANT DE CRÉER SON COMPTE DE MANIÈRE SIMPLIFIÉE
|
||||
|
||||
/// 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
|
||||
/// L'utilisateur peut avoir répondu à un quiz avant de lancer la création de son compte
|
||||
/// Dans ce cas il faut enregistrer son résultat en même temps que les informations de son compte
|
||||
|
||||
// Fichier de configuration tirés du backend :
|
||||
import { apiUrl, availableLangs, theme } from "../../config/instance.js";
|
||||
const lang=availableLangs[0];
|
||||
|
||||
const configTemplate = require("../../views/"+theme+"/config/"+lang+".js");// besoin de toutes les déclarations, car appel dynamique : configTemplate[homePage]
|
||||
const configUsers = require("../../config/users");// idem pour configurer formulaire
|
||||
|
||||
// Importation des fonctions utiles au script :
|
||||
import { getLocaly, removeLocaly, saveLocaly } from "./tools/clientstorage.js";
|
||||
import { getLocaly, removeLocaly } from "./tools/clientstorage.js";
|
||||
import { addElement } from "./tools/dom.js";
|
||||
import { helloDev } from "./tools/everywhere.js";
|
||||
import { helloDev, updateAccountLink } from "./tools/everywhere.js";
|
||||
import { getDatasFromInputs, setAttributesToInputs } from "./tools/forms.js";
|
||||
import { loadMatomo } from "./tools/matomo.js";
|
||||
import { checkAnswerDatas, checkSession, getPassword, getTimeDifference } from "./tools/users.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 { 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");
|
||||
const divResponse=document.getElementById("response");
|
||||
const emailInput=document.getElementById("email");
|
||||
const myForm=document.getElementById("subscription");
|
||||
|
||||
helloDev();
|
||||
|
||||
// Test de connexion de l'utilisateur + affichage formulaire d'inscription.
|
||||
// Test de connexion de l'utilisateur + affichage formulaire d'inscription :
|
||||
const initialise = async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
const isConnected=await checkSession();
|
||||
let isConnected=await checkSession(), user;
|
||||
if(isConnected)
|
||||
{
|
||||
//saveLocaly("message", { message: alreadyConnected, color:"info" });// pour l'afficher sur la page suivante
|
||||
//const user=getLocaly("user", true);
|
||||
//const homePage=user.status+"HomePage";
|
||||
//window.location.assign("/"+configTemplate[homePage]);
|
||||
user=getLocaly("user", true);
|
||||
updateAccountLink(user.status, configTemplate);// lien vers le compte adapté pour les utilisateurs connectés
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -61,18 +52,7 @@ const initialise = async () =>
|
||||
}
|
||||
}
|
||||
initialise();
|
||||
|
||||
// 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"]);
|
||||
});
|
||||
helloDev();
|
||||
|
||||
// Test 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.
|
||||
@ -92,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,34 +87,6 @@ emailInput.addEventListener("blur", function(e)
|
||||
}
|
||||
});
|
||||
|
||||
// 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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
});
|
||||
|
||||
// Traitement de l'envoi des données d'inscription :
|
||||
myForm.addEventListener("submit", function(e)
|
||||
{
|
||||
@ -152,11 +104,14 @@ myForm.addEventListener("submit", function(e)
|
||||
{
|
||||
myForm.style.display="none";
|
||||
addElement(divResponse, "p", response.message, "", ["success"]);
|
||||
removeLocaly("lastAnswer");// ! important pour ne pas enregister plusieurs fois le résultat.
|
||||
removeLocaly("lastAnswer");// !! important, pour ne pas enregister plusieurs fois le résultat.
|
||||
}
|
||||
else if (response.errors)
|
||||
{
|
||||
response.errors = response.errors.join("<br>");
|
||||
if(Array.isArray(response.errors))
|
||||
response.errors = response.errors.join("<br>");
|
||||
else
|
||||
response.errors = serverError;
|
||||
addElement(divResponse, "p", response.errors, "", ["error"]);
|
||||
}
|
||||
else
|
||||
@ -168,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, j'ajoute les infos 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));
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ import { getLocaly, removeLocaly } from "./tools/clientstorage.js";
|
||||
import { addElement } from "./tools/dom.js";
|
||||
import { helloDev, updateAccountLink } from "./tools/everywhere.js";
|
||||
import { empyForm, getDatasFromInputs, setAttributesToInputs } from "./tools/forms.js";
|
||||
import { dateFormat, isEmpty, replaceAll } from "../../tools/main";
|
||||
import { dateFormat, getPassword, isEmpty, replaceAll } from "../../tools/main";
|
||||
import { getUrlParams } from "./tools/url.js";
|
||||
import { checkSession, getPassword } from "./tools/users.js";
|
||||
import { checkSession } from "./tools/users.js";
|
||||
|
||||
// Dictionnaires :
|
||||
const { addOkMessage, serverError } = require("../../lang/"+lang+"/general");
|
||||
|
@ -15,8 +15,9 @@ 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, getPassword, getTimeDifference } from "./tools/users.js";
|
||||
import { checkAnswerDatas, checkSession, getTimeDifference } from "./tools/users.js";
|
||||
|
||||
// Dictionnaires :
|
||||
const { notRequired, serverError } = require("../../lang/"+lang+"/general");
|
||||
|
@ -18,25 +18,6 @@ export const getTimeDifference = () =>
|
||||
return timeLocal;
|
||||
}
|
||||
|
||||
// On enlève volontairement les 0/O pour éviter les confusions !
|
||||
// Et mieux vaut aussi débuter et finir par une lettre simple.
|
||||
export const getPassword = (nbCarMin, nbCarMax) =>
|
||||
{
|
||||
const nbCar=nbCarMin+Math.floor(Math.random()*(nbCarMax-nbCarMin));
|
||||
const letters="ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz";
|
||||
const others="123456789!?.*-_%@&ÉÀÈÙ€$ÂÊÛÎ";
|
||||
let password=letters[Math.floor(Math.random()*letters.length)];
|
||||
for(let i=1;i<(nbCar-1);i++)
|
||||
{
|
||||
if((i % 2) ===1)
|
||||
password+=others[Math.floor(Math.random()*others.length)];
|
||||
else
|
||||
password+=letters[Math.floor(Math.random()*letters.length)];
|
||||
}
|
||||
password+=letters[Math.floor(Math.random()*letters.length)];
|
||||
return password;
|
||||
}
|
||||
|
||||
// J'utilise le stockage local du navigateur pour enregistrer les données permettant de reconnaître l'utilisateur par la suite
|
||||
// Seul le serveur pourra vérifier que les identifiants sont (toujours) valides.
|
||||
export const setSession = (userId, token, durationTS) =>
|
||||
|
@ -76,6 +76,25 @@ class Tool
|
||||
else
|
||||
return myMounth+"/"+myDay+"/"+myYear;
|
||||
}
|
||||
|
||||
// On enlève volontairement les 0/O pour éviter les confusions !
|
||||
// Et mieux vaut aussi débuter et finir par une lettre simple.
|
||||
static getPassword (nbCarMin, nbCarMax)
|
||||
{
|
||||
const nbCar=nbCarMin+Math.floor(Math.random()*(nbCarMax-nbCarMin));
|
||||
const letters="ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz";
|
||||
const others="123456789!?.*-_%@&ÉÀÈÙ€$ÂÊÛÎ";
|
||||
let password=letters[Math.floor(Math.random()*letters.length)];
|
||||
for(let i=1;i<(nbCar-1);i++)
|
||||
{
|
||||
if((i % 2) ===1)
|
||||
password+=others[Math.floor(Math.random()*others.length)];
|
||||
else
|
||||
password+=letters[Math.floor(Math.random()*letters.length)];
|
||||
}
|
||||
password+=letters[Math.floor(Math.random()*letters.length)];
|
||||
return password;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Tool;
|
@ -85,7 +85,7 @@ block content
|
||||
strong #{configTpl.noJSNotification}
|
||||
- const cguOkLabel = txtUser.formsCGUOkLabel.replace("#link", "/"+configTpl.cguPage); /// remettre class="needJS" au formulaire ci-dessous
|
||||
div#quizElementSignupForm
|
||||
form(id="subscription" method="POST")
|
||||
form(id="subscription" method="POST" class="needJS")
|
||||
h3 #{configTpl.quizElementSubcriptionFormTitle}
|
||||
fieldset
|
||||
label(for="email") #{txtUser.formsEmailLabel}
|
||||
|
@ -58,7 +58,7 @@ block content
|
||||
div
|
||||
strong #{configTpl.noJSNotification}
|
||||
// à cacher si pas de JS !
|
||||
form(id="group" method="POST")
|
||||
form(id="group" method="POST" class="needJS")
|
||||
h2 #{group.Group.title}
|
||||
div#response
|
||||
div(class="subscribeBtns")
|
||||
|
Loading…
Reference in New Issue
Block a user