[Major] Implemented password change request

This commit is contained in:
Robert von Burg 2021-02-23 12:40:10 +01:00
parent 0ac8e74fad
commit 7f729b2896
3 changed files with 83 additions and 62 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "strolch-wc-auth", "name": "strolch-wc-auth",
"description": "Strolch WebComponent Auth", "description": "Strolch WebComponent Auth",
"version": "0.8.2", "version": "0.9.0",
"authors": ["Robert von Burg"], "authors": ["Robert von Burg"],
"keywords": [ "keywords": [
"strolch", "strolch",

View File

@ -7,6 +7,7 @@
"reset": "Reset", "reset": "Reset",
"passwordReset": "Password Reset", "passwordReset": "Password Reset",
"passwordResetDesc": "To reset your password, enter your username", "passwordResetDesc": "To reset your password, enter your username",
"passwordChangeRequest": "A password change has been requested",
"passwordResetInitiated": "The reset has been initiated for your account. Please check your e-mail inbox as there should be an e-mail with a reset code. The code in the e-mail will be valid for one hour.", "passwordResetInitiated": "The reset has been initiated for your account. Please check your e-mail inbox as there should be an e-mail with a reset code. The code in the e-mail will be valid for one hour.",
"passwordResetCode": "Please enter the code here:", "passwordResetCode": "Please enter the code here:",
"passwordResetNew": "Type in a new password and please repeat it", "passwordResetNew": "Type in a new password and please repeat it",
@ -46,6 +47,7 @@
"reset": "Zurücksetzen", "reset": "Zurücksetzen",
"passwordReset": "Passwort zurücksetzen", "passwordReset": "Passwort zurücksetzen",
"passwordResetDesc": "Geben Sie Ihren Nutzernamen ein, um ihr Passwort zurückzusetzen", "passwordResetDesc": "Geben Sie Ihren Nutzernamen ein, um ihr Passwort zurückzusetzen",
"passwordChangeRequest": "Das Passwort muss geändert werden",
"passwordResetInitiated": "Der Passwort-Reset wurde eingeleitet. Bitte überprüfen Sie ihren E-Mail Eingang, dieser sollte nun eine E-Mail mit dem Bestätigungs-Code enthalten. Dieser ist für eine Stunde gültig.", "passwordResetInitiated": "Der Passwort-Reset wurde eingeleitet. Bitte überprüfen Sie ihren E-Mail Eingang, dieser sollte nun eine E-Mail mit dem Bestätigungs-Code enthalten. Dieser ist für eine Stunde gültig.",
"passwordResetCode": "Bitte geben Sie den Code hier ein:", "passwordResetCode": "Bitte geben Sie den Code hier ein:",
"passwordResetNew": "Geben Sie ein neues Passwort ein und wiederholen Sie es", "passwordResetNew": "Geben Sie ein neues Passwort ein und wiederholen Sie es",

View File

@ -55,19 +55,19 @@
<div id="authForm" class="centered"> <div id="authForm" class="centered">
<iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_submitForm"></iron-a11y-keys> <iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_submitForm"></iron-a11y-keys>
<paper-card heading="{{localize('login')}}"> <paper-card heading="[[localize('login')]]">
<div class="card-content"> <div class="card-content">
<p>{{localize('pleaseLogin', 'appTitle', appTitle)}}</p> <p>[[localize('pleaseLogin', 'appTitle', appTitle)]]</p>
<paper-input id="usernameInput" <paper-input id="usernameInput"
value="{{username}}" value="{{username}}"
label="{{localize('username')}}" label="[[localize('username')]]"
required required
autofocus="true" autofocus="true"
auto-validate></paper-input> auto-validate></paper-input>
<paper-input id="passwordInput" <paper-input id="passwordInput"
value="{{password}}" value="{{password}}"
label="{{localize('password')}}" label="[[localize('password')]]"
required required
type="password" type="password"
on-focus="onFocus" on-focus="onFocus"
@ -85,84 +85,89 @@
</div> </div>
<div class="card-actions"> <div class="card-actions">
<paper-button on-tap="_showResetForm">{{localize('reset')}}</paper-button> <paper-button on-tap="_showResetForm">[[localize('reset')]]</paper-button>
<paper-button on-tap="_submitForm">{{localize('login')}}</paper-button> <paper-button on-tap="_submitForm">[[localize('login')]]</paper-button>
</div> </div>
</paper-card> </paper-card>
</div> </div>
<div id="initiateResetForm" class="centered" hidden> <div id="initiateResetForm" class="centered" hidden>
<iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_initiateReset"></iron-a11y-keys> <iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_initiateReset"></iron-a11y-keys>
<paper-card heading="{{localize('passwordReset')}}"> <paper-card heading="[[localize('passwordReset')]]">
<div class="card-content"> <div class="card-content">
<p>{{localize('passwordResetDesc')}}</p> <p>[[localize('passwordResetDesc')]]</p>
<paper-input id="usernameResetInput" <paper-input id="usernameResetInput"
value="{{username}}" value="{{username}}"
label="{{localize('username')}}" label="[[localize('username')]]"
required required
autofocus="true" autofocus="true"
auto-validate></paper-input> auto-validate></paper-input>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<paper-button on-tap="_cancelReset">{{localize('cancel')}}</paper-button> <paper-button on-tap="_cancelReset">[[localize('cancel')]]</paper-button>
<paper-button on-tap="_initiateReset">{{localize('reset')}}</paper-button> <paper-button on-tap="_initiateReset">[[localize('reset')]]</paper-button>
</div> </div>
</paper-card> </paper-card>
</div> </div>
<div id="resetInitiated" class="centered" hidden> <div id="resetInitiated" class="centered" hidden>
<iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_validateChallenge"></iron-a11y-keys> <iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_validateChallenge"></iron-a11y-keys>
<paper-card heading="{{localize('passwordReset')}}"> <paper-card heading="[[localize('passwordReset')]]">
<div class="card-content"> <div class="card-content">
<p>{{localize('passwordResetInitiated')}}</p> <p>[[localize('passwordResetInitiated')]]</p>
<p>{{localize('passwordResetCode')}}</p> <p>[[localize('passwordResetCode')]]</p>
<paper-input id="codeInput" <paper-input id="codeInput"
bind-value="{{code}}" bind-value="{{code}}"
label="{{localize('code')}}" label="[[localize('code')]]"
required required
autofocus="true" autofocus="true"
auto-validate></paper-input> auto-validate></paper-input>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<paper-button on-tap="_validateChallenge">{{localize('send')}}</paper-button> <paper-button on-tap="_validateChallenge">[[localize('send')]]</paper-button>
</div> </div>
</paper-card> </paper-card>
</div> </div>
<div id="resetForm" class="centered" hidden> <div id="resetForm" class="centered" hidden>
<iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_doReset"></iron-a11y-keys> <iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_doReset"></iron-a11y-keys>
<paper-card heading="{{localize('passwordReset')}}"> <paper-card heading="[[localize('passwordReset')]]">
<div class="card-content"> <div class="card-content">
<p>{{localize('passwordResetNew')}}</p> <template is="dom-if" if="[[isPasswordChangeRequested]]">
<p>[[localize('passwordChangeRequest')]]</p>
</template>
<template is="dom-if" if="[[!isPasswordChangeRequested]]">
<p>[[localize('passwordResetNew')]]</p>
</template>
<paper-input id="password1Input" <paper-input id="password1Input"
bind-value="{{password1}}" bind-value="{{password1}}"
label="{{localize('password')}}" label="[[localize('password')]]"
required required
type="password" type="password"
on-focus="onFocus" on-focus="onFocus"
auto-validate></paper-input> auto-validate></paper-input>
<paper-input id="password2Input" <paper-input id="password2Input"
bind-value="{{password2}}" bind-value="{{password2}}"
label="{{localize('repeat')}}" label="[[localize('repeat')]]"
required required
type="password" type="password"
on-focus="onFocus" on-focus="onFocus"
auto-validate></paper-input> auto-validate></paper-input>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<paper-button on-tap="_doReset">{{localize('reset')}}</paper-button> <paper-button on-tap="_doReset">[[localize('reset')]]</paper-button>
</div> </div>
</paper-card> </paper-card>
</div> </div>
<div id="passwordResetDone" class="centered" hidden> <div id="passwordResetDone" class="centered" hidden>
<iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_toLogin"></iron-a11y-keys> <iron-a11y-keys id="a11y" keys="enter" on-keys-pressed="_toLogin"></iron-a11y-keys>
<paper-card heading="{{localize('passwordReset')}}"> <paper-card heading="[[localize('passwordReset')]]">
<div class="card-content"> <div class="card-content">
<p>{{localize('passwordResetDone')}}</p> <p>[[localize('passwordResetDone')]]</p>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<paper-button on-tap="_showLoginForm">{{localize('login')}}</paper-button> <paper-button id="backToLoginBtn" on-tap="_showLoginForm">[[localize('login')]]</paper-button>
</div> </div>
</paper-card> </paper-card>
</div> </div>
@ -256,6 +261,10 @@
}, },
dlgTitle: { dlgTitle: {
type: String type: String
},
isPasswordChangeRequested: {
type: Boolean,
value: false
} }
}, },
@ -292,15 +301,14 @@
console.log("Validating session..."); console.log("Validating session...");
} }
var that = this;
setTimeout(function () { setTimeout(function () {
that.$.usernameInput.focus(); this.$.usernameInput.focus();
}, 100); }.bind(this), 100);
}, },
sessionValidated: function (data) { sessionValidated: function (e) {
console.log("Session validated."); console.log("Session validated.");
var userConfig = data.detail.response; var userConfig = e.detail.response;
Strolch.setUserConfig(userConfig); Strolch.setUserConfig(userConfig);
Strolch.sessionVerified = true; Strolch.sessionVerified = true;
this.fire('strolch-session-valid', { this.fire('strolch-session-valid', {
@ -324,8 +332,6 @@
var keepAliveDays = keepAliveMinutes / 60 / 24; var keepAliveDays = keepAliveMinutes / 60 / 24;
var delayMin = 14; var delayMin = 14;
var that = this;
if (keepAliveMinutes > 1440) { if (keepAliveMinutes > 1440) {
// more than a day // more than a day
@ -340,8 +346,8 @@
// check again in delayMin min // check again in delayMin min
console.log("Keep alive is " + keepAliveDays + " days and expiring in the future. Delaying refresh for " + delayMin + "m..."); console.log("Keep alive is " + keepAliveDays + " days and expiring in the future. Delaying refresh for " + delayMin + "m...");
setTimeout(function () { setTimeout(function () {
that.handleKeepAlive(Strolch.getUserConfig()); this.handleKeepAlive(Strolch.getUserConfig());
}, delayMin * 60 * 1000); }.bind(this), delayMin * 60 * 1000);
} }
} else if (keepAliveMinutes < 15) { } else if (keepAliveMinutes < 15) {
@ -356,8 +362,8 @@
// check again in delayMin // check again in delayMin
console.log("Keep alive is " + keepAliveMinutes + " minutes and expiring in " + expiryMin + "m. Delaying refresh for " + delayMin + "m..."); console.log("Keep alive is " + keepAliveMinutes + " minutes and expiring in " + expiryMin + "m. Delaying refresh for " + delayMin + "m...");
setTimeout(function () { setTimeout(function () {
that.handleKeepAlive(Strolch.getUserConfig()); this.handleKeepAlive(Strolch.getUserConfig());
}, delayMin * 60 * 1000); }.bind(this), delayMin * 60 * 1000);
} else { } else {
// less than 15 min // less than 15 min
@ -378,12 +384,12 @@
console.log('No response handler defined!'); console.log('No response handler defined!');
}, },
_handleAjaxError: function (data) { _handleAjaxError: function (e) {
var dlgText; var dlgText;
if (data.detail.request.response) { if (e.detail.request.response) {
dlgText = data.detail.request.response.msg; dlgText = e.detail.request.response.msg;
} else { } else {
dlgText = data.detail.error; dlgText = e.detail.error;
} }
this.showError(this.dlgTitle, dlgText); this.showError(this.dlgTitle, dlgText);
@ -392,7 +398,7 @@
logout: function () { logout: function () {
console.log('Logging out...'); console.log('Logging out...');
this._ajaxResponse = function (data) { this._ajaxResponse = function (e) {
console.log('Logged out.'); console.log('Logged out.');
Strolch.clearStorageData(); Strolch.clearStorageData();
}; };
@ -439,10 +445,19 @@
} }
console.log('Authenticating...'); console.log('Authenticating...');
this._ajaxResponse = function (data) { this._ajaxResponse = function (e) {
if (e.detail.response.usage === "set-password") {
this.authToken = e.detail.response.authToken;
this.isPasswordChangeRequested = true;
this._hideAll();
this.$.resetForm.hidden = false;
this.$.password1Input.focus();
return;
}
console.log('Logged in.'); console.log('Logged in.');
Strolch.setAuthToken(data.detail.response.authToken); Strolch.setAuthToken(e.detail.response.authToken);
Strolch.setUserConfig(data.detail.response); Strolch.setUserConfig(e.detail.response);
location.reload(); location.reload();
}; };
this.dlgTitle = this.localize('authenticationFailed'); this.dlgTitle = this.localize('authenticationFailed');
@ -451,6 +466,7 @@
password: btoa(unescape(encodeURIComponent(this.password))), password: btoa(unescape(encodeURIComponent(this.password))),
keepAlive: this.keepAlive keepAlive: this.keepAlive
}; };
this.password = "";
this.$.ajaxAuth.url = this.basePath + 'rest/strolch/authentication'; this.$.ajaxAuth.url = this.basePath + 'rest/strolch/authentication';
this.$.ajaxAuth.method = 'POST'; this.$.ajaxAuth.method = 'POST';
this.$.ajaxAuth.generateRequest(); this.$.ajaxAuth.generateRequest();
@ -467,11 +483,13 @@
_showResetForm: function () { _showResetForm: function () {
this._hideAll(); this._hideAll();
this.$.initiateResetForm.hidden = false; this.$.initiateResetForm.hidden = false;
this.$.usernameResetInput.focus();
}, },
_showLoginForm: function () { _showLoginForm: function () {
this._hideAll(); this._hideAll();
this.$.authForm.hidden = false; this.$.authForm.hidden = false;
this.$.passwordInput.inputElement.select();
}, },
_cancelReset: function () { _cancelReset: function () {
@ -485,11 +503,10 @@
console.log('Initiating reset...'); console.log('Initiating reset...');
var that = this;
this._ajaxResponse = function (data) { this._ajaxResponse = function (data) {
that._hideAll(); this._hideAll();
that.$.resetInitiated.hidden = false; this.$.resetInitiated.hidden = false;
that.$.codeInput.focus(); this.$.codeInput.focus();
}; };
this.dlgTitle = this.localize('resetFailed'); this.dlgTitle = this.localize('resetFailed');
@ -508,12 +525,11 @@
console.log('Validating challenge...'); console.log('Validating challenge...');
var that = this;
this._ajaxResponse = function (data) { this._ajaxResponse = function (data) {
that.authToken = data.detail.response.authToken; this.authToken = data.detail.response.authToken;
that._hideAll(); this._hideAll();
that.$.resetForm.hidden = false; this.$.resetForm.hidden = false;
that.$.password1Input.focus(); this.$.password1Input.focus();
}; };
this.dlgTitle = this.localize('resetFailed'); this.dlgTitle = this.localize('resetFailed');
@ -540,10 +556,10 @@
console.log('Doing reset...'); console.log('Doing reset...');
var that = this; this._ajaxResponse = function (e) {
this._ajaxResponse = function (data) { this._hideAll();
that._hideAll(); this.$.passwordResetDone.hidden = false;
that.$.passwordResetDone.hidden = false; this.$.backToLoginBtn.focus();
}; };
this.dlgTitle = this.localize('resetFailed'); this.dlgTitle = this.localize('resetFailed');
@ -552,11 +568,14 @@
this.$.ajaxAuth.body = { this.$.ajaxAuth.body = {
password: btoa(unescape(encodeURIComponent(this.password1))) password: btoa(unescape(encodeURIComponent(this.password1)))
}; };
this.password = "";
this.password1 = "";
this.password2 = "";
this.$.ajaxAuth.generateRequest(); this.$.ajaxAuth.generateRequest();
}, },
onGetVersionResponse: function (event) { onGetVersionResponse: function (e) {
var version = event.detail.response; var version = e.detail.response;
this.appName = version.agentVersion.agentName; this.appName = version.agentVersion.agentName;
this.appVersion = version.appVersion.artifactVersion; this.appVersion = version.appVersion.artifactVersion;
this.environment = version.agentVersion.environment; this.environment = version.agentVersion.environment;
@ -564,9 +583,9 @@
sessionStorage.setItem("strolchAppVersion", JSON.stringify(version)); sessionStorage.setItem("strolchAppVersion", JSON.stringify(version));
}, },
onGetVersionError: function (event) { onGetVersionError: function (e) {
var readyState = event.detail.request.xhr.readyState; var readyState = e.detail.request.xhr.readyState;
var status = event.detail.request.xhr.status; var status = e.detail.request.xhr.status;
console.log("Ignoring get version error due to readyState: " + readyState + " / status: " + status); console.log("Ignoring get version error due to readyState: " + readyState + " / status: " + status);
}, },
_getEnv: function (environment) { _getEnv: function (environment) {