Skip to content

Commit c22f7b7

Browse files
committed
Merge branch '6.2' into 6.3
* 6.2: Remove 6.0 and 6.1 from the PR template [Validator] Make ConstraintValidatorTestCase compatible with PHPUnit 10 [WebProfilerBundle] Fix some minor HTML issues [WebProfilerBundle] Disable Turbo for debug toolbar links [WebProfilerBundle] Fix an accessibility issue in the search form of the header [Mailer][MailPace] Fix undefined key in error response [Form] Fix PasswordHasherListener to work with empty data [PropertyInfo] Add meaningful message when `phpstan/phpdoc-parser` is not installed when using `PhpStanExtractor`
2 parents b5a3907 + cfb099e commit c22f7b7

File tree

2 files changed

+74
-20
lines changed

2 files changed

+74
-20
lines changed

Extension/PasswordHasher/EventListener/PasswordHasherListener.php

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
use Symfony\Component\Form\Exception\InvalidConfigurationException;
1515
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
1616
use Symfony\Component\Form\FormEvent;
17+
use Symfony\Component\Form\FormInterface;
1718
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
1819
use Symfony\Component\PropertyAccess\PropertyAccess;
1920
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
2021
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
2122

2223
/**
2324
* @author Sébastien Alfaiate <[email protected]>
25+
* @author Gábor Egyed <[email protected]>
2426
*/
2527
class PasswordHasherListener
2628
{
@@ -35,26 +37,11 @@ public function __construct(
3537

3638
public function registerPassword(FormEvent $event)
3739
{
38-
$form = $event->getForm();
39-
$parentForm = $form->getParent();
40-
$mapped = $form->getConfig()->getMapped();
41-
42-
if ($parentForm && $parentForm->getConfig()->getType()->getInnerType() instanceof RepeatedType) {
43-
$mapped = $parentForm->getConfig()->getMapped();
44-
$parentForm = $parentForm->getParent();
45-
}
46-
47-
if ($mapped) {
48-
throw new InvalidConfigurationException('The "hash_property_path" option cannot be used on mapped field.');
49-
}
50-
51-
if (!($user = $parentForm?->getData()) || !$user instanceof PasswordAuthenticatedUserInterface) {
52-
throw new InvalidConfigurationException(sprintf('The "hash_property_path" option only supports "%s" objects, "%s" given.', PasswordAuthenticatedUserInterface::class, get_debug_type($user)));
53-
}
40+
$this->assertNotMapped($event->getForm());
5441

5542
$this->passwords[] = [
56-
'user' => $user,
57-
'property_path' => $form->getConfig()->getOption('hash_property_path'),
43+
'form' => $event->getForm(),
44+
'property_path' => $event->getForm()->getConfig()->getOption('hash_property_path'),
5845
'password' => $event->getData(),
5946
];
6047
}
@@ -69,14 +56,45 @@ public function hashPasswords(FormEvent $event)
6956

7057
if ($form->isValid()) {
7158
foreach ($this->passwords as $password) {
59+
$user = $this->getUser($password['form']);
60+
7261
$this->propertyAccessor->setValue(
73-
$password['user'],
62+
$user,
7463
$password['property_path'],
75-
$this->passwordHasher->hashPassword($password['user'], $password['password'])
64+
$this->passwordHasher->hashPassword($user, $password['password'])
7665
);
7766
}
7867
}
7968

8069
$this->passwords = [];
8170
}
71+
72+
private function getTargetForm(FormInterface $form): FormInterface
73+
{
74+
$parent = $form->getParent();
75+
76+
if ($parent && $parent->getConfig()->getType()->getInnerType() instanceof RepeatedType) {
77+
return $parent;
78+
}
79+
80+
return $form;
81+
}
82+
83+
private function getUser(FormInterface $form): PasswordAuthenticatedUserInterface
84+
{
85+
$parent = $this->getTargetForm($form)->getParent();
86+
87+
if (!($user = $parent?->getData()) || !$user instanceof PasswordAuthenticatedUserInterface) {
88+
throw new InvalidConfigurationException(sprintf('The "hash_property_path" option only supports "%s" objects, "%s" given.', PasswordAuthenticatedUserInterface::class, get_debug_type($user)));
89+
}
90+
91+
return $user;
92+
}
93+
94+
private function assertNotMapped(FormInterface $form): void
95+
{
96+
if ($this->getTargetForm($form)->getConfig()->getMapped()) {
97+
throw new InvalidConfigurationException('The "hash_property_path" option cannot be used on mapped field.');
98+
}
99+
}
82100
}

Tests/Extension/PasswordHasher/Type/PasswordTypePasswordHasherExtensionTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,42 @@ public function testPasswordHashSuccess()
7777
$this->assertSame($user->getPassword(), $hashedPassword);
7878
}
7979

80+
public function testPasswordHashSuccessWitnEmptyData()
81+
{
82+
$user = new User();
83+
84+
$plainPassword = 'PlainPassword';
85+
$hashedPassword = 'HashedPassword';
86+
87+
$this->passwordHasher
88+
->expects($this->once())
89+
->method('hashPassword')
90+
->with($user, $plainPassword)
91+
->willReturn($hashedPassword)
92+
;
93+
94+
$this->assertNull($user->getPassword());
95+
96+
$form = $this->factory
97+
->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, [
98+
'data_class' => User::class,
99+
'empty_data' => function () use ($user) {
100+
return $user;
101+
},
102+
])
103+
->add('plainPassword', 'Symfony\Component\Form\Extension\Core\Type\PasswordType', [
104+
'hash_property_path' => 'password',
105+
'mapped' => false,
106+
])
107+
->getForm()
108+
;
109+
110+
$form->submit(['plainPassword' => $plainPassword]);
111+
112+
$this->assertTrue($form->isValid());
113+
$this->assertSame($user->getPassword(), $hashedPassword);
114+
}
115+
80116
public function testPasswordHashOnInvalidForm()
81117
{
82118
$user = new User();

0 commit comments

Comments
 (0)