Skip to content

Commit c0d50c5

Browse files
committed
Refactored the update of the hashed password and canonical fields
The responsibility of updating these fields is moved to dedicated services instead of being in the UserManager, allowing to inject them in the Doctrine listener and the validator initializer without any issue about circular dependencies.
1 parent 9c64d6f commit c0d50c5

18 files changed

+366
-243
lines changed

.php_cs

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ return Symfony\CS\Config\Config::create()
2929
'ordered_use',
3030
'php_unit_construct',
3131
'php_unit_strict',
32+
'-phpdoc_no_empty_return',
3233
))
3334
->setUsingCache(true)
3435
->finder($finder)

Doctrine/CouchDB/UserListener.php

+9-24
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,18 @@
1515
use Doctrine\ODM\CouchDB\Event;
1616
use Doctrine\ODM\CouchDB\Event\LifecycleEventArgs;
1717
use FOS\UserBundle\Model\UserInterface;
18-
use FOS\UserBundle\Model\UserManagerInterface;
19-
use Symfony\Component\DependencyInjection\ContainerInterface;
18+
use FOS\UserBundle\Util\CanonicalFieldsUpdater;
19+
use FOS\UserBundle\Util\PasswordUpdaterInterface;
2020

2121
class UserListener implements EventSubscriber
2222
{
23-
/**
24-
* @var UserManagerInterface
25-
*/
26-
private $userManager;
27-
28-
/**
29-
* @var ContainerInterface
30-
*/
31-
private $container;
23+
private $passwordUpdater;
24+
private $canonicalFieldsUpdater;
3225

33-
/**
34-
* Constructor.
35-
*
36-
* @param ContainerInterface $container
37-
*/
38-
public function __construct(ContainerInterface $container)
26+
public function __construct(PasswordUpdaterInterface $passwordUpdater, CanonicalFieldsUpdater $canonicalFieldsUpdater)
3927
{
40-
$this->container = $container;
28+
$this->passwordUpdater = $passwordUpdater;
29+
$this->canonicalFieldsUpdater = $canonicalFieldsUpdater;
4130
}
4231

4332
/**
@@ -80,11 +69,7 @@ public function preUpdate(LifecycleEventArgs $args)
8069
*/
8170
private function updateUserFields(UserInterface $user)
8271
{
83-
if (null === $this->userManager) {
84-
$this->userManager = $this->container->get('fos_user.user_manager');
85-
}
86-
87-
$this->userManager->updateCanonicalFields($user);
88-
$this->userManager->updatePassword($user);
72+
$this->canonicalFieldsUpdater->updateCanonicalFields($user);
73+
$this->passwordUpdater->hashPassword($user);
8974
}
9075
}

Doctrine/UserListener.php

+9-24
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
use Doctrine\ODM\MongoDB\DocumentManager;
1818
use Doctrine\ORM\EntityManager;
1919
use FOS\UserBundle\Model\UserInterface;
20-
use FOS\UserBundle\Model\UserManagerInterface;
21-
use Symfony\Component\DependencyInjection\ContainerInterface;
20+
use FOS\UserBundle\Util\CanonicalFieldsUpdater;
21+
use FOS\UserBundle\Util\PasswordUpdaterInterface;
2222

2323
/**
2424
* Doctrine listener updating the canonical username and password fields.
@@ -28,24 +28,13 @@
2828
*/
2929
class UserListener implements EventSubscriber
3030
{
31-
/**
32-
* @var UserManagerInterface
33-
*/
34-
private $userManager;
35-
36-
/**
37-
* @var ContainerInterface
38-
*/
39-
private $container;
31+
private $passwordUpdater;
32+
private $canonicalFieldsUpdater;
4033

41-
/**
42-
* Constructor.
43-
*
44-
* @param ContainerInterface $container
45-
*/
46-
public function __construct(ContainerInterface $container)
34+
public function __construct(PasswordUpdaterInterface $passwordUpdater, CanonicalFieldsUpdater $canonicalFieldsUpdater)
4735
{
48-
$this->container = $container;
36+
$this->passwordUpdater = $passwordUpdater;
37+
$this->canonicalFieldsUpdater = $canonicalFieldsUpdater;
4938
}
5039

5140
/**
@@ -93,12 +82,8 @@ public function preUpdate(LifecycleEventArgs $args)
9382
*/
9483
private function updateUserFields(UserInterface $user)
9584
{
96-
if (null === $this->userManager) {
97-
$this->userManager = $this->container->get('fos_user.user_manager');
98-
}
99-
100-
$this->userManager->updateCanonicalFields($user);
101-
$this->userManager->updatePassword($user);
85+
$this->canonicalFieldsUpdater->updateCanonicalFields($user);
86+
$this->passwordUpdater->hashPassword($user);
10287
}
10388

10489
/**

Doctrine/UserManager.php

+8-9
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
use Doctrine\Common\Persistence\ObjectRepository;
1616
use FOS\UserBundle\Model\UserInterface;
1717
use FOS\UserBundle\Model\UserManager as BaseUserManager;
18-
use FOS\UserBundle\Util\CanonicalizerInterface;
19-
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
18+
use FOS\UserBundle\Util\CanonicalFieldsUpdater;
19+
use FOS\UserBundle\Util\PasswordUpdaterInterface;
2020

2121
class UserManager extends BaseUserManager
2222
{
@@ -38,15 +38,14 @@ class UserManager extends BaseUserManager
3838
/**
3939
* Constructor.
4040
*
41-
* @param EncoderFactoryInterface $encoderFactory
42-
* @param CanonicalizerInterface $usernameCanonicalizer
43-
* @param CanonicalizerInterface $emailCanonicalizer
44-
* @param ObjectManager $om
45-
* @param string $class
41+
* @param PasswordUpdaterInterface $passwordUpdater
42+
* @param CanonicalFieldsUpdater $canonicalFieldsUpdater
43+
* @param ObjectManager $om
44+
* @param string $class
4645
*/
47-
public function __construct(EncoderFactoryInterface $encoderFactory, CanonicalizerInterface $usernameCanonicalizer, CanonicalizerInterface $emailCanonicalizer, ObjectManager $om, $class)
46+
public function __construct(PasswordUpdaterInterface $passwordUpdater, CanonicalFieldsUpdater $canonicalFieldsUpdater, ObjectManager $om, $class)
4847
{
49-
parent::__construct($encoderFactory, $usernameCanonicalizer, $emailCanonicalizer);
48+
parent::__construct($passwordUpdater, $canonicalFieldsUpdater);
5049

5150
$this->objectManager = $om;
5251
$this->repository = $om->getRepository($class);

Model/UserManager.php

+11-71
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111

1212
namespace FOS\UserBundle\Model;
1313

14-
use FOS\UserBundle\Util\CanonicalizerInterface;
15-
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
16-
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
14+
use FOS\UserBundle\Util\CanonicalFieldsUpdater;
15+
use FOS\UserBundle\Util\PasswordUpdaterInterface;
1716

1817
/**
1918
* Abstract User Manager implementation which can be used as base class for your
@@ -23,33 +22,13 @@
2322
*/
2423
abstract class UserManager implements UserManagerInterface
2524
{
26-
/**
27-
* @var EncoderFactoryInterface
28-
*/
29-
protected $encoderFactory;
25+
private $passwordUpdater;
26+
private $canonicalFieldsUpdater;
3027

31-
/**
32-
* @var CanonicalizerInterface
33-
*/
34-
protected $usernameCanonicalizer;
35-
36-
/**
37-
* @var CanonicalizerInterface
38-
*/
39-
protected $emailCanonicalizer;
40-
41-
/**
42-
* Constructor.
43-
*
44-
* @param EncoderFactoryInterface $encoderFactory
45-
* @param CanonicalizerInterface $usernameCanonicalizer
46-
* @param CanonicalizerInterface $emailCanonicalizer
47-
*/
48-
public function __construct(EncoderFactoryInterface $encoderFactory, CanonicalizerInterface $usernameCanonicalizer, CanonicalizerInterface $emailCanonicalizer)
28+
public function __construct(PasswordUpdaterInterface $passwordUpdater, CanonicalFieldsUpdater $canonicalFieldsUpdater)
4929
{
50-
$this->encoderFactory = $encoderFactory;
51-
$this->usernameCanonicalizer = $usernameCanonicalizer;
52-
$this->emailCanonicalizer = $emailCanonicalizer;
30+
$this->passwordUpdater = $passwordUpdater;
31+
$this->canonicalFieldsUpdater = $canonicalFieldsUpdater;
5332
}
5433

5534
/**
@@ -68,15 +47,15 @@ public function createUser()
6847
*/
6948
public function findUserByEmail($email)
7049
{
71-
return $this->findUserBy(array('emailCanonical' => $this->canonicalizeEmail($email)));
50+
return $this->findUserBy(array('emailCanonical' => $this->canonicalFieldsUpdater->canonicalizeEmail($email)));
7251
}
7352

7453
/**
7554
* {@inheritdoc}
7655
*/
7756
public function findUserByUsername($username)
7857
{
79-
return $this->findUserBy(array('usernameCanonical' => $this->canonicalizeUsername($username)));
58+
return $this->findUserBy(array('usernameCanonical' => $this->canonicalFieldsUpdater->canonicalizeUsername($username)));
8059
}
8160

8261
/**
@@ -104,53 +83,14 @@ public function findUserByConfirmationToken($token)
10483
*/
10584
public function updateCanonicalFields(UserInterface $user)
10685
{
107-
$user->setUsernameCanonical($this->canonicalizeUsername($user->getUsername()));
108-
$user->setEmailCanonical($this->canonicalizeEmail($user->getEmail()));
86+
$this->canonicalFieldsUpdater->updateCanonicalFields($user);
10987
}
11088

11189
/**
11290
* {@inheritdoc}
11391
*/
11492
public function updatePassword(UserInterface $user)
11593
{
116-
if (0 !== strlen($password = $user->getPlainPassword())) {
117-
$encoder = $this->getEncoder($user);
118-
$user->setPassword($encoder->encodePassword($password, $user->getSalt()));
119-
$user->eraseCredentials();
120-
}
121-
}
122-
123-
/**
124-
* Canonicalizes an email.
125-
*
126-
* @param string $email
127-
*
128-
* @return string
129-
*/
130-
protected function canonicalizeEmail($email)
131-
{
132-
return $this->emailCanonicalizer->canonicalize($email);
133-
}
134-
135-
/**
136-
* Canonicalizes a username.
137-
*
138-
* @param string $username
139-
*
140-
* @return string
141-
*/
142-
protected function canonicalizeUsername($username)
143-
{
144-
return $this->usernameCanonicalizer->canonicalize($username);
145-
}
146-
147-
/**
148-
* @param UserInterface $user
149-
*
150-
* @return PasswordEncoderInterface
151-
*/
152-
protected function getEncoder(UserInterface $user)
153-
{
154-
return $this->encoderFactory->getEncoder($user);
94+
$this->passwordUpdater->hashPassword($user);
15595
}
15696
}

Propel/UserManager.php

+7-8
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
use FOS\UserBundle\Model\UserInterface;
1515
use FOS\UserBundle\Model\UserManager as BaseUserManager;
16-
use FOS\UserBundle\Util\CanonicalizerInterface;
17-
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
16+
use FOS\UserBundle\Util\CanonicalFieldsUpdater;
17+
use FOS\UserBundle\Util\PasswordUpdaterInterface;
1818

1919
class UserManager extends BaseUserManager
2020
{
@@ -26,14 +26,13 @@ class UserManager extends BaseUserManager
2626
/**
2727
* Constructor.
2828
*
29-
* @param EncoderFactoryInterface $encoderFactory
30-
* @param CanonicalizerInterface $usernameCanonicalizer
31-
* @param CanonicalizerInterface $emailCanonicalizer
32-
* @param string $class
29+
* @param PasswordUpdaterInterface $passwordUpdater
30+
* @param CanonicalFieldsUpdater $canonicalFieldsUpdater
31+
* @param string $class
3332
*/
34-
public function __construct(EncoderFactoryInterface $encoderFactory, CanonicalizerInterface $usernameCanonicalizer, CanonicalizerInterface $emailCanonicalizer, $class)
33+
public function __construct(PasswordUpdaterInterface $passwordUpdater, CanonicalFieldsUpdater $canonicalFieldsUpdater, $class)
3534
{
36-
parent::__construct($encoderFactory, $usernameCanonicalizer, $emailCanonicalizer);
35+
parent::__construct($passwordUpdater, $canonicalFieldsUpdater);
3736

3837
$this->class = $class;
3938
}

Resources/config/doctrine.xml

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66

77
<services>
88
<service id="fos_user.user_manager.default" class="FOS\UserBundle\Doctrine\UserManager" public="false">
9-
<argument type="service" id="security.encoder_factory" />
10-
<argument type="service" id="fos_user.util.username_canonicalizer" />
11-
<argument type="service" id="fos_user.util.email_canonicalizer" />
9+
<argument type="service" id="fos_user.util.password_updater" />
10+
<argument type="service" id="fos_user.util.canonical_fields_updater" />
1211
<argument type="service" id="fos_user.object_manager" />
1312
<argument>%fos_user.model.user.class%</argument>
1413
</service>
@@ -19,7 +18,8 @@
1918
</service>
2019

2120
<service id="fos_user.user_listener" class="FOS\UserBundle\Doctrine\UserListener" public="false">
22-
<argument type="service" id="service_container" />
21+
<argument type="service" id="fos_user.util.password_updater" />
22+
<argument type="service" id="fos_user.util.canonical_fields_updater" />
2323
</service>
2424
</services>
2525

Resources/config/propel.xml

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66

77
<services>
88
<service id="fos_user.user_manager.default" class="FOS\UserBundle\Propel\UserManager" public="false">
9-
<argument type="service" id="security.encoder_factory" />
10-
<argument type="service" id="fos_user.util.username_canonicalizer" />
11-
<argument type="service" id="fos_user.util.email_canonicalizer" />
9+
<argument type="service" id="fos_user.util.password_updater" />
10+
<argument type="service" id="fos_user.util.canonical_fields_updater" />
1211
<argument>%fos_user.model.user.class%</argument>
1312
</service>
1413
</services>

Resources/config/util.xml

+10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@
1818
<argument type="service" id="logger" on-invalid="ignore" />
1919
</service>
2020

21+
<service id="fos_user.util.password_updater" class="FOS\UserBundle\Util\PasswordUpdater" public="false">
22+
<argument type="service" id="security.encoder_factory" />
23+
</service>
24+
25+
<service id="fos_user.util.canonical_fields_updater" class="FOS\UserBundle\Util\CanonicalFieldsUpdater" public="false">
26+
<argument type="service" id="fos_user.util.username_canonicalizer" />
27+
<argument type="service" id="fos_user.util.email_canonicalizer" />
28+
</service>
29+
30+
2131
</services>
2232

2333
</container>

Resources/config/validator.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<services>
88
<service id="fos_user.validator.initializer" class="FOS\UserBundle\Validator\Initializer" public="false">
99
<tag name="validator.initializer" />
10-
<argument type="service" id="fos_user.user_manager" />
10+
<argument type="service" id="fos_user.util.canonical_fields_updater" />
1111
</service>
1212
</services>
1313

0 commit comments

Comments
 (0)