comparison core/modules/user/user.es6.js @ 4:a9cd425dd02b

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:11:55 +0000
parents c75dbcec494b
children
comparison
equal deleted inserted replaced
3:307d7a7fd348 4:a9cd425dd02b
1 /** 1 /**
2 * @file 2 * @file
3 * User behaviors. 3 * User behaviors.
4 */ 4 */
5 5
6 (function ($, Drupal, drupalSettings) { 6 (function($, Drupal, drupalSettings) {
7 /** 7 /**
8 * Attach handlers to evaluate the strength of any password fields and to 8 * Attach handlers to evaluate the strength of any password fields and to
9 * check that its confirmation is correct. 9 * check that its confirmation is correct.
10 * 10 *
11 * @type {Drupal~behavior} 11 * @type {Drupal~behavior}
14 * Attaches password strength indicator and other relevant validation to 14 * Attaches password strength indicator and other relevant validation to
15 * password fields. 15 * password fields.
16 */ 16 */
17 Drupal.behaviors.password = { 17 Drupal.behaviors.password = {
18 attach(context, settings) { 18 attach(context, settings) {
19 const $passwordInput = $(context).find('input.js-password-field').once('password'); 19 const $passwordInput = $(context)
20 .find('input.js-password-field')
21 .once('password');
20 22
21 if ($passwordInput.length) { 23 if ($passwordInput.length) {
22 const translate = settings.password; 24 const translate = settings.password;
23 25
24 const $passwordInputParent = $passwordInput.parent(); 26 const $passwordInputParent = $passwordInput.parent();
30 32
31 // Add the password confirmation layer. 33 // Add the password confirmation layer.
32 $passwordInputParentWrapper 34 $passwordInputParentWrapper
33 .find('input.js-password-confirm') 35 .find('input.js-password-confirm')
34 .parent() 36 .parent()
35 .append(`<div aria-live="polite" aria-atomic="true" class="password-confirm js-password-confirm">${translate.confirmTitle} <span></span></div>`) 37 .append(
38 `<div aria-live="polite" aria-atomic="true" class="password-confirm js-password-confirm">${
39 translate.confirmTitle
40 } <span></span></div>`,
41 )
36 .addClass('confirm-parent'); 42 .addClass('confirm-parent');
37 43
38 const $confirmInput = $passwordInputParentWrapper.find('input.js-password-confirm'); 44 const $confirmInput = $passwordInputParentWrapper.find(
39 const $confirmResult = $passwordInputParentWrapper.find('div.js-password-confirm'); 45 'input.js-password-confirm',
46 );
47 const $confirmResult = $passwordInputParentWrapper.find(
48 'div.js-password-confirm',
49 );
40 const $confirmChild = $confirmResult.find('span'); 50 const $confirmChild = $confirmResult.find('span');
41 51
42 // If the password strength indicator is enabled, add its markup. 52 // If the password strength indicator is enabled, add its markup.
43 if (settings.password.showStrengthIndicator) { 53 if (settings.password.showStrengthIndicator) {
44 const passwordMeter = `<div class="password-strength"><div class="password-strength__meter"><div class="password-strength__indicator js-password-strength__indicator"></div></div><div aria-live="polite" aria-atomic="true" class="password-strength__title">${translate.strengthTitle} <span class="password-strength__text js-password-strength__text"></span></div></div>`; 54 const passwordMeter = `<div class="password-strength"><div class="password-strength__meter"><div class="password-strength__indicator js-password-strength__indicator"></div></div><div aria-live="polite" aria-atomic="true" class="password-strength__title">${
45 $confirmInput.parent().after('<div class="password-suggestions description"></div>'); 55 translate.strengthTitle
56 } <span class="password-strength__text js-password-strength__text"></span></div></div>`;
57 $confirmInput
58 .parent()
59 .after('<div class="password-suggestions description"></div>');
46 $passwordInputParent.append(passwordMeter); 60 $passwordInputParent.append(passwordMeter);
47 $passwordSuggestions = $passwordInputParentWrapper.find('div.password-suggestions').hide(); 61 $passwordSuggestions = $passwordInputParentWrapper
62 .find('div.password-suggestions')
63 .hide();
48 } 64 }
49 65
50 // Check that password and confirmation inputs match. 66 // Check that password and confirmation inputs match.
51 const passwordCheckMatch = function (confirmInputVal) { 67 const passwordCheckMatch = function(confirmInputVal) {
52 const success = $passwordInput.val() === confirmInputVal; 68 const success = $passwordInput.val() === confirmInputVal;
53 const confirmClass = success ? 'ok' : 'error'; 69 const confirmClass = success ? 'ok' : 'error';
54 70
55 // Fill in the success message and set the class accordingly. 71 // Fill in the success message and set the class accordingly.
56 $confirmChild.html(translate[`confirm${success ? 'Success' : 'Failure'}`]) 72 $confirmChild
57 .removeClass('ok error').addClass(confirmClass); 73 .html(translate[`confirm${success ? 'Success' : 'Failure'}`])
74 .removeClass('ok error')
75 .addClass(confirmClass);
58 }; 76 };
59 77
60 // Check the password strength. 78 // Check the password strength.
61 const passwordCheck = function () { 79 const passwordCheck = function() {
62 if (settings.password.showStrengthIndicator) { 80 if (settings.password.showStrengthIndicator) {
63 // Evaluate the password strength. 81 // Evaluate the password strength.
64 const result = Drupal.evaluatePasswordStrength($passwordInput.val(), settings.password); 82 const result = Drupal.evaluatePasswordStrength(
83 $passwordInput.val(),
84 settings.password,
85 );
65 86
66 // Update the suggestions for how to improve the password. 87 // Update the suggestions for how to improve the password.
67 if ($passwordSuggestions.html() !== result.message) { 88 if ($passwordSuggestions.html() !== result.message) {
68 $passwordSuggestions.html(result.message); 89 $passwordSuggestions.html(result.message);
69 } 90 }
71 // Only show the description box if a weakness exists in the 92 // Only show the description box if a weakness exists in the
72 // password. 93 // password.
73 $passwordSuggestions.toggle(result.strength !== 100); 94 $passwordSuggestions.toggle(result.strength !== 100);
74 95
75 // Adjust the length of the strength indicator. 96 // Adjust the length of the strength indicator.
76 $passwordInputParent.find('.js-password-strength__indicator') 97 $passwordInputParent
98 .find('.js-password-strength__indicator')
77 .css('width', `${result.strength}%`) 99 .css('width', `${result.strength}%`)
78 .removeClass('is-weak is-fair is-good is-strong') 100 .removeClass('is-weak is-fair is-good is-strong')
79 .addClass(result.indicatorClass); 101 .addClass(result.indicatorClass);
80 102
81 // Update the strength indication text. 103 // Update the strength indication text.
82 $passwordInputParent.find('.js-password-strength__text').html(result.indicatorText); 104 $passwordInputParent
105 .find('.js-password-strength__text')
106 .html(result.indicatorText);
83 } 107 }
84 108
85 // Check the value in the confirm input and show results. 109 // Check the value in the confirm input and show results.
86 if ($confirmInput.val()) { 110 if ($confirmInput.val()) {
87 passwordCheckMatch($confirmInput.val()); 111 passwordCheckMatch($confirmInput.val());
88 $confirmResult.css({ visibility: 'visible' }); 112 $confirmResult.css({ visibility: 'visible' });
89 } 113 } else {
90 else {
91 $confirmResult.css({ visibility: 'hidden' }); 114 $confirmResult.css({ visibility: 'hidden' });
92 } 115 }
93 }; 116 };
94 117
95 // Monitor input events. 118 // Monitor input events.
110 * An object containing the text to display for each strength level. 133 * An object containing the text to display for each strength level.
111 * 134 *
112 * @return {object} 135 * @return {object}
113 * An object containing strength, message, indicatorText and indicatorClass. 136 * An object containing strength, message, indicatorText and indicatorClass.
114 */ 137 */
115 Drupal.evaluatePasswordStrength = function (password, translate) { 138 Drupal.evaluatePasswordStrength = function(password, translate) {
116 password = password.trim(); 139 password = password.trim();
117 let indicatorText; 140 let indicatorText;
118 let indicatorClass; 141 let indicatorClass;
119 let weaknesses = 0; 142 let weaknesses = 0;
120 let strength = 100; 143 let strength = 100;
126 const hasPunctuation = /[^a-zA-Z0-9]/.test(password); 149 const hasPunctuation = /[^a-zA-Z0-9]/.test(password);
127 150
128 // If there is a username edit box on the page, compare password to that, 151 // If there is a username edit box on the page, compare password to that,
129 // otherwise use value from the database. 152 // otherwise use value from the database.
130 const $usernameBox = $('input.username'); 153 const $usernameBox = $('input.username');
131 const username = ($usernameBox.length > 0) ? $usernameBox.val() : translate.username; 154 const username =
155 $usernameBox.length > 0 ? $usernameBox.val() : translate.username;
132 156
133 // Lose 5 points for every character less than 12, plus a 30 point penalty. 157 // Lose 5 points for every character less than 12, plus a 30 point penalty.
134 if (password.length < 12) { 158 if (password.length < 12) {
135 msg.push(translate.tooShort); 159 msg.push(translate.tooShort);
136 strength -= ((12 - password.length) * 5) + 30; 160 strength -= (12 - password.length) * 5 + 30;
137 } 161 }
138 162
139 // Count weaknesses. 163 // Count weaknesses.
140 if (!hasLowercase) { 164 if (!hasLowercase) {
141 msg.push(translate.addLowerCase); 165 msg.push(translate.addLowerCase);
183 // Based on the strength, work out what text should be shown by the 207 // Based on the strength, work out what text should be shown by the
184 // password strength meter. 208 // password strength meter.
185 if (strength < 60) { 209 if (strength < 60) {
186 indicatorText = translate.weak; 210 indicatorText = translate.weak;
187 indicatorClass = 'is-weak'; 211 indicatorClass = 'is-weak';
188 } 212 } else if (strength < 70) {
189 else if (strength < 70) {
190 indicatorText = translate.fair; 213 indicatorText = translate.fair;
191 indicatorClass = 'is-fair'; 214 indicatorClass = 'is-fair';
192 } 215 } else if (strength < 80) {
193 else if (strength < 80) {
194 indicatorText = translate.good; 216 indicatorText = translate.good;
195 indicatorClass = 'is-good'; 217 indicatorClass = 'is-good';
196 } 218 } else if (strength <= 100) {
197 else if (strength <= 100) {
198 indicatorText = translate.strong; 219 indicatorText = translate.strong;
199 indicatorClass = 'is-strong'; 220 indicatorClass = 'is-strong';
200 } 221 }
201 222
202 // Assemble the final message. 223 // Assemble the final message.
203 msg = `${translate.hasWeaknesses}<ul><li>${msg.join('</li><li>')}</li></ul>`; 224 msg = `${translate.hasWeaknesses}<ul><li>${msg.join(
225 '</li><li>',
226 )}</li></ul>`;
204 227
205 return { 228 return {
206 strength, 229 strength,
207 message: msg, 230 message: msg,
208 indicatorText, 231 indicatorText,
209 indicatorClass, 232 indicatorClass,
210 }; 233 };
211 }; 234 };
212 }(jQuery, Drupal, drupalSettings)); 235 })(jQuery, Drupal, drupalSettings);