Merge pull request 'Validate signup email and password strength' (#155) from feature/150-signup-credential-validation into main
CI / Tests (PHP 8.2) (push) Failing after 43s
CI / No Debug Code (push) Successful in 2s
CI / PHPStan (push) Successful in 2m55s
CI / Coding Standards (push) Successful in 2m56s
CI / Tests (PHP 8.3) (push) Failing after 2m44s
CI / Build Plugin Zip (push) Skipped
CI / Tests (PHP 8.1) (push) Failing after 50s
CI / Tests (PHP 8.2) (push) Failing after 43s
CI / No Debug Code (push) Successful in 2s
CI / PHPStan (push) Successful in 2m55s
CI / Coding Standards (push) Successful in 2m56s
CI / Tests (PHP 8.3) (push) Failing after 2m44s
CI / Build Plugin Zip (push) Skipped
CI / Tests (PHP 8.1) (push) Failing after 50s
Reviewed-on: #155
This commit was merged in pull request #155.
This commit is contained in:
@@ -14,10 +14,113 @@
|
||||
* block. Ticking the box also takes the guardian's *own* question panel out
|
||||
* of play — in guardian mode the questions are asked per child, so the
|
||||
* server ignores those answers and the browser must not demand them.
|
||||
* 3. **Password strength.** The password is scored with zxcvbn (via WordPress's
|
||||
* own `wp.passwordStrength`) and a weak one is refused. The server applies
|
||||
* its own, coarser rule regardless — see `Auth\PasswordPolicy`.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var PASSWORD = window.usSchedulerPassword || {};
|
||||
|
||||
/**
|
||||
* Gate the form on password strength.
|
||||
*
|
||||
* The verdict is attached to the field with `setCustomValidity()` rather than
|
||||
* by disabling the submit button: the form has up to three submits (the plain
|
||||
* one, the guardian-mode early one, and step two's) plus a "Next" that
|
||||
* already gates on `checkValidity()`, and an invalid field blocks all of them
|
||||
* at once without any of them having to know why.
|
||||
*/
|
||||
function enhancePassword(form) {
|
||||
var field = form.querySelector('#us-reg-pass');
|
||||
var output = form.querySelector('#us-reg-pass-strength');
|
||||
var strings = PASSWORD.strings || {};
|
||||
|
||||
if (!field || !PASSWORD.minScore) {
|
||||
return;
|
||||
}
|
||||
|
||||
// What the password must not simply repeat back. Mirrors the identity
|
||||
// check PasswordPolicy makes server-side.
|
||||
function identity() {
|
||||
var out = [];
|
||||
var sources = form.querySelectorAll('#us-reg-email, #us-reg-name');
|
||||
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
var value = (sources[i].value || '').trim();
|
||||
if (value) {
|
||||
out.push(value);
|
||||
if (value.indexOf('@') > 0) {
|
||||
out.push(value.split('@')[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function assess() {
|
||||
var value = field.value || '';
|
||||
|
||||
if (!value) {
|
||||
report('', '');
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.length < (PASSWORD.minLength || 8)) {
|
||||
report(strings.short, 'short');
|
||||
return;
|
||||
}
|
||||
|
||||
// zxcvbn's dictionary is fetched after load, and wp.passwordStrength
|
||||
// reports -1 until it arrives. Say nothing and allow the submit in that
|
||||
// window — the server still checks, and the next keystroke re-runs this
|
||||
// once the dictionary is in.
|
||||
if (!window.wp || !window.wp.passwordStrength || typeof window.zxcvbn === 'undefined') {
|
||||
report('', '');
|
||||
return;
|
||||
}
|
||||
|
||||
var score = window.wp.passwordStrength.meter(value, identity(), '');
|
||||
|
||||
if (score < 0) {
|
||||
report('', '');
|
||||
return;
|
||||
}
|
||||
|
||||
if (score >= 3) {
|
||||
report(strings.strong, 'strong');
|
||||
} else if (score >= PASSWORD.minScore) {
|
||||
report(strings.medium, 'medium');
|
||||
} else {
|
||||
report(score <= 0 ? strings.veryWeak : strings.weak, 'weak');
|
||||
}
|
||||
}
|
||||
|
||||
/** Show the verdict, and make it the field's validity at the same time. */
|
||||
function report(message, level) {
|
||||
var acceptable = '' === level || 'medium' === level || 'strong' === level;
|
||||
|
||||
if (output) {
|
||||
output.textContent = message || '';
|
||||
output.className = 'us-password-strength' + (level ? ' is-' + level : '');
|
||||
}
|
||||
|
||||
field.setCustomValidity(acceptable ? '' : message || '');
|
||||
}
|
||||
|
||||
field.addEventListener('input', assess);
|
||||
field.addEventListener('blur', assess);
|
||||
|
||||
// The identity check depends on these, so a password typed first and an
|
||||
// email typed second is still caught.
|
||||
var sources = form.querySelectorAll('#us-reg-email, #us-reg-name');
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
sources[i].addEventListener('change', assess);
|
||||
}
|
||||
}
|
||||
|
||||
function enhanceSteps(form) {
|
||||
var step1 = form.querySelector('[data-step="1"]');
|
||||
var step2 = form.querySelector('[data-step="2"]');
|
||||
@@ -168,6 +271,7 @@
|
||||
: null;
|
||||
|
||||
enhanceGuardian(forms[i], steps);
|
||||
enhancePassword(forms[i]);
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user