- Refactor ActiveEntry.sigIn method
- Add own Reset password template - Check password history and validation in Reset Password - Add expireTimeInMinute in passwordOptions to control expire time of reset link - Show sending notification while reset link is sent
This commit is contained in:
parent
7fa4c33064
commit
1e1c4033a6
@ -90,40 +90,11 @@ Template.changePassword.events({
|
||||
ActiveEntry.errorMessages.set('changePasswordError', null);
|
||||
|
||||
|
||||
if (ActiveEntry.successMessages.get('password') && ActiveEntry.successMessages.get('confirm') && oldPassword) {
|
||||
Meteor.call("checkPasswordExistence", new String(password).hashCode(), function(error, result) {
|
||||
if (error) {
|
||||
console.warn(error.message);
|
||||
ActiveEntry.errorMessages.set('changePasswordError', error.message);
|
||||
|
||||
} else {
|
||||
if (result) {
|
||||
ActiveEntry.errorMessages.set('changePasswordError', 'Password is used before. Please change your new password.');
|
||||
} else {
|
||||
ActiveEntry.errorMessages.set('changePasswordError', null);
|
||||
|
||||
// If password is not found in password history, change the password
|
||||
Accounts.changePassword(oldPassword, confirmPassword, function(error) {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
ActiveEntry.errorMessages.set('changePasswordError', error.message);
|
||||
} else {
|
||||
// Save the new password
|
||||
ActiveEntry.insertHashedPassword(confirmPassword);
|
||||
|
||||
// Update password expiration date
|
||||
ActiveEntry.updatePasswordSetDate();
|
||||
|
||||
// Logout
|
||||
ActiveEntry.signOut();
|
||||
// Go to signIn page for new entry
|
||||
Router.go('/entrySignIn');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (ActiveEntry.errorMessages.get('password') || ActiveEntry.errorMessages.get('confirm') || !oldPassword) {
|
||||
return;
|
||||
}
|
||||
|
||||
ActiveEntry.changePassword(oldPassword, password);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@ -28,45 +28,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="resetPassword">
|
||||
{{#if resetPassword}}
|
||||
<div id="resetPassword" class="page entryPage" style="{{getOpacityWithCorner}}">
|
||||
<div class="content-scrollable">
|
||||
<div class="wrapper-auth">
|
||||
<div class="entryLogo" style="background-image: url('{{getLogoUrl}}')"></div>
|
||||
|
||||
<h1 id="signInPageTitle" class="title-auth">Reset Password</h1>
|
||||
<div id="signInPageMessage" class="subtitle-auth" >Improve your clinical practice with checklists.</div>
|
||||
|
||||
<form>
|
||||
{{#if resetPasswordErrorMessages}}
|
||||
<div id="errorMessages" class="list-errors">
|
||||
{{#each resetPasswordErrorMessages}}
|
||||
<div class="alert alert-danger list-item">{{this}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="input-symbol ">
|
||||
<input id="resetPasswordInput" type="password" name="password" placeholder="Password" style="{{getPasswordStyling}}" />
|
||||
<span class="fa fa-lock" title="Password"></span>
|
||||
<!-- <span class="icon-lock" title="Password"></span> -->
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<div class="input-symbol">
|
||||
<input id="resetPasswordConfirmInput" type="password" name="confirm" placeholder="Confirm Password" style="{{getConfirmPasswordStyling}}" />
|
||||
<span class="fa fa-lock" title="Confirm Password"></span>
|
||||
<!-- <span class="icon-lock" title="Confirm Password"></span> -->
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
</form>
|
||||
<button id="resetPasswordButton" type="submit" class="btn-gray btn-main btn-large" style="{{getButtonColor}}">Reset Password</button><br><br>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
@ -5,16 +5,6 @@ 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({
|
||||
getForgotPasswordMessageColor: function (){
|
||||
if (ActiveEntry.errorMessages.get('forgotPassword')) {
|
||||
@ -37,48 +27,10 @@ Template.forgotPassword.helpers({
|
||||
Template.forgotPassword.events({
|
||||
"submit": function (event, template) {
|
||||
event.preventDefault();
|
||||
|
||||
console.log('send reminder!');
|
||||
ActiveEntry.successMessages.set("forgotPassword", "Your password reset email is sending...");
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
|
||||
<template name="resetPassword">
|
||||
{{#if resetPassword}}
|
||||
<div id="resetPassword" class="page entryPage" style="{{getOpacityWithCorner}}">
|
||||
<div class="content-scrollable">
|
||||
<div class="wrapper-auth">
|
||||
<div class="entryLogo" style="background-image: url('{{getLogoUrl}}')"></div>
|
||||
|
||||
<h1 id="signInPageTitle" class="title-auth">Reset Password</h1>
|
||||
<p id="signInPageMessage" class="subtitle-auth" style="{{getResetPasswordInMessageColor}}">{{{getResetPasswordMessage}}}</p>
|
||||
|
||||
<form>
|
||||
{{#if resetPasswordErrorMessages}}
|
||||
<div id="errorMessages" class="list-errors">
|
||||
{{#each resetPasswordErrorMessages}}
|
||||
<div class="alert alert-danger list-item">{{this}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="input-symbol ">
|
||||
<input id="resetPasswordInput" type="password" name="password" placeholder="Password" style="{{getPasswordStyling}}" />
|
||||
<span class="fa fa-lock" title="Password"></span>
|
||||
<!-- <span class="icon-lock" title="Password"></span> -->
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<div class="input-symbol">
|
||||
<input id="resetPasswordConfirmInput" type="password" name="confirm" placeholder="Confirm Password" style="{{getConfirmPasswordStyling}}" />
|
||||
<span class="fa fa-lock" title="Confirm Password"></span>
|
||||
<!-- <span class="icon-lock" title="Confirm Password"></span> -->
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
</form>
|
||||
<button id="resetPasswordButton" type="submit" class="btn-gray btn-main btn-large" style="{{getButtonColor}}">Reset Password</button><br><br>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
@ -0,0 +1,67 @@
|
||||
|
||||
Router.route('/resetPassword/:token', {
|
||||
template: 'resetPassword',
|
||||
name: 'resetPassword',
|
||||
onBeforeAction: function() {
|
||||
var token = this.params.token;
|
||||
Session.set('_resetPasswordToken', token);
|
||||
this.next();
|
||||
}
|
||||
});
|
||||
|
||||
// Reset password template
|
||||
Template.resetPassword.helpers({
|
||||
getResetPasswordInMessageColor: function (){
|
||||
if (ActiveEntry.errorMessages.get('resetPasswordError')) {
|
||||
return "color: #a94442; background-color: #f2dede; border-color: #ebccd1;"
|
||||
} else {
|
||||
return "color: black;"
|
||||
}
|
||||
},
|
||||
getResetPasswordMessage: function (){
|
||||
if (ActiveEntry.errorMessages.get('resetPasswordError')) {
|
||||
return ActiveEntry.errorMessages.get('resetPasswordError');
|
||||
} else {
|
||||
return Session.get('defaultSignInMessage');
|
||||
}
|
||||
},
|
||||
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('resetPasswordError', null);
|
||||
},
|
||||
'keyup #resetPasswordConfirmInput': function (event, template) {
|
||||
|
||||
var password = $('#resetPasswordInput').val();
|
||||
var confirmPassword = $('#resetPasswordConfirmInput').val();
|
||||
|
||||
ActiveEntry.verifyConfirmPassword(password, confirmPassword);
|
||||
ActiveEntry.errorMessages.set('resetPasswordError', null);
|
||||
},
|
||||
'click #resetPasswordButton': function(e, template) {
|
||||
e.preventDefault();
|
||||
var password = $('#resetPasswordInput').val();
|
||||
var passwordConfirm = $('#resetPasswordConfirmInput').val();
|
||||
|
||||
if (ActiveEntry.errorMessages.get('password') || ActiveEntry.errorMessages.get('confirm')) {
|
||||
return;
|
||||
}
|
||||
ActiveEntry.resetPassword(password, passwordConfirm);
|
||||
}
|
||||
});
|
||||
@ -30,7 +30,8 @@ if (Meteor.isClient) {
|
||||
passwordHistoryCount: 6,
|
||||
failedAttemptsLimit: 5,
|
||||
passwordExpirationDays: 90,
|
||||
inactivityPeriodDays: 180
|
||||
inactivityPeriodDays: 180,
|
||||
expireTimeInMinute: 30
|
||||
}
|
||||
});
|
||||
|
||||
@ -43,6 +44,7 @@ if (Meteor.isClient) {
|
||||
// Change password warning message according to whether zxcvbn is turned on
|
||||
Session.set('passwordWarning', 'Password must have at least 8 characters. It must contain at least 1 uppercase, 1 lowercase, 1 number and 1 special character.');
|
||||
|
||||
// Activate LDAP if ldap url and port is set in settings.json
|
||||
Meteor.call('isLDAPSet', function(error, isSet) {
|
||||
Session.set('isLDAPSet', isSet);
|
||||
});
|
||||
@ -65,7 +67,8 @@ ActiveEntry.configure = function (configObject) {
|
||||
passwordHistoryCount: 6,
|
||||
failedAttemptsLimit: 5,
|
||||
passwordExpirationDays: 90,
|
||||
inactivityPeriodDays: 180
|
||||
inactivityPeriodDays: 180,
|
||||
expireTimeInMinute: 30
|
||||
}
|
||||
}
|
||||
Session.set('Photonic.ActiveEntry', configObject);
|
||||
@ -151,96 +154,152 @@ ActiveEntry.signIn = function (emailValue, passwordValue){
|
||||
|
||||
ActiveEntry.verifyPassword(passwordValue);
|
||||
ActiveEntry.verifyEmail(emailValue);
|
||||
// TODO: Find a solution nested calling
|
||||
|
||||
var signInArgs = {email: emailValue, password: passwordValue};
|
||||
|
||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||
var failedAttemptsLimit = ActiveEntryConfig && ActiveEntryConfig.passwordOptions && ActiveEntryConfig.passwordOptions.failedAttemptsLimit || 5;
|
||||
var passwordExpirationDays = ActiveEntryConfig && ActiveEntryConfig.passwordOptions && ActiveEntryConfig.passwordOptions.passwordExpirationDays || 90;
|
||||
var inactivityPeriodDays = ActiveEntryConfig && ActiveEntryConfig.passwordOptions && ActiveEntryConfig.passwordOptions.inactivityPeriodDays || 180;
|
||||
var passwordOptions = ActiveEntryConfig && ActiveEntryConfig.passwordOptions;
|
||||
|
||||
Meteor.call("isAccountInactive",[emailValue,inactivityPeriodDays], function(error, isAccountInactive) {
|
||||
Meteor.call("isAccountInactive",emailValue, passwordOptions.inactivityPeriodDays, function(error, isAccountInactive) {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
console.warn(error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAccountInactive) {
|
||||
// Lock account
|
||||
ActiveEntry.lockAccount(signInArgs);
|
||||
} else {
|
||||
if (isAccountInactive) {
|
||||
// Lock account
|
||||
Meteor.call("lockAccount", emailValue);
|
||||
ActiveEntry.errorMessages.set('signInError', "Your account has been locked due to inactivity.");
|
||||
return;
|
||||
} else {
|
||||
// Check account is locked
|
||||
Meteor.call("isAccountLocked", function (error, isAccountLocked) {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
} else {
|
||||
|
||||
if (isAccountLocked) {
|
||||
ActiveEntry.errorMessages.set('signInError', "Your account has been locked.");
|
||||
return;
|
||||
}
|
||||
|
||||
Meteor.call("getFailedAttemptsCount", emailValue, function(error, failedAttemptsCount) {
|
||||
if (error) {
|
||||
console.warn(error.message);
|
||||
} else {
|
||||
if (failedAttemptsCount != failedAttemptsLimit) {
|
||||
Meteor.loginWithPassword({email: emailValue}, passwordValue, function (loginError, result) {
|
||||
if (loginError) {
|
||||
// Login failed
|
||||
Meteor.call("updateFailedAttempts", [emailValue, failedAttemptsLimit], function(error, failedAttemptCount) {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
} else {
|
||||
if (failedAttemptCount == failedAttemptsLimit) {
|
||||
ActiveEntry.errorMessages.set('signInError', "Too many failed login attempts. Your account has been locked.");
|
||||
|
||||
} else if (failedAttemptCount < failedAttemptsLimit) {
|
||||
ActiveEntry.errorMessages.set('signInError', loginError.message + "<br />" +(failedAttemptsLimit - failedAttemptCount) + " attempts remaining.");
|
||||
} else {
|
||||
ActiveEntry.errorMessages.set('signInError', loginError.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Reset failed attempts
|
||||
Meteor.call("resetFailedAttempts", emailValue);
|
||||
|
||||
// Check password expiration
|
||||
// if password expired, route to changePassword page
|
||||
Meteor.call("isPasswordExpired", passwordExpirationDays, function(error, isPasswordExpired) {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
} else {
|
||||
// Update last login time
|
||||
Meteor.call("updateLastLoginDate");
|
||||
|
||||
if (isPasswordExpired) {
|
||||
ActiveEntry.errorMessages.set('changePasswordError', 'Your password expired. Please change your password.');
|
||||
Router.go('/changePassword');
|
||||
} else {
|
||||
Router.go(ActiveEntryConfig.signIn.destination);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ActiveEntry.errorMessages.set('signInError', "Your account has been locked.");
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
// Check account is locked
|
||||
ActiveEntry.isAccountLocked(signInArgs, passwordOptions);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
ActiveEntry.lockAccount = function(signInArgs) {
|
||||
var emailValue = signInArgs && signInArgs.email;
|
||||
if (!emailValue) {
|
||||
return;
|
||||
}
|
||||
Meteor.call("lockAccount", emailValue);
|
||||
ActiveEntry.errorMessages.set('signInError', "Your account has been locked due to inactivity.");
|
||||
};
|
||||
|
||||
ActiveEntry.isAccountLocked = function(signInArgs, passwordOptions) {
|
||||
var emailValue = signInArgs && signInArgs.email;
|
||||
if (!emailValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
Meteor.call("isAccountLocked", emailValue, function (error, isAccountLocked) {
|
||||
if (error) {
|
||||
console.warn(error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAccountLocked) {
|
||||
ActiveEntry.errorMessages.set('signInError', "Your account has been locked.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get failed attempts count
|
||||
ActiveEntry.getFailedAttemptsCount(signInArgs, passwordOptions);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
ActiveEntry.getFailedAttemptsCount = function(signInArgs, passwordOptions) {
|
||||
var emailValue = signInArgs && signInArgs.email;
|
||||
if (!emailValue) {
|
||||
return;
|
||||
}
|
||||
Meteor.call("getFailedAttemptsCount", emailValue, function(error, failedAttemptsCount) {
|
||||
if (error) {
|
||||
console.warn(error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (failedAttemptsCount != passwordOptions.failedAttemptsLimit) {
|
||||
// Login with password
|
||||
ActiveEntry.loginWithPassword(signInArgs, passwordOptions);
|
||||
} else {
|
||||
ActiveEntry.errorMessages.set('signInError', "Your account has been locked.");
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
ActiveEntry.loginWithPassword = function(signInArgs, passwordOptions) {
|
||||
var emailValue = signInArgs && signInArgs.email;
|
||||
var password = signInArgs && signInArgs.password;
|
||||
|
||||
if (!emailValue || !password) {
|
||||
return;
|
||||
}
|
||||
|
||||
Meteor.loginWithPassword(emailValue, password, function (loginError, result) {
|
||||
if (loginError) {
|
||||
// Login failed
|
||||
if (loginError.error == 403) {
|
||||
ActiveEntry.updateFailedAttempts(signInArgs, passwordOptions, loginError);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset failed attempts
|
||||
Meteor.call("resetFailedAttempts", emailValue);
|
||||
|
||||
// Check password expiration
|
||||
ActiveEntry.isPasswordExpired(passwordOptions);
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
ActiveEntry.isPasswordExpired = function(passwordOptions) {
|
||||
// if password expired, route to changePassword page
|
||||
Meteor.call("isPasswordExpired", passwordOptions.passwordExpirationDays, function(error, isPasswordExpired) {
|
||||
if (error) {
|
||||
console.warn(error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update last login time
|
||||
Meteor.call("updateLastLoginDate");
|
||||
|
||||
if (isPasswordExpired) {
|
||||
ActiveEntry.errorMessages.set('changePasswordError', 'Your password expired. Please change your password.');
|
||||
Router.go('/changePassword');
|
||||
} else {
|
||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||
Router.go(ActiveEntryConfig.signIn.destination);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ActiveEntry.updateFailedAttempts = function(signInArgs, passwordOptions, loginError) {
|
||||
var emailValue = signInArgs && signInArgs.email;
|
||||
|
||||
if (!emailValue) {
|
||||
return;
|
||||
}
|
||||
Meteor.call("updateFailedAttempts", emailValue, passwordOptions.failedAttemptsLimit, function(error, failedAttemptCount) {
|
||||
if (error) {
|
||||
console.warn(error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (failedAttemptCount == passwordOptions.failedAttemptsLimit) {
|
||||
ActiveEntry.errorMessages.set('signInError', "Too many failed login attempts. Your account has been locked.");
|
||||
} else if (failedAttemptCount < passwordOptions.failedAttemptsLimit) {
|
||||
ActiveEntry.errorMessages.set('signInError', loginError.message + "<br />" +(passwordOptions.failedAttemptsLimit - failedAttemptCount) + " attempts remaining.");
|
||||
} else {
|
||||
ActiveEntry.errorMessages.set('signInError', loginError.message);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
ActiveEntry.loginWithLDAP = function(username, password) {
|
||||
ActiveEntry.verifyLDAPUsername(username);
|
||||
ActiveEntry.verifyLDAPPassword(password);
|
||||
@ -315,19 +374,56 @@ ActiveEntry.signUp = function (emailValue, passwordValue, confirmPassword, fullN
|
||||
}, function (error, result) {
|
||||
if (error) {
|
||||
ActiveEntry.errorMessages.set('signInError', error.message);
|
||||
} else {
|
||||
// Add password in previousPasswords field
|
||||
ActiveEntry.insertHashedPassword(passwordValue);
|
||||
|
||||
// Update password set date
|
||||
ActiveEntry.updatePasswordSetDate();
|
||||
|
||||
// Update last login time
|
||||
Meteor.call("updateLastLoginDate");
|
||||
|
||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||
Router.go(ActiveEntryConfig.signUp.destination);
|
||||
return;
|
||||
}
|
||||
// Add password in previousPasswords field
|
||||
ActiveEntry.insertHashedPassword(passwordValue);
|
||||
|
||||
// Update password set date
|
||||
ActiveEntry.updatePasswordSetDate();
|
||||
|
||||
// Update last login time
|
||||
Meteor.call("updateLastLoginDate");
|
||||
|
||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||
Router.go(ActiveEntryConfig.signUp.destination);
|
||||
|
||||
});
|
||||
};
|
||||
ActiveEntry.changePassword = function(oldPassword, password) {
|
||||
Meteor.call("checkPasswordExistence", new String(password).hashCode(), function(error, isPasswordExisted) {
|
||||
if (error) {
|
||||
console.warn(error.message);
|
||||
ActiveEntry.errorMessages.set('changePasswordError', error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPasswordExisted) {
|
||||
ActiveEntry.errorMessages.set('changePasswordError', 'Password is used before. Please change your new password.');
|
||||
} else {
|
||||
ActiveEntry.errorMessages.set('changePasswordError', null);
|
||||
|
||||
// If password is not found in password history, change the password
|
||||
Accounts.changePassword(oldPassword, password, function(error) {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
ActiveEntry.errorMessages.set('changePasswordError', error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the new password
|
||||
ActiveEntry.insertHashedPassword(password);
|
||||
|
||||
// Update password expiration date
|
||||
ActiveEntry.updatePasswordSetDate();
|
||||
|
||||
// Logout
|
||||
ActiveEntry.signOut();
|
||||
// Go to signIn page for new entry
|
||||
Router.go('/entrySignIn');
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@ -344,8 +440,10 @@ ActiveEntry.forgotPassword = function(emailAddress) {
|
||||
if (error) {
|
||||
console.warn(error.message);
|
||||
ActiveEntry.errorMessages.set("forgotPassword", error.message);
|
||||
ActiveEntry.successMessages.set("forgotPassword", null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show email sent notification
|
||||
ActiveEntry.successMessages.set("forgotPassword", "Your password reset email is sent to <strong>"+emailAddress+"</strong>");
|
||||
});
|
||||
@ -361,8 +459,11 @@ ActiveEntry.resetPassword = function(passwordValue, confirmPassword) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||
var passwordOptions = ActiveEntryConfig && ActiveEntryConfig.passwordOptions;
|
||||
|
||||
// Check token is expired
|
||||
Meteor.call('checkResetTokenIsExpired',Session.get('_resetPasswordToken'), function(error, isTokenExpired) {
|
||||
Meteor.call('checkResetTokenIsExpired', Session.get('_resetPasswordToken'), passwordOptions.expireTimeInMinute, function(error, isTokenExpired) {
|
||||
if (error) {
|
||||
console.log(error.message);
|
||||
return;
|
||||
@ -376,16 +477,39 @@ ActiveEntry.resetPassword = function(passwordValue, confirmPassword) {
|
||||
return;
|
||||
}
|
||||
|
||||
Accounts.resetPassword(Session.get('_resetPasswordToken'), passwordValue, function(error) {
|
||||
// Check password history
|
||||
Meteor.call("checkResetPasswordExistence", new String(passwordValue).hashCode(), Session.get('_resetPasswordToken'), function(error, isPasswordExisted) {
|
||||
if (error) {
|
||||
ActiveEntry.errorMessages.set("resetPassword", error.message);
|
||||
console.warn(error.message);
|
||||
ActiveEntry.errorMessages.set('resetPasswordError', error.message);
|
||||
return;
|
||||
}
|
||||
Session.set('_resetPasswordToken', null);
|
||||
// Update last login time
|
||||
Meteor.call("updateLastLoginDate");
|
||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||
Router.go(ActiveEntryConfig.signIn.destination);
|
||||
|
||||
if (isPasswordExisted) {
|
||||
|
||||
ActiveEntry.errorMessages.set('resetPasswordError', 'Password is used before. Please change your new password.');
|
||||
} else {
|
||||
|
||||
ActiveEntry.errorMessages.set('resetPasswordError', null);
|
||||
Accounts.resetPassword(Session.get('_resetPasswordToken'), passwordValue, function(error) {
|
||||
if (error) {
|
||||
ActiveEntry.errorMessages.set("resetPassword", error.message);
|
||||
return;
|
||||
}
|
||||
Session.set('_resetPasswordToken', null);
|
||||
// Save the new password
|
||||
ActiveEntry.insertHashedPassword(passwordValue);
|
||||
|
||||
// Update password expiration date
|
||||
ActiveEntry.updatePasswordSetDate();
|
||||
|
||||
// Update last login time
|
||||
Meteor.call("updateLastLoginDate");
|
||||
|
||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||
Router.go(ActiveEntryConfig.signIn.destination);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@ -61,7 +61,10 @@ Package.onUse(function (api) {
|
||||
|
||||
'components/changePassword/changePassword.html',
|
||||
'components/changePassword/changePassword.js',
|
||||
'components/changePassword/changePassword.less'
|
||||
'components/changePassword/changePassword.less',
|
||||
|
||||
'components/resetPassword/resetPassword.html',
|
||||
'components/resetPassword/resetPassword.js'
|
||||
], ['client']);
|
||||
|
||||
|
||||
|
||||
@ -41,7 +41,6 @@ Meteor.methods({
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
},
|
||||
|
||||
getFailedAttemptsCount: function(emailAddress) {
|
||||
@ -54,9 +53,7 @@ Meteor.methods({
|
||||
return currentUser.failedPasswordAttempts || 0;
|
||||
},
|
||||
|
||||
updateFailedAttempts: function(failedAttemptsParameters) {
|
||||
var emailAddress = failedAttemptsParameters[0];
|
||||
var failedAttemptsLimit = failedAttemptsParameters[1];
|
||||
updateFailedAttempts: function(emailAddress, failedAttemptsLimit) {
|
||||
|
||||
// Check if the user actually exists, and if not, stop here
|
||||
var currentUser = Meteor.users.findOne({"emails.address": emailAddress});
|
||||
@ -135,10 +132,7 @@ Meteor.methods({
|
||||
Meteor.users.update({_id: Meteor.userId()}, {$set: {priorLoginDate: priorLoginDate, lastLoginDate: new Date()}});
|
||||
},
|
||||
|
||||
isAccountInactive: function (inactivityParameters) {
|
||||
var emailAddress = inactivityParameters[0];
|
||||
var inactivityPeriodDays = inactivityParameters[1];
|
||||
|
||||
isAccountInactive: function (emailAddress, inactivityPeriodDays) {
|
||||
// Check if the user actually exists, and if not, stop here
|
||||
var currentUser = Meteor.users.findOne({"emails.address": emailAddress});
|
||||
if (!currentUser) {
|
||||
@ -167,7 +161,7 @@ Meteor.methods({
|
||||
return false;
|
||||
},
|
||||
|
||||
checkResetTokenIsExpired: function(token) {
|
||||
checkResetTokenIsExpired: function(token, expireTimeInMinute) {
|
||||
var user = Meteor.users.findOne({"services.password.reset.token": token});
|
||||
if (!user) {
|
||||
return;
|
||||
@ -177,7 +171,7 @@ Meteor.methods({
|
||||
return;
|
||||
}
|
||||
// Token will be expired if created time is over 30 min as default
|
||||
tokenCreatedTime.setTime(tokenCreatedTime.getTime() + 30*60000);
|
||||
tokenCreatedTime.setTime(tokenCreatedTime.getTime() + expireTimeInMinute*60000);
|
||||
if (tokenCreatedTime < new Date()) {
|
||||
// Remove reset token
|
||||
Meteor.users.update({_id: user._id}, {$unset: {'services.password.reset': 1}});
|
||||
@ -185,6 +179,24 @@ Meteor.methods({
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
checkResetPasswordExistence: function(hashedPassword, token) {
|
||||
var user = Meteor.users.findOne({"services.password.reset.token": token});
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
var previousPasswords = user.previousPasswords;
|
||||
if (!previousPasswords) {
|
||||
return;
|
||||
}
|
||||
for(var i=0; i< previousPasswords.length; i++) {
|
||||
var recordedHashedPassword = previousPasswords[i].hashedPassword;
|
||||
if (recordedHashedPassword == hashedPassword) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user