Skip to content

Commit

Permalink
9097 add contextual password helper (#9256)
Browse files Browse the repository at this point in the history
* update back-office forms

* Display tip on reset password page as well

* add directive for password tip

* integrate directove in login screen

* forgot the ng-keyup :-)

* adapt tooltip directive to potential different Members and Users password settings

* remove watcher

Co-authored-by: Nathan Woulfe <[email protected]>
  • Loading branch information
mikecp and nathanwoulfe authored Mar 22, 2021
1 parent 3d05bd6 commit 88611f3
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
function UmbLoginController($scope, $location, currentUserResource, formHelper,
mediaHelper, umbRequestHelper, Upload, localizationService,
userService, externalLoginInfo, externalLoginInfoService,
resetPasswordCodeInfo, $timeout, authResource, $q, $route) {
resetPasswordCodeInfo, authResource, $q) {

const vm = this;

Expand Down Expand Up @@ -72,6 +72,7 @@
vm.loginSubmit = loginSubmit;
vm.requestPasswordResetSubmit = requestPasswordResetSubmit;
vm.setPasswordSubmit = setPasswordSubmit;
vm.newPasswordKeyUp = newPasswordKeyUp;
vm.labels = {};
localizationService.localizeMany([
vm.usernameIsEmail ? "general_email" : "general_username",
Expand Down Expand Up @@ -362,6 +363,9 @@
});
}

function newPasswordKeyUp(event) {
vm.passwordVal = event.target.value;
}

////

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
(function () {
'use strict';

angular
.module('umbraco.directives')
.component('umbPasswordTip', {
controller: UmbPasswordTipController,
controllerAs: 'vm',
template:
'<span class="help-inline" style="display: block;" ng-if="vm.passwordTip" ng-bind-html="vm.passwordTip">{{vm.passwordTip}}</span>',
bindings: {
passwordVal: "<",
minPwdLength: "<",
minPwdNonAlphaNum: "<"
}
});

function UmbPasswordTipController(localizationService) {

let defaultMinPwdLength = Umbraco.Sys.ServerVariables.umbracoSettings.minimumPasswordLength;
let defaultMinPwdNonAlphaNum = Umbraco.Sys.ServerVariables.umbracoSettings.minimumPasswordNonAlphaNum;

var vm = this;
vm.$onInit = onInit;
vm.$onChanges = onChanges;

function onInit() {
if (vm.minPwdLength === undefined) {
vm.minPwdLength = defaultMinPwdLength;
}

if (vm.minPwdNonAlphaNum === undefined) {
vm.minPwdNonAlphaNum = defaultMinPwdNonAlphaNum;
}

if (vm.minPwdNonAlphaNum > 0) {
localizationService.localize('user_newPasswordFormatNonAlphaTip', [vm.minPwdNonAlphaNum]).then(data => {
vm.passwordNonAlphaTip = data;
updatePasswordTip(0);
});
} else {
vm.passwordNonAlphaTip = '';
updatePasswordTip(0);
}
}

function onChanges(simpleChanges) {
if (simpleChanges.passwordVal) {
if (simpleChanges.passwordVal.currentValue) {
updatePasswordTip(simpleChanges.passwordVal.currentValue.length);
} else {
updatePasswordTip(0);
}
}
}

const updatePasswordTip = passwordLength => {
const remainingLength = vm.minPwdLength - passwordLength;
if (remainingLength > 0) {
localizationService.localize('user_newPasswordFormatLengthTip', [remainingLength]).then(data => {
vm.passwordTip = data;
if (vm.passwordNonAlphaTip) {
vm.passwordTip += `<br/>${vm.passwordNonAlphaTip}`;
}
});
} else {
vm.passwordTip = vm.passwordNonAlphaTip;
}
}
}
})();
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
vm.cancelChange = cancelChange;
vm.showOldPass = showOldPass;
vm.showCancelBtn = showCancelBtn;
vm.newPasswordKeyUp = newPasswordKeyUp;

var unsubscribe = [];

Expand Down Expand Up @@ -55,6 +56,11 @@
vm.config.minPasswordLength = 0;
}

// Check non-alpha pwd settings for tooltip display
if (vm.config.minNonAlphaNumericChars === undefined) {
vm.config.minNonAlphaNumericChars = 0;
}

//set the model defaults
if (!Utilities.isObject(vm.passwordValues)) {
//if it's not an object then just create a new one
Expand Down Expand Up @@ -152,6 +158,9 @@
return vm.config.disableToggle !== true && vm.config.hasPassword;
};

function newPasswordKeyUp(event) {
vm.passwordVal = event.target.value;
}
}

var component = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ <h1>{{greeting}}</h1>

<div ng-hide="vm.resetComplete" class="control-group" ng-class="{error: vm.setPasswordForm.password.$invalid}">
<label for="umb-passwordThree"><localize key="user_newPassword">New password</localize></label>
<input type="password" ng-model="vm.password" name="password" id="umb-passwordThree" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" focus-when="{{vm.view === 'set-password'}}" />
<input type="password" ng-model="vm.password" name="password" id="umb-passwordThree" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" focus-when="{{vm.view === 'set-password'}}" ng-keyup="vm.newPasswordKeyUp($event)" />
<umb-password-tip password-val="vm.passwordVal"></umb-password-tip>
</div>

<div ng-hide="vm.resetComplete" class="control-group" ng-class="{error: vm.setPasswordForm.confirmPassword.$invalid}">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@
required
val-server-field="password"
ng-minlength="{{vm.config.minPasswordLength}}"
no-dirty-check />
no-dirty-check
ng-keyup="vm.newPasswordKeyUp($event)"/>
<span ng-messages="changePasswordForm.password.$error" show-validation-on-submit>
<span class="help-inline" ng-message="required">Required</span>
<span class="help-inline" ng-message="minlength">Minimum {{vm.config.minPasswordLength}} characters</span>
<span class="help-inline" ng-message="valServerField">{{changePasswordForm.password.errorMsg}}</span>
</span>
<umb-password-tip password-val="vm.passwordVal" min-pwd-length="vm.config.minPasswordLength" min-pwd-non-alpha-num="vm.config.minNonAlphaNumericChars"></umb-password-tip>
</umb-control-group>

<umb-control-group alias="confirmPassword" label="@user_confirmNewPassword" ng-if="!vm.showReset" required="true">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont
if (!$scope.model.config || $scope.model.config.minPasswordLength === undefined) {
$scope.model.config.minPasswordLength = 0;
}
if (!$scope.model.config || $scope.model.config.minNonAlphaNumericChars === undefined) {
$scope.model.config.minNonAlphaNumericChars = 0;
}

//set the model defaults
if (!Utilities.isObject($scope.model.value)) {
Expand Down
2 changes: 2 additions & 0 deletions src/Umbraco.Web.UI/Umbraco/config/lang/en.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="changePassword">Change your password</key>
<key alias="changePhoto">Change photo</key>
<key alias="newPassword">New password</key>
<key alias="newPasswordFormatLengthTip">Minimum %0% character(s) to go!</key>
<key alias="newPasswordFormatNonAlphaTip">There should be at least %0% special character(s) in there.</key>
<key alias="noLockouts">hasn't been locked out</key>
<key alias="noPasswordChange">The password hasn't been changed</key>
<key alias="confirmNewPassword">Confirm new password</key>
Expand Down
2 changes: 2 additions & 0 deletions src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="changePassword">Change your password</key>
<key alias="changePhoto">Change photo</key>
<key alias="newPassword">New password</key>
<key alias="newPasswordFormatLengthTip">Minimum %0% character(s) to go!</key>
<key alias="newPasswordFormatNonAlphaTip">There should be at least %0% special character(s) in there.</key>
<key alias="noLockouts">hasn't been locked out</key>
<key alias="noPasswordChange">The password hasn't been changed</key>
<key alias="confirmNewPassword">Confirm new password</key>
Expand Down
2 changes: 2 additions & 0 deletions src/Umbraco.Web.UI/Umbraco/config/lang/fr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,8 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
<key alias="changePassword">Changer le mot de passe</key>
<key alias="changePhoto">Changer la photo</key>
<key alias="newPassword">Nouveau mot de passe</key>
<key alias="newPasswordFormatLengthTip">Plus que %0% caractère(s) minimum!</key>
<key alias="newPasswordFormatNonAlphaTip">Il devrait y avoir au moins %0% caractère(s) spéciaux.</key>
<key alias="noLockouts">n'a pas été bloqué</key>
<key alias="noPasswordChange">Le mot de passe n'a pas été modifié</key>
<key alias="confirmNewPassword">Confirmez votre nouveau mot de passe</key>
Expand Down
6 changes: 5 additions & 1 deletion src/Umbraco.Web/Editors/BackOfficeServerVariables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ internal Dictionary<string, object> BareMinimumServerVariables()
var keepOnlyKeys = new Dictionary<string, string[]>
{
{"umbracoUrls", new[] {"authenticationApiBaseUrl", "serverVarsJs", "externalLoginsUrl", "currentUserApiBaseUrl", "iconApiBaseUrl"}},
{"umbracoSettings", new[] {"allowPasswordReset", "imageFileTypes", "maxFileSize", "loginBackgroundImage", "loginLogoImage", "canSendRequiredEmail", "usernameIsEmail"}},
{"umbracoSettings", new[] {"allowPasswordReset", "imageFileTypes", "maxFileSize", "loginBackgroundImage", "loginLogoImage", "canSendRequiredEmail", "usernameIsEmail", "minimumPasswordLength", "minimumPasswordNonAlphaNum"}},
{"application", new[] {"applicationPath", "cacheBuster"}},
{"isDebuggingEnabled", new string[] { }},
{"features", new [] {"disabledFeatures"}}
Expand Down Expand Up @@ -100,6 +100,8 @@ internal Dictionary<string, object> BareMinimumServerVariables()
/// <returns></returns>
internal Dictionary<string, object> GetServerVariables()
{
var userMembershipProvider = Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider();

var defaultVals = new Dictionary<string, object>
{
{
Expand Down Expand Up @@ -357,6 +359,8 @@ internal Dictionary<string, object> GetServerVariables()
{"showUserInvite", EmailSender.CanSendRequiredEmail},
{"canSendRequiredEmail", EmailSender.CanSendRequiredEmail},
{"showAllowSegmentationForDocumentTypes", false},
{"minimumPasswordLength", userMembershipProvider.MinRequiredPasswordLength},
{"minimumPasswordNonAlphaNum", userMembershipProvider.MinRequiredNonAlphanumericCharacters},
}
},
{
Expand Down

0 comments on commit 88611f3

Please sign in to comment.