Password wizard wip

This commit is contained in:
Mo Bitar
2020-02-13 13:41:00 -06:00
parent 7a587a275d
commit 6fc53f3920
4 changed files with 277 additions and 249 deletions

View File

@@ -1,6 +1,5 @@
import template from '%/directives/password-wizard.pug'; import template from '%/directives/password-wizard.pug';
import { STRING_FAILED_PASSWORD_CHANGE } from '@/strings'; import { PureCtrl } from '@Controllers';
import { isNullOrUndefined } from '../../utils';
const DEFAULT_CONTINUE_TITLE = "Continue"; const DEFAULT_CONTINUE_TITLE = "Continue";
const Steps = { const Steps = {
@@ -8,13 +7,16 @@ const Steps = {
FinishStep: 5 FinishStep: 5
}; };
class PasswordWizardCtrl { class PasswordWizardCtrl extends PureCtrl {
/* @ngInject */ /* @ngInject */
constructor( constructor(
$element, $element,
$scope, $scope,
$timeout $timeout,
application,
appState
) { ) {
super($scope, $timeout, application, appState);
this.$element = $element; this.$element = $element;
this.$timeout = $timeout; this.$timeout = $timeout;
this.$scope = $scope; this.$scope = $scope;
@@ -22,20 +24,17 @@ class PasswordWizardCtrl {
} }
$onInit() { $onInit() {
this.formData = {}; this.initProps({
this.configureDefaults(); type: this.type,
} changePassword: this.props.type === 'change-pw',
securityUpdate: this.props.type === 'upgrade-security'
configureDefaults() { });
if (this.type === 'change-pw') { this.setState({
this.title = "Change Password"; formData: {},
this.changePassword = true; continueTitle: DEFAULT_CONTINUE_TITLE,
} else if (this.type === 'upgrade-security') { step: Steps.PasswordStep,
this.title = "Account Update"; title: this.props.changePassword ? 'Change Password' : 'Account Update'
this.securityUpdate = true; });
}
this.continueTitle = DEFAULT_CONTINUE_TITLE;
this.step = Steps.IntroStep;
} }
/** Confirms with user before closing tab */ /** Confirms with user before closing tab */
@@ -51,7 +50,7 @@ class PasswordWizardCtrl {
titleForStep(step) { titleForStep(step) {
switch (step) { switch (step) {
case Steps.PasswordStep: case Steps.PasswordStep:
return this.changePassword return this.props.changePassword
? "Password information" ? "Password information"
: "Enter your current password"; : "Enter your current password";
case Steps.FinishStep: case Steps.FinishStep:
@@ -62,7 +61,7 @@ class PasswordWizardCtrl {
} }
async nextStep() { async nextStep() {
if (this.lockContinue || this.isContinuing) { if (this.state.lockContinue || this.isContinuing) {
return; return;
} }
this.isContinuing = true; this.isContinuing = true;
@@ -70,32 +69,24 @@ class PasswordWizardCtrl {
this.dismiss(); this.dismiss();
return; return;
} }
const next = () => { if(this.step === Steps.PasswordStep) {
this.step++; this.setState({
this.initializeStep(this.step); showSpinner: true,
this.isContinuing = false; continueTitle: "Generating Keys..."
};
const preprocessor = this.preprocessorForStep(this.step);
if (preprocessor) {
await preprocessor().then(next).catch(() => {
this.isContinuing = false;
}); });
} else { const success = await this.validateCurrentPassword();
next(); this.setState({
} showSpinner: false,
} continueTitle: DEFAULT_CONTINUE_TITLE
});
preprocessorForStep(step) { if(!success) {
if (step === Steps.PasswordStep) { return;
return async () => { }
this.showSpinner = true; this.isContinuing = false;
this.continueTitle = "Generating Keys...";
const success = await this.validateCurrentPassword();
this.showSpinner = false;
this.continueTitle = DEFAULT_CONTINUE_TITLE;
return success;
};
} }
this.step++;
this.initializeStep(this.step);
this.isContinuing = false;
} }
async initializeStep(step) { async initializeStep(step) {
@@ -104,46 +95,66 @@ class PasswordWizardCtrl {
} }
} }
async setFormDataState(formData) {
return this.setState({
formData: {
...this.state.formData,
...formData
}
});
}
async initializeSyncingStep() { async initializeSyncingStep() {
this.lockContinue = true; this.setState({
this.formData.status = "Processing encryption keys..."; lockContinue: true,
this.formData.processing = true; processing: true
});
this.setFormDataState({
status: "Processing encryption keys..."
});
const passwordSuccess = await this.processPasswordChange(); const passwordSuccess = await this.processPasswordChange();
this.formData.statusError = !passwordSuccess; this.setFormDataState({
this.formData.processing = passwordSuccess; statusError: !passwordSuccess,
processing: passwordSuccess
});
if (!passwordSuccess) { if (!passwordSuccess) {
this.formData.status = "Unable to process your password. Please try again."; this.setFormDataState({
status: "Unable to process your password. Please try again."
});
return; return;
} }
this.lockContinue = false; this.setState({
if (this.changePassword) { lockContinue: false,
this.formData.status = "Successfully changed password."; formData: {
} else if (this.securityUpdate) { ...this.state.formData,
this.formData.status = "Successfully performed account update."; status: this.props.changePassword
} ? "Successfully changed password."
: "Successfully performed account update."
}
});
} }
async validateCurrentPassword() { async validateCurrentPassword() {
const currentPassword = this.formData.currentPassword; const currentPassword = this.state.formData.currentPassword;
const newPass = this.securityUpdate ? currentPassword : this.formData.newPassword; const newPass = this.props.securityUpdate ? currentPassword : this.state.formData.newPassword;
if (!currentPassword || currentPassword.length === 0) { if (!currentPassword || currentPassword.length === 0) {
this.application.alertManager.alert({ this.application.alertManager.alert({
text: "Please enter your current password." text: "Please enter your current password."
}); });
return false; return false;
} }
if (this.changePassword) { if (this.props.changePassword) {
if (!newPass || newPass.length === 0) { if (!newPass || newPass.length === 0) {
this.application.alertManager.alert({ this.application.alertManager.alert({
text: "Please enter a new password." text: "Please enter a new password."
}); });
return false; return false;
} }
if (newPass !== this.formData.newPasswordConfirmation) { if (newPass !== this.state.formData.newPasswordConfirmation) {
this.application.alertManager.alert({ this.application.alertManager.alert({
text: "Your new password does not match its confirmation." text: "Your new password does not match its confirmation."
}); });
this.formData.status = null; this.state.formData.status = null;
return false; return false;
} }
} }
@@ -151,32 +162,30 @@ class PasswordWizardCtrl {
this.application.alertManager.alert({ this.application.alertManager.alert({
text: "We don't have your email stored. Please log out then log back in to fix this issue." text: "We don't have your email stored. Please log out then log back in to fix this issue."
}); });
this.formData.status = null; this.state.formData.status = null;
return false; return false;
} }
/** Validate current password */ /** Validate current password */
const key = await this.application.validateAccountPassword({ const success = await this.application.validateAccountPassword({
password: this.formData.currentPassword password: this.state.formData.currentPassword
}); });
if (key) { if (!success) {
this.currentServerPassword = key.serverPassword;
} else {
this.application.alertManager.alert({ this.application.alertManager.alert({
text: "The current password you entered is not correct. Please try again." text: "The current password you entered is not correct. Please try again."
}); });
} }
return !isNullOrUndefined(key); return success;
} }
async processPasswordChange() { async processPasswordChange() {
const newPassword = this.securityUpdate const newPassword = this.props.securityUpdate
? this.formData.currentPassword ? this.state.formData.currentPassword
: this.formData.newPassword; : this.state.formData.newPassword;
const response = await this.application.changePassword({ const response = await this.application.changePassword({
email: this.application.getUser().email, email: this.application.getUser().email,
currentPassword: this.formData.currentPassword, currentPassword: this.state.formData.currentPassword,
newPassword: newPassword newPassword: newPassword
}); });
if (response.error) { if (response.error) {
@@ -192,7 +201,7 @@ class PasswordWizardCtrl {
} }
dismiss() { dismiss() {
if (this.lockContinue) { if (this.state.lockContinue) {
this.application.alertManager.alert({ this.application.alertManager.alert({
text: "Cannot close window until pending tasks are complete." text: "Cannot close window until pending tasks are complete."
}); });

View File

@@ -5,36 +5,36 @@
.sn-component .sn-component
.sk-panel .sk-panel
.sk-panel-header .sk-panel-header
.sk-panel-header-title {{ctrl.title}} .sk-panel-header-title {{ctrl.state.title}}
a.sk-a.info.close-button(ng-click='ctrl.dismiss()') Close a.sk-a.info.close-button(ng-click='ctrl.dismiss()') Close
.sk-panel-content .sk-panel-content
div(ng-if='ctrl.step == 3') div(ng-if='ctrl.state.step == 3')
.sk-panel-row .sk-panel-row
.sk-panel-column.stretch .sk-panel-column.stretch
form.sk-panel-form form.sk-panel-form
input.sk-input.contrast( input.sk-input.contrast(
ng-model='ctrl.formData.currentPassword', ng-model='ctrl.state.formData.currentPassword',
placeholder='Current Password', placeholder='Current Password',
should-focus='true', should-focus='true',
sn-autofocus='true', sn-autofocus='true',
type='password' type='password'
) )
input.sk-input.contrast( input.sk-input.contrast(
ng-if='ctrl.changePassword', ng-if='ctrl.props.changePassword',
ng-model='ctrl.formData.newPassword', ng-model='ctrl.state.formData.newPassword',
placeholder='New Password', placeholder='New Password',
type='password' type='password'
) )
input.sk-input.contrast( input.sk-input.contrast(
ng-if='ctrl.changePassword', ng-if='ctrl.props.changePassword',
ng-model='ctrl.formData.newPasswordConfirmation', ng-model='ctrl.state.formData.newPasswordConfirmation',
placeholder='Confirm New Password', placeholder='Confirm New Password',
type='password' type='password'
) )
div(ng-if='ctrl.step == 5') div(ng-if='ctrl.state.step == 5')
div(ng-if='ctrl.changePassword') div(ng-if='ctrl.props.changePassword')
p.sk-p.sk-panel-row.info-i Your password has been successfully changed. p.sk-p.sk-panel-row.info-i Your password has been successfully changed.
div(ng-if='ctrl.securityUpdate') div(ng-if='ctrl.props.securityUpdate')
p.sk-p.sk-panel-row.info-i p.sk-p.sk-panel-row.info-i
| The account update has been successfully applied to your account. | The account update has been successfully applied to your account.
p.sk-p.sk-panel-row p.sk-p.sk-panel-row
@@ -43,8 +43,8 @@
.sk-panel-footer .sk-panel-footer
.empty .empty
a.sk-a.info.right( a.sk-a.info.right(
ng-class="{'disabled' : ctrl.lockContinue}", ng-class="{'disabled' : ctrl.state.lockContinue}",
ng-click='ctrl.nextStep()', ng-click='ctrl.nextStep()',
ng-disabled='ctrl.lockContinue') ng-disabled='ctrl.state.lockContinue')
.sk-spinner.small.inline.info.mr-5(ng-if='ctrl.showSpinner') .sk-spinner.small.inline.info.mr-5(ng-if='ctrl.state.showSpinner')
| {{ctrl.continueTitle}} | {{ctrl.state.continueTitle}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long