forked from brooksbingham/theme-elegance
199 lines
6.4 KiB
JavaScript
199 lines
6.4 KiB
JavaScript
/**
|
|
* Copyright since 2007 PrestaShop SA and Contributors
|
|
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
|
*
|
|
* NOTICE OF LICENSE
|
|
*
|
|
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
|
* that is bundled with this package in the file LICENSE.md.
|
|
* It is also available through the world-wide-web at this URL:
|
|
* https://opensource.org/licenses/AFL-3.0
|
|
* If you did not receive a copy of the license and are unable to
|
|
* obtain it through the world-wide-web, please send an email
|
|
* to license@prestashop.com so we can send you a copy immediately.
|
|
*
|
|
* DISCLAIMER
|
|
*
|
|
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
|
* versions in the future. If you wish to customize PrestaShop for your
|
|
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
|
*
|
|
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
|
* @copyright Since 2007 PrestaShop SA and Contributors
|
|
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
|
*/
|
|
|
|
import {sprintf} from 'sprintf-js';
|
|
|
|
const {passwordPolicy: PasswordPolicyMap} = prestashop.themeSelectors;
|
|
|
|
const PASSWORD_POLICY_ERROR = 'The password policy elements are undefined.';
|
|
|
|
const getPasswordStrengthFeedback = (
|
|
strength,
|
|
) => {
|
|
switch (strength) {
|
|
case 0:
|
|
return {
|
|
color: 'bg-danger',
|
|
};
|
|
|
|
case 1:
|
|
return {
|
|
color: 'bg-danger',
|
|
};
|
|
|
|
case 2:
|
|
return {
|
|
color: 'bg-warning',
|
|
};
|
|
|
|
case 3:
|
|
return {
|
|
color: 'bg-success',
|
|
};
|
|
|
|
case 4:
|
|
return {
|
|
color: 'bg-success',
|
|
};
|
|
|
|
default:
|
|
throw new Error('Invalid password strength indicator.');
|
|
}
|
|
};
|
|
|
|
const watchPassword = async (
|
|
elementInput,
|
|
feedbackContainer,
|
|
hints,
|
|
) => {
|
|
const {prestashop} = window;
|
|
const passwordValue = elementInput.value;
|
|
const elementIcon = feedbackContainer.querySelector(PasswordPolicyMap.requirementScoreIcon);
|
|
const result = await prestashop.checkPasswordScore(passwordValue);
|
|
const feedback = getPasswordStrengthFeedback(result.score);
|
|
const passwordLength = passwordValue.length;
|
|
const popoverContent = [];
|
|
|
|
$(elementInput).popover('dispose');
|
|
|
|
feedbackContainer.style.display = passwordValue === '' ? 'none' : 'block';
|
|
|
|
if (result.feedback.warning !== '') {
|
|
if (result.feedback.warning in hints) {
|
|
popoverContent.push(hints[result.feedback.warning]);
|
|
}
|
|
}
|
|
|
|
result.feedback.suggestions.forEach((suggestion) => {
|
|
if (suggestion in hints) {
|
|
popoverContent.push(hints[suggestion]);
|
|
}
|
|
});
|
|
|
|
$(elementInput).popover({
|
|
html: true,
|
|
placement: 'top',
|
|
content: popoverContent.join('<br/>'),
|
|
}).popover('show');
|
|
|
|
const passwordLengthValid = passwordLength >= parseInt(elementInput.dataset.minlength, 10)
|
|
&& passwordLength <= parseInt(elementInput.dataset.maxlength, 10);
|
|
const passwordScoreValid = parseInt(elementInput.dataset.minscore, 10) <= result.score;
|
|
|
|
feedbackContainer.querySelector(PasswordPolicyMap.requirementLengthIcon).classList.toggle(
|
|
'text-success',
|
|
passwordLengthValid,
|
|
);
|
|
|
|
elementIcon.classList.toggle(
|
|
'text-success',
|
|
passwordScoreValid,
|
|
);
|
|
|
|
// Change input border color depending on the validity
|
|
elementInput
|
|
.classList.remove('border-success', 'border-danger');
|
|
elementInput
|
|
.classList.add(passwordScoreValid && passwordLengthValid ? 'border-success' : 'border-danger');
|
|
elementInput
|
|
.classList.add('form-control', 'border');
|
|
|
|
const percentage = (result.score * 20) + 20;
|
|
const progressBar = feedbackContainer.querySelector(PasswordPolicyMap.progressBar);
|
|
|
|
// increase and decrease progress bar
|
|
if (progressBar) {
|
|
progressBar.style.width = `${percentage}%`;
|
|
progressBar.classList.remove('bg-success', 'bg-danger', 'bg-warning');
|
|
progressBar.classList.add(feedback.color);
|
|
}
|
|
};
|
|
|
|
// Not testable because it manipulates SVG elements, unsupported by JSDom
|
|
const usePasswordPolicy = (selector) => {
|
|
const elements = document.querySelectorAll(selector);
|
|
elements.forEach((element) => {
|
|
const inputColumn = element?.querySelector(PasswordPolicyMap.inputColumn);
|
|
const elementInput = element?.querySelector('input');
|
|
const templateElement = document.createElement('div');
|
|
const feedbackTemplate = document.querySelector(PasswordPolicyMap.template);
|
|
let feedbackContainer;
|
|
|
|
if (feedbackTemplate && element && inputColumn && elementInput) {
|
|
templateElement.innerHTML = feedbackTemplate.innerHTML;
|
|
inputColumn.append(templateElement);
|
|
feedbackContainer = element.querySelector(PasswordPolicyMap.container);
|
|
|
|
if (feedbackContainer) {
|
|
const hintElement = document.querySelector(PasswordPolicyMap.hint);
|
|
|
|
if (hintElement) {
|
|
const hints = JSON.parse(hintElement.innerHTML);
|
|
|
|
// eslint-disable-next-line max-len
|
|
const passwordRequirementsLength = feedbackContainer.querySelector(PasswordPolicyMap.requirementLength);
|
|
// eslint-disable-next-line max-len
|
|
const passwordRequirementsScore = feedbackContainer.querySelector(PasswordPolicyMap.requirementScore);
|
|
const passwordLengthText = passwordRequirementsLength?.querySelector('span');
|
|
const passwordRequirementsText = passwordRequirementsScore?.querySelector('span');
|
|
|
|
if (passwordLengthText && passwordRequirementsLength && passwordRequirementsLength.dataset.translation) {
|
|
passwordLengthText.innerText = sprintf(
|
|
passwordRequirementsLength.dataset.translation,
|
|
elementInput.dataset.minlength,
|
|
elementInput.dataset.maxlength,
|
|
);
|
|
}
|
|
|
|
if (passwordRequirementsText && passwordRequirementsScore && passwordRequirementsScore.dataset.translation) {
|
|
passwordRequirementsText.innerText = sprintf(
|
|
passwordRequirementsScore.dataset.translation,
|
|
hints[elementInput.dataset.minscore],
|
|
);
|
|
}
|
|
|
|
// eslint-disable-next-line max-len
|
|
elementInput.addEventListener('keyup', () => watchPassword(elementInput, feedbackContainer, hints));
|
|
elementInput.addEventListener('blur', () => {
|
|
$(elementInput).popover('dispose');
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (element) {
|
|
return {
|
|
element,
|
|
};
|
|
}
|
|
|
|
return {
|
|
error: new Error(PASSWORD_POLICY_ERROR),
|
|
};
|
|
});
|
|
};
|
|
|
|
export default usePasswordPolicy;
|