Mercurial > hg > cmmr2012-drupal-site
comparison core/modules/user/user.es6.js @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | a9cd425dd02b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
1 /** | |
2 * @file | |
3 * User behaviors. | |
4 */ | |
5 | |
6 (function ($, Drupal, drupalSettings) { | |
7 /** | |
8 * Attach handlers to evaluate the strength of any password fields and to | |
9 * check that its confirmation is correct. | |
10 * | |
11 * @type {Drupal~behavior} | |
12 * | |
13 * @prop {Drupal~behaviorAttach} attach | |
14 * Attaches password strength indicator and other relevant validation to | |
15 * password fields. | |
16 */ | |
17 Drupal.behaviors.password = { | |
18 attach(context, settings) { | |
19 const $passwordInput = $(context).find('input.js-password-field').once('password'); | |
20 | |
21 if ($passwordInput.length) { | |
22 const translate = settings.password; | |
23 | |
24 const $passwordInputParent = $passwordInput.parent(); | |
25 const $passwordInputParentWrapper = $passwordInputParent.parent(); | |
26 let $passwordSuggestions; | |
27 | |
28 // Add identifying class to password element parent. | |
29 $passwordInputParent.addClass('password-parent'); | |
30 | |
31 // Add the password confirmation layer. | |
32 $passwordInputParentWrapper | |
33 .find('input.js-password-confirm') | |
34 .parent() | |
35 .append(`<div aria-live="polite" aria-atomic="true" class="password-confirm js-password-confirm">${translate.confirmTitle} <span></span></div>`) | |
36 .addClass('confirm-parent'); | |
37 | |
38 const $confirmInput = $passwordInputParentWrapper.find('input.js-password-confirm'); | |
39 const $confirmResult = $passwordInputParentWrapper.find('div.js-password-confirm'); | |
40 const $confirmChild = $confirmResult.find('span'); | |
41 | |
42 // If the password strength indicator is enabled, add its markup. | |
43 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>`; | |
45 $confirmInput.parent().after('<div class="password-suggestions description"></div>'); | |
46 $passwordInputParent.append(passwordMeter); | |
47 $passwordSuggestions = $passwordInputParentWrapper.find('div.password-suggestions').hide(); | |
48 } | |
49 | |
50 // Check that password and confirmation inputs match. | |
51 const passwordCheckMatch = function (confirmInputVal) { | |
52 const success = $passwordInput.val() === confirmInputVal; | |
53 const confirmClass = success ? 'ok' : 'error'; | |
54 | |
55 // Fill in the success message and set the class accordingly. | |
56 $confirmChild.html(translate[`confirm${success ? 'Success' : 'Failure'}`]) | |
57 .removeClass('ok error').addClass(confirmClass); | |
58 }; | |
59 | |
60 // Check the password strength. | |
61 const passwordCheck = function () { | |
62 if (settings.password.showStrengthIndicator) { | |
63 // Evaluate the password strength. | |
64 const result = Drupal.evaluatePasswordStrength($passwordInput.val(), settings.password); | |
65 | |
66 // Update the suggestions for how to improve the password. | |
67 if ($passwordSuggestions.html() !== result.message) { | |
68 $passwordSuggestions.html(result.message); | |
69 } | |
70 | |
71 // Only show the description box if a weakness exists in the | |
72 // password. | |
73 $passwordSuggestions.toggle(result.strength !== 100); | |
74 | |
75 // Adjust the length of the strength indicator. | |
76 $passwordInputParent.find('.js-password-strength__indicator') | |
77 .css('width', `${result.strength}%`) | |
78 .removeClass('is-weak is-fair is-good is-strong') | |
79 .addClass(result.indicatorClass); | |
80 | |
81 // Update the strength indication text. | |
82 $passwordInputParent.find('.js-password-strength__text').html(result.indicatorText); | |
83 } | |
84 | |
85 // Check the value in the confirm input and show results. | |
86 if ($confirmInput.val()) { | |
87 passwordCheckMatch($confirmInput.val()); | |
88 $confirmResult.css({ visibility: 'visible' }); | |
89 } | |
90 else { | |
91 $confirmResult.css({ visibility: 'hidden' }); | |
92 } | |
93 }; | |
94 | |
95 // Monitor input events. | |
96 $passwordInput.on('input', passwordCheck); | |
97 $confirmInput.on('input', passwordCheck); | |
98 } | |
99 }, | |
100 }; | |
101 | |
102 /** | |
103 * Evaluate the strength of a user's password. | |
104 * | |
105 * Returns the estimated strength and the relevant output message. | |
106 * | |
107 * @param {string} password | |
108 * The password to evaluate. | |
109 * @param {object} translate | |
110 * An object containing the text to display for each strength level. | |
111 * | |
112 * @return {object} | |
113 * An object containing strength, message, indicatorText and indicatorClass. | |
114 */ | |
115 Drupal.evaluatePasswordStrength = function (password, translate) { | |
116 password = password.trim(); | |
117 let indicatorText; | |
118 let indicatorClass; | |
119 let weaknesses = 0; | |
120 let strength = 100; | |
121 let msg = []; | |
122 | |
123 const hasLowercase = /[a-z]/.test(password); | |
124 const hasUppercase = /[A-Z]/.test(password); | |
125 const hasNumbers = /[0-9]/.test(password); | |
126 const hasPunctuation = /[^a-zA-Z0-9]/.test(password); | |
127 | |
128 // If there is a username edit box on the page, compare password to that, | |
129 // otherwise use value from the database. | |
130 const $usernameBox = $('input.username'); | |
131 const username = ($usernameBox.length > 0) ? $usernameBox.val() : translate.username; | |
132 | |
133 // Lose 5 points for every character less than 12, plus a 30 point penalty. | |
134 if (password.length < 12) { | |
135 msg.push(translate.tooShort); | |
136 strength -= ((12 - password.length) * 5) + 30; | |
137 } | |
138 | |
139 // Count weaknesses. | |
140 if (!hasLowercase) { | |
141 msg.push(translate.addLowerCase); | |
142 weaknesses++; | |
143 } | |
144 if (!hasUppercase) { | |
145 msg.push(translate.addUpperCase); | |
146 weaknesses++; | |
147 } | |
148 if (!hasNumbers) { | |
149 msg.push(translate.addNumbers); | |
150 weaknesses++; | |
151 } | |
152 if (!hasPunctuation) { | |
153 msg.push(translate.addPunctuation); | |
154 weaknesses++; | |
155 } | |
156 | |
157 // Apply penalty for each weakness (balanced against length penalty). | |
158 switch (weaknesses) { | |
159 case 1: | |
160 strength -= 12.5; | |
161 break; | |
162 | |
163 case 2: | |
164 strength -= 25; | |
165 break; | |
166 | |
167 case 3: | |
168 strength -= 40; | |
169 break; | |
170 | |
171 case 4: | |
172 strength -= 40; | |
173 break; | |
174 } | |
175 | |
176 // Check if password is the same as the username. | |
177 if (password !== '' && password.toLowerCase() === username.toLowerCase()) { | |
178 msg.push(translate.sameAsUsername); | |
179 // Passwords the same as username are always very weak. | |
180 strength = 5; | |
181 } | |
182 | |
183 // Based on the strength, work out what text should be shown by the | |
184 // password strength meter. | |
185 if (strength < 60) { | |
186 indicatorText = translate.weak; | |
187 indicatorClass = 'is-weak'; | |
188 } | |
189 else if (strength < 70) { | |
190 indicatorText = translate.fair; | |
191 indicatorClass = 'is-fair'; | |
192 } | |
193 else if (strength < 80) { | |
194 indicatorText = translate.good; | |
195 indicatorClass = 'is-good'; | |
196 } | |
197 else if (strength <= 100) { | |
198 indicatorText = translate.strong; | |
199 indicatorClass = 'is-strong'; | |
200 } | |
201 | |
202 // Assemble the final message. | |
203 msg = `${translate.hasWeaknesses}<ul><li>${msg.join('</li><li>')}</li></ul>`; | |
204 | |
205 return { | |
206 strength, | |
207 message: msg, | |
208 indicatorText, | |
209 indicatorClass, | |
210 }; | |
211 }; | |
212 }(jQuery, Drupal, drupalSettings)); |