diff --git a/assets/app.ts b/assets/app.ts index 5ac4b1c85..83aea3964 100644 --- a/assets/app.ts +++ b/assets/app.ts @@ -27,4 +27,5 @@ import './controllers/form_visite'; import './controllers/view_signalement'; import './controllers/cookie_banner'; import './controllers/maintenance_banner'; +import './controllers/activate_account/activate_account'; diff --git a/assets/controllers/activate_account/activate_account.js b/assets/controllers/activate_account/activate_account.js new file mode 100644 index 000000000..07bf21da4 --- /dev/null +++ b/assets/controllers/activate_account/activate_account.js @@ -0,0 +1,90 @@ +document?.querySelectorAll('.fr-password-toggle')?.forEach(pwdToggle => { + pwdToggle.addEventListeners('click touchdown', (event) => { + ['fr-fi-eye-off-fill', 'fr-fi-eye-fill'].map(c => { + event.target.classList.toggle(c); + }) + let pwd = event.target.parentElement.querySelector('[name^="password"]'); + "text" !== pwd.type ? pwd.type = "text" : pwd.type = "password"; + }) +}) +document?.querySelector('form[name="login-creation-mdp-form"]')?.querySelectorAll('[name^="password"]').forEach(pwd => { + pwd.addEventListener('input', canSubmitFormReinitPassword) +}) +document?.querySelector('form[name="login-creation-mdp-form"]')?.addEventListener('submit', (event) => { + event.preventDefault(); + const modalCgu = document.getElementById("fr-modal-cgu-bo"); + dsfr(modalCgu).modal.conceal(); + if(canSubmitFormReinitPassword()){ + event.target.submit(); + } +}) + +function canSubmitFormReinitPassword() { + const pass = document?.querySelector('form[name="login-creation-mdp-form"] #login-password').value; + const repeat = document?.querySelector('form[name="login-creation-mdp-form"] #login-password-repeat').value; + const pwdMatchError = document?.querySelector('form[name="login-creation-mdp-form"] #password-match-error'); + const submitBtn = document?.querySelector('form[name="login-creation-mdp-form"] #submitter'); + const messageLength = document?.querySelector('form[name="login-creation-mdp-form"] #password-input-message-info-length'); + const messageMaj = document?.querySelector('form[name="login-creation-mdp-form"] #password-input-message-info-maj'); + const messageMin = document?.querySelector('form[name="login-creation-mdp-form"] #password-input-message-info-min'); + const messageNb = document?.querySelector('form[name="login-creation-mdp-form"] #password-input-message-info-nb'); + const messageSpecial = document?.querySelector('form[name="login-creation-mdp-form"] #password-input-message-info-special'); + const groupInputPassword = document?.querySelector('form[name="login-creation-mdp-form"] .fr-input-group-password'); + const groupInputPasswordRepeat = document?.querySelector('form[name="login-creation-mdp-form"] .fr-input-group-password-repeat'); + let canSubmit = true; + pwdMatchError.classList.add('fr-hidden') + submitBtn.disabled = false; + if (pass !== repeat) { + canSubmit = false; + pwdMatchError.classList.remove('fr-hidden') + } + if (pass.length < 8) { + messageLength.classList.remove('fr-message--info', 'fr-message--valid') + messageLength.classList.add('fr-message--error') + canSubmit = false; + }else{ + messageLength.classList.remove('fr-message--info', 'fr-message--valid') + messageLength.classList.add('fr-message--valid') + } + if (!/[A-Z]/.test(pass)) { + messageMaj.classList.remove('fr-message--info', 'fr-message--valid') + messageMaj.classList.add('fr-message--error') + canSubmit = false; + }else{ + messageMaj.classList.remove('fr-message--info', 'fr-message--valid') + messageMaj.classList.add('fr-message--valid') + } + if(!/[a-z]/.test(pass)){ + messageMin.classList.remove('fr-message--info', 'fr-message--valid') + messageMin.classList.add('fr-message--error') + canSubmit = false; + }else{ + messageMin.classList.remove('fr-message--info', 'fr-message--valid') + messageMin.classList.add('fr-message--valid') + } + if(!/[0-9]/.test(pass)){ + messageNb.classList.remove('fr-message--info', 'fr-message--valid') + messageNb.classList.add('fr-message--error') + canSubmit = false; + }else{ + messageNb.classList.remove('fr-message--info', 'fr-message--valid') + messageNb.classList.add('fr-message--valid') + } + if(!/[^a-zA-Z0-9]/.test(pass)){ + messageSpecial.classList.remove('fr-message--info', 'fr-message--valid') + messageSpecial.classList.add('fr-message--error') + canSubmit = false; + }else{ + messageSpecial.classList.remove('fr-message--info', 'fr-message--valid') + messageSpecial.classList.add('fr-message--valid') + } + if(!canSubmit){ + groupInputPassword.classList.add('fr-input-group--error') + groupInputPasswordRepeat.classList.add('fr-input-group--error') + submitBtn.disabled = true; + }else{ + groupInputPassword.classList.remove('fr-input-group--error') + groupInputPasswordRepeat.classList.remove('fr-input-group--error') + } + return canSubmit; +} \ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js index 0c66fb1ae..052cc88b0 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -953,42 +953,7 @@ document?.querySelectorAll('[data-delete]')?.forEach(actionBtn => { } }) }); -document?.querySelectorAll('.fr-password-toggle')?.forEach(pwdToggle => { - pwdToggle.addEventListeners('click touchdown', (event) => { - ['fr-fi-eye-off-fill', 'fr-fi-eye-fill'].map(c => { - event.target.classList.toggle(c); - }) - let pwd = event.target.parentElement.querySelector('[name^="password"]'); - "text" !== pwd.type ? pwd.type = "text" : pwd.type = "password"; - }) -}) -document?.querySelector('form[name="login-creation-mdp-form"]')?.querySelectorAll('[name^="password"]').forEach(pwd => { - pwd.addEventListener('input', () => { - let pass = document?.querySelector('form[name="login-creation-mdp-form"] #login-password').value; - let repeat = document?.querySelector('form[name="login-creation-mdp-form"] #login-password-repeat').value; - let pwdMatchError = document?.querySelector('form[name="login-creation-mdp-form"] #password-match-error'); - let submitBtn = document?.querySelector('form[name="login-creation-mdp-form"] #submitter'); - submitBtn.addEventListener('click', (e) => { - e.preventDefault() - }) - if (pass !== repeat) { - document?.querySelector('form[name="login-creation-mdp-form"]').querySelectorAll('.fr-input-group').forEach(iptGroup => { - iptGroup.classList.add('fr-input-group--error') - iptGroup.querySelector('.fr-input').classList.add('fr-input--error') - }) - submitBtn.disabled = true; - pwdMatchError.classList.remove('fr-hidden') - } else { - document?.querySelector('form[name="login-creation-mdp-form"]').querySelectorAll('.fr-input-group--error,.fr-input--error').forEach(iptError => { - ['fr-input-group--error', 'fr-input--error'].map(c => { - iptError.classList.remove(c) - }); - }) - pwdMatchError.classList.add('fr-hidden'); - submitBtn.disabled = false; - } - }) -}) + document.querySelector('#modal-dpe-opener')?.addEventListener('click', (event) => { let urlDpe = event.target.getAttribute('data-dpe-url'); fetch(urlDpe).then(r => { diff --git a/src/Command/AddUserCommand.php b/src/Command/AddUserCommand.php index 47d0e1cf2..335d7e703 100644 --- a/src/Command/AddUserCommand.php +++ b/src/Command/AddUserCommand.php @@ -192,9 +192,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int ); } - $password = $this->hasher->hashPassword($user, 'histologe'); - - $user->setPassword($password)->setStatut(User::STATUS_ACTIVE); + $user->setPassword('histologe-HI1')->setStatut(User::STATUS_ACTIVE); /** @var ConstraintViolationList $errors */ $errors = $this->validator->validate($user, null, ['Default', 'password']); @@ -205,6 +203,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::FAILURE; } + $password = $this->hasher->hashPassword($user, $user->getPassword()); + $user->setPassword($password); + $this->entityManager->persist($user); $this->entityManager->flush(); diff --git a/src/Entity/User.php b/src/Entity/User.php index 409ba8e23..ba22890ea 100755 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -60,9 +60,13 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\Column(type: 'string', nullable: true)] #[Assert\NotBlank(groups: ['password'])] - #[Assert\Length(min: 8, max: 200, minMessage: 'Votre mot de passe doit contenir au moins {{ limit }} caratères', groups: ['password'])] + #[Assert\Length(min: 8, max: 200, minMessage: 'Le mot de passe doit contenir au moins {{ limit }} caratères.', groups: ['password'])] + #[Assert\Regex(pattern: '/[A-Z]/', message: 'Le mot de passe doit contenir au moins une lettre majuscule.', groups: ['password'])] + #[Assert\Regex(pattern: '/[a-z]/', message: 'Le mot de passe doit contenir au moins une lettre minuscule.', groups: ['password'])] + #[Assert\Regex(pattern: '/[0-9]/', message: 'Le mot de passe doit contenir au moins un chiffre.', groups: ['password'])] + #[Assert\Regex(pattern: '/[^a-zA-Z0-9]/', message: 'Le mot de passe doit contenir au moins un caractère spécial.', groups: ['password'])] #[Assert\NotCompromisedPassword(message: 'Ce mot de passe est compromis, veuillez en choisir un autre.', groups: ['password'])] - #[Assert\NotEqualTo(propertyPath: 'email', message: 'Votre mot de passe ne doit pas contenir votre email.', groups: ['password'])] + #[Assert\NotEqualTo(propertyPath: 'email', message: 'Le mot de passe ne doit pas être votre email.', groups: ['password'])] private $password; #[ORM\Column(length: 255, nullable: true)] diff --git a/templates/security/reset_password_new.html.twig b/templates/security/reset_password_new.html.twig index 7e88a04ce..629dc3a3a 100644 --- a/templates/security/reset_password_new.html.twig +++ b/templates/security/reset_password_new.html.twig @@ -24,7 +24,7 @@ {% endif %} -