diff --git a/properties/messages.json b/properties/messages.json index 9ce508e..e8b4451 100644 --- a/properties/messages.json +++ b/properties/messages.json @@ -24,7 +24,18 @@ }, "random_code": { "name": "One time password", - "description": "Method to generate random codes valid for some time" + "description": "Method to generate random codes valid for some time", + "verify_code": { + "sms": { + "pre": "A code has been sent to you by SMS to the number", + "post": "Please enter the code received to validate this number" + }, + "mail": { + "pre": "A code has been sent to you by email to the address", + "post": "Please enter the code received to validate this email address" + }, + "wrong": "Incorrect code." + } }, "random_code_mail": { "name": "One time password by mail", diff --git a/properties/messages_en.json b/properties/messages_en.json index 897a3a7..4f29685 100644 --- a/properties/messages_en.json +++ b/properties/messages_en.json @@ -24,7 +24,18 @@ }, "random_code": { "name": "One time password", - "description": "Method to generate random codes valid for some time" + "description": "Method to generate random codes valid for some time", + "verify_code": { + "sms": { + "pre": "A code has been sent to you by SMS to the number", + "post": "Please enter the code received to validate this number" + }, + "mail": { + "pre": "A code has been sent to you by email to the address", + "post": "Please enter the code received to validate this email address" + }, + "wrong": "Incorrect code." + } }, "random_code_mail": { "name": "One time password by mail", diff --git a/properties/messages_fr.json b/properties/messages_fr.json index 1390731..d7b93b6 100644 --- a/properties/messages_fr.json +++ b/properties/messages_fr.json @@ -24,7 +24,18 @@ }, "random_code": { "name": "Code par SMS", - "description": "Méthode permettant de s'authentifier à partir d'un code aléatoire à usage unique envoyé par SMS." + "description": "Méthode permettant de s'authentifier à partir d'un code aléatoire à usage unique envoyé par SMS.", + "verify_code": { + "sms": { + "pre": "Un code vous a été envoyé par SMS au numéro", + "post": "Veuillez indiquer le code reçu pour valider ce numéro" + }, + "mail": { + "pre": "Un code vous a été envoyé par email à l'adresse", + "post": "Veuillez indiquer le code reçu pour valider cette adresse email" + }, + "wrong": "Code incorrect." + } }, "random_code_mail": { "name": "Code par Courriel", diff --git a/public/javascripts/app.js b/public/javascripts/app.js index 07f2c4c..0eface3 100644 --- a/public/javascripts/app.js +++ b/public/javascripts/app.js @@ -140,26 +140,55 @@ const RandomCodeMethod = Vue.extend({ if (transport == 'sms') reg = new RegExp("^0[6-7]([-. ]?[0-9]{2}){4}$"); else reg = new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/); if (reg.test(new_transport)) { - var oldTransport = this.user.transports[transport]; - this.user.transports[transport]= new_transport; - document.getElementById(transport + '-input').value = ''; $.ajax({ - method: 'PUT', - url: this.formatApiUrl('transport/' + transport + '/' + new_transport), + method: 'GET', + url: this.formatApiUrl('transport/' + transport + '/' + new_transport + "/test"), dataType: 'json', cache: false, success: function(data) { if (data.code != "Ok") { - this.user.transports[transport]= oldTransport; - document.getElementById(transport + '-input').value = oldTransport; Materialize.toast('Erreur interne, veuillez réessayer plus tard.', 3000, 'red darken-1'); - }else Materialize.toast('Transport vérifié', 3000, 'green darken-1'); + }else { + const expected = data.otp; + + const verifyCodeMessages = this.messages.api.methods.random_code.verify_code; + + const defaultPromptMessage = verifyCodeMessages[transport].pre + " " + new_transport + ". " + verifyCodeMessages[transport].post; + + const verifyRandomCode = promptMessage => { + const input = prompt(promptMessage); // plutôt utiliser modal + input ? + if (input == expected) { // if good code + $.ajax({ + method: 'PUT', + url: this.formatApiUrl('transport/' + transport + '/' + new_transport), + dataType: 'json', + cache: false, + success: function(data) { + if (data.code != "Ok") { + Materialize.toast('Erreur interne, veuillez réessayer plus tard.', 3000, 'red darken-1'); + } else { + // equivalent to "this.user.transports[transport] = new_transport;", but allows new reactive property to be added dynamically + Vue.set(this.user.transports, transport, new_transport); + document.getElementById(transport + '-input').value = ''; + Materialize.toast('Transport vérifié', 3000, 'green darken-1'); + } + }.bind(this), + error: function(xhr, status, err) { + Materialize.toast(err, 3000, 'red darken-1'); + console.error('/api/transport/' + transport + '/' + new_transport, status, err.toString()); + }.bind(this) + }); + } else if (input !== null) { // if wrong code + verifyRandomCode(verifyCodeMessages.wrong + " " + defaultPromptMessage); + } + } + + verifyRandomCode(defaultPromptMessage); + } }.bind(this), error: function(xhr, status, err) { - this.user.transports[transport]= oldTransport; - document.getElementById(transport + '-input').value = oldTransport; Materialize.toast(err, 3000, 'red darken-1'); - console.error('/api/transport/' + transport + '/' + new_transport, status, err.toString()); + console.error('/api/transport/' + transport + '/' + new_transport + "/test", status, err.toString()); }.bind(this) }); }else Materialize.toast('Format invalide.', 3000, 'red darken-1'); diff --git a/server/routes.js b/server/routes.js index f1869b7..d87c4f8 100644 --- a/server/routes.js +++ b/server/routes.js @@ -222,6 +222,20 @@ function routing() { }); }); + router.get('/api/transport/:transport/:new_transport/test', isUser, function(req, res) { + request_otp_api(req, res, { + method: 'GET', + relUrl: 'users/' + req.session.passport.user.uid + '/transports/' + req.params.transport + '/' + req.params.new_transport + '/test/' + getHash(req), + }); + }); + + router.get('/api/admin/transport/:transport/:new_transport/test/:uid', isManager, function(req, res) { + request_otp_api(req, res, { + method: 'GET', + relUrl: 'protected/users/' + req.params.uid + '/transports/' + req.params.transport + '/' + req.params.new_transport + '/test', bearerAuth: true, + }); + }); + router.delete('/api/transport/:transport/', isUser, function(req, res) { request_otp_api(req, res, { method: 'DELETE',