From a5d4c6d0eb054841db6bdb8c80699766bd96139c Mon Sep 17 00:00:00 2001 From: Aysel Afsar Date: Wed, 16 Mar 2016 10:28:07 -0400 Subject: [PATCH] LT-102: Send a email which includes password reset link if Forgot Password option is selected - Add custom Reset Password template and reset password - Show the first error instead showing all errors of invalidated input values in Sign Up and changePassword templates --- LesionTracker/server/email.js | 26 +++++-- .../changePassword/changePassword.html | 4 +- .../changePassword/changePassword.js | 19 +++-- .../components/entrySignUp/entrySignUp.js | 17 +++-- .../forgotPassword/forgotPassword.html | 50 ++++++++++++- .../forgotPassword/forgotPassword.js | 70 +++++++++++++++++-- Packages/active-entry/lib/ActiveEntry.js | 41 +++++++++++ .../components/activeEntry/activeEntry.styl | 4 +- 8 files changed, 205 insertions(+), 26 deletions(-) diff --git a/LesionTracker/server/email.js b/LesionTracker/server/email.js index afbc6dbde..535ce5549 100644 --- a/LesionTracker/server/email.js +++ b/LesionTracker/server/email.js @@ -6,10 +6,11 @@ Meteor.startup(function () { var server = Meteor.settings && Meteor.settings.mailServerSettings && Meteor.settings.mailServerSettings.server || null; var port = Meteor.settings && Meteor.settings.mailServerSettings && Meteor.settings.mailServerSettings.port || null; var verifyEmail = Meteor.settings && Meteor.settings.public && Meteor.settings.public.verifyEmail || false; + var siteName = Meteor.settings && Meteor.settings.public && Meteor.settings.public.siteName || "Lesion Tracker"; - if (verifyEmail && username && password && server && port) { - Accounts.emailTemplates.siteName = 'Lesion Tracker'; - Accounts.emailTemplates.from = 'Lesion Tracker Admin <'+username+'>'; + if (username && password && server && port) { + Accounts.emailTemplates.siteName = siteName; + Accounts.emailTemplates.from = siteName+' Admin <'+username+'>'; process.env.MAIL_URL = 'smtp://' + encodeURIComponent(username) + ':' + @@ -18,7 +19,7 @@ Meteor.startup(function () { // Subject line of the email. Accounts.emailTemplates.verifyEmail.subject = function(user) { - return 'Confirm Your Email Address for Lesion Tracker'; + return 'Confirm Your Email Address for '+siteName; }; // Email text @@ -26,9 +27,24 @@ Meteor.startup(function () { return 'Thank you for registering. Please click on the following link to verify your email address: \r\n' + url; }; + // Reset password mail + Accounts.emailTemplates.resetPassword.subject = function() { + return 'Reset your '+siteName+' password' + }; + + Accounts.urls.resetPassword = function(token) { + return Meteor.absoluteUrl('resetPassword/' + token); + }; + + Accounts.emailTemplates.resetPassword.text = function(user, url) { + return "Hello " + user.profile.fullName + ",\n\n" + + "Click the following link to set your new password:\n" + + url + "\n\n"; + }; + // Send email when account is created Accounts.config({ - sendVerificationEmail: true + sendVerificationEmail: verifyEmail }); } }); \ No newline at end of file diff --git a/Packages/active-entry/components/changePassword/changePassword.html b/Packages/active-entry/components/changePassword/changePassword.html index f6c4c805f..c7ef947f6 100755 --- a/Packages/active-entry/components/changePassword/changePassword.html +++ b/Packages/active-entry/components/changePassword/changePassword.html @@ -8,9 +8,9 @@
{{getChangePasswordMessage}}
- {{#if entryErrorMessages}} + {{#if changePasswordErrorMessages}}
- {{#each entryErrorMessages}} + {{#each changePasswordErrorMessages}}
{{this}}
{{/each}}
diff --git a/Packages/active-entry/components/changePassword/changePassword.js b/Packages/active-entry/components/changePassword/changePassword.js index bbe87240a..edbc30897 100755 --- a/Packages/active-entry/components/changePassword/changePassword.js +++ b/Packages/active-entry/components/changePassword/changePassword.js @@ -46,14 +46,19 @@ Template.changePassword.helpers({ } }, - entryErrorMessages: function() { - var errorMessages = []; - Object.keys(ActiveEntry.errorMessages.all()).forEach(function(key) { - if ((key === "password" || key === "confirm") && ActiveEntry.errorMessages.get(key)) { - errorMessages.push(ActiveEntry.errorMessages.get(key)); - } + changePasswordErrorMessages: function() { + var allErrorMessages = Object.keys(ActiveEntry.errorMessages.all()).filter(function(key) { + return (key === "password" || key === "confirm") && ActiveEntry.errorMessages.get(key); }); - return errorMessages; + + if (allErrorMessages.length > 0) { + var errorMessage = ActiveEntry.errorMessages.get(allErrorMessages[0]); + if (errorMessage) { + return [errorMessage]; + } + } + + return; } }); diff --git a/Packages/active-entry/components/entrySignUp/entrySignUp.js b/Packages/active-entry/components/entrySignUp/entrySignUp.js index 0bdddb3a4..69866adfb 100755 --- a/Packages/active-entry/components/entrySignUp/entrySignUp.js +++ b/Packages/active-entry/components/entrySignUp/entrySignUp.js @@ -30,13 +30,18 @@ Template.entrySignUp.helpers({ } }, entryErrorMessages: function () { - var errorMessages = []; - Object.keys(ActiveEntry.errorMessages.all()).forEach(function(key) { - if (key !== "signInError" && ActiveEntry.errorMessages.get(key)) { - errorMessages.push(ActiveEntry.errorMessages.get(key)); - } + var allErrorMessages = Object.keys(ActiveEntry.errorMessages.all()).filter(function(key) { + return key !== "signInError" && ActiveEntry.errorMessages.get(key); }); - return errorMessages; + + if (allErrorMessages.length > 0) { + var errorMessage = ActiveEntry.errorMessages.get(allErrorMessages[0]); + if (errorMessage) { + return [errorMessage]; + } + } + + return; }, getButtonText: function () { if (ActiveEntry.errorMessages.get('signInError')) { diff --git a/Packages/active-entry/components/forgotPassword/forgotPassword.html b/Packages/active-entry/components/forgotPassword/forgotPassword.html index 8a77f6c92..66096207b 100755 --- a/Packages/active-entry/components/forgotPassword/forgotPassword.html +++ b/Packages/active-entry/components/forgotPassword/forgotPassword.html @@ -5,7 +5,8 @@

Forgot Password

-
Imdivrove your clincal practice with checklists.
+
Improve your clinical practice with checklists.
+

{{{getForgotPasswordMessage}}}

@@ -15,6 +16,11 @@



+ {{#if forgotPasswordNotification}} +
+ {{{forgotPasswordNotification}}} +
+ {{/if}}
@@ -22,3 +28,45 @@ + + diff --git a/Packages/active-entry/components/forgotPassword/forgotPassword.js b/Packages/active-entry/components/forgotPassword/forgotPassword.js index b39444fa4..41846f206 100755 --- a/Packages/active-entry/components/forgotPassword/forgotPassword.js +++ b/Packages/active-entry/components/forgotPassword/forgotPassword.js @@ -5,11 +5,33 @@ Router.route('/forgotPassword', { template: "forgotPassword" }); +Router.route('/resetPassword/:token', { + template: 'resetPassword', + name: 'resetPassword', + onBeforeAction: function() { + var token = this.params.token; + Session.set('_resetPasswordToken', token); + this.next(); + } +}); Template.forgotPassword.helpers({ - getForgotPasswordStyle: function (){ - return "border: 1px solid gray"; - } + getForgotPasswordMessageColor: function (){ + if (ActiveEntry.errorMessages.get('forgotPassword')) { + return "color: #a94442; background-color: #f2dede; border-color: #ebccd1;" + } else { + return "color: black;" + } + }, + getForgotPasswordMessage: function (){ + return ActiveEntry.errorMessages.get('forgotPassword'); + }, + getForgotPasswordStyle: function (){ + return "border: 1px solid gray"; + }, + forgotPasswordNotification: function() { + return ActiveEntry.successMessages.get("forgotPassword"); + } }); Template.forgotPassword.events({ @@ -17,6 +39,46 @@ Template.forgotPassword.events({ event.preventDefault(); console.log('send reminder!'); - Accounts.forgotPassword({email: $('#signInPageEmailInput').val()}); + var emailAddress = $('#signInPageEmailInput').val(); + ActiveEntry.forgotPassword(emailAddress); } }); + +// Reset password template +Template.resetPassword.helpers({ + resetPassword: function(){ + return Session.get('_resetPasswordToken'); + }, + resetPasswordErrorMessages: function() { + if (ActiveEntry.errorMessages.get("password")) { + return [ActiveEntry.errorMessages.get("password")]; + } + if (ActiveEntry.errorMessages.get("confirm")) { + return [ActiveEntry.errorMessages.get("confirm")]; + } + + return; + } +}); + +Template.resetPassword.events({ + 'keyup #resetPasswordInput': function (event, template) { + var password = $('#resetPasswordInput').val(); + ActiveEntry.verifyPassword(password); + ActiveEntry.errorMessages.set('forgotPassword', null); + }, + 'keyup #resetPasswordConfirmInput': function (event, template) { + + var password = $('#resetPasswordInput').val(); + var confirmPassword = $('#resetPasswordConfirmInput').val(); + + ActiveEntry.verifyConfirmPassword(password, confirmPassword); + ActiveEntry.errorMessages.set('forgotPassword', null); + }, + 'click #resetPasswordButton': function(e, template) { + e.preventDefault(); + var password = $('#resetPasswordInput').val(); + var passwordConfirm = $('#resetPasswordConfirmInput').val(); + ActiveEntry.resetPassword(password, passwordConfirm); + } +}); diff --git a/Packages/active-entry/lib/ActiveEntry.js b/Packages/active-entry/lib/ActiveEntry.js index d4e5434c7..714d4e4cd 100755 --- a/Packages/active-entry/lib/ActiveEntry.js +++ b/Packages/active-entry/lib/ActiveEntry.js @@ -263,6 +263,47 @@ ActiveEntry.signUp = function (emailValue, passwordValue, confirmPassword, fullN }); }; +ActiveEntry.forgotPassword = function(emailAddress) { + ActiveEntry.verifyEmail(emailAddress); + ActiveEntry.errorMessages.set("forgotPassword", null); + ActiveEntry.successMessages.set("forgotPassword", null); + + if (ActiveEntry.errorMessages.get("email")) { + return; + } + + Accounts.forgotPassword({email:emailAddress }, function(error){ + if (error) { + console.warn(error.message); + ActiveEntry.errorMessages.set("forgotPassword", error.message); + return; + } + // Show email sent notification + ActiveEntry.successMessages.set("forgotPassword", "Your password reset email is sent to "+emailAddress+""); + }); +}; + +ActiveEntry.resetPassword = function(passwordValue, confirmPassword) { + ActiveEntry.verifyPassword(passwordValue); + ActiveEntry.verifyConfirmPassword(passwordValue, confirmPassword); + ActiveEntry.errorMessages.set("resetPassword", null); + + // Check error messages + if (ActiveEntry.errorMessages.get("password") || ActiveEntry.errorMessages.get("confirm")) { + return; + } + + Accounts.resetPassword(Session.get('_resetPasswordToken'), passwordValue, function(error) { + if (error) { + ActiveEntry.errorMessages.set("resetPassword", error.message); + return; + } + Session.set('_resetPasswordToken', null); + var ActiveEntryConfig = Session.get('Photonic.ActiveEntry'); + Router.go(ActiveEntryConfig.signIn.destination); + }); +}; + // Insert hashed password in previousPasswords fields ActiveEntry.insertHashedPassword = function(passwordValue) { var ActiveEntryConfig = Session.get('Photonic.ActiveEntry'); diff --git a/Packages/lesiontracker/client/components/activeEntry/activeEntry.styl b/Packages/lesiontracker/client/components/activeEntry/activeEntry.styl index c64163c85..772350931 100644 --- a/Packages/lesiontracker/client/components/activeEntry/activeEntry.styl +++ b/Packages/lesiontracker/client/components/activeEntry/activeEntry.styl @@ -1,6 +1,8 @@ #entrySignIn.entryPage, #entrySignUp.entryPage, -#changePassword +#changePassword, +#forgotPassword, +#resetPassword .wrapper-auth .title-auth color: white