forked from Sylius/Sylius
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Specify an listener to update the encoded password on login
- Loading branch information
Showing
4 changed files
with
321 additions
and
0 deletions.
There are no files selected for viewing
80 changes: 80 additions & 0 deletions
80
src/Sylius/Bundle/UserBundle/EventListener/UpdateUserEncoderListener.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Sylius package. | ||
* | ||
* (c) Paweł Jędrzejewski | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Sylius\Bundle\UserBundle\EventListener; | ||
|
||
use Doctrine\Common\Persistence\ObjectManager; | ||
use Sylius\Component\User\Model\UserInterface; | ||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; | ||
|
||
final class UpdateUserEncoderListener | ||
{ | ||
/** @var ObjectManager */ | ||
private $objectManager; | ||
|
||
/** @var string */ | ||
private $recommendedEncoderName; | ||
|
||
/** @var string */ | ||
private $className; | ||
|
||
/** @var string */ | ||
private $interfaceName; | ||
|
||
/** @var string */ | ||
private $passwordParameter; | ||
|
||
public function __construct( | ||
ObjectManager $objectManager, | ||
string $recommendedEncoderName, | ||
string $className, | ||
string $interfaceName, | ||
string $passwordParameter | ||
) { | ||
$this->objectManager = $objectManager; | ||
$this->recommendedEncoderName = $recommendedEncoderName; | ||
$this->className = $className; | ||
$this->interfaceName = $interfaceName; | ||
$this->passwordParameter = $passwordParameter; | ||
} | ||
|
||
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event): void | ||
{ | ||
$user = $event->getAuthenticationToken()->getUser(); | ||
|
||
if (!$user instanceof UserInterface) { | ||
return; | ||
} | ||
|
||
if (!$user instanceof $this->className || !$user instanceof $this->interfaceName) { | ||
return; | ||
} | ||
|
||
if ($user->getEncoderName() === $this->recommendedEncoderName) { | ||
return; | ||
} | ||
|
||
$request = $event->getRequest(); | ||
|
||
$plainPassword = $request->request->get($this->passwordParameter); | ||
if (null === $plainPassword || '' === $plainPassword) { | ||
return; | ||
} | ||
|
||
$user->setEncoderName($this->recommendedEncoderName); | ||
$user->setPlainPassword($plainPassword); | ||
|
||
$this->objectManager->persist($user); | ||
$this->objectManager->flush(); | ||
} | ||
} |
201 changes: 201 additions & 0 deletions
201
src/Sylius/Bundle/UserBundle/spec/EventListener/UpdateUserEncoderListenerSpec.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace spec\Sylius\Bundle\UserBundle\EventListener; | ||
|
||
use Doctrine\Common\Persistence\ObjectManager; | ||
use PhpSpec\ObjectBehavior; | ||
use Sylius\Bundle\UserBundle\spec\Fixture\FixtureUser; | ||
use Sylius\Bundle\UserBundle\spec\Fixture\FixtureUserInterface; | ||
use Sylius\Component\User\Model\User; | ||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; | ||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; | ||
|
||
final class UpdateUserEncoderListenerSpec extends ObjectBehavior | ||
{ | ||
function let(ObjectManager $objectManager): void | ||
{ | ||
$this->beConstructedWith($objectManager, 'newalgo', FixtureUser::class, FixtureUserInterface::class, '_password'); | ||
} | ||
|
||
function it_does_nothing_if_user_does_not_implement_user_interface( | ||
ObjectManager $objectManager, | ||
InteractiveLoginEvent $event, | ||
TokenInterface $token | ||
): void { | ||
$event->getAuthenticationToken()->willReturn($token); | ||
|
||
$user = new \stdClass(); | ||
|
||
$token->getUser()->willReturn($user); | ||
|
||
$objectManager->persist($user)->shouldNotBeCalled(); | ||
$objectManager->flush()->shouldNotBeCalled(); | ||
|
||
$this->onSecurityInteractiveLogin($event); | ||
} | ||
|
||
function it_does_nothing_if_user_does_not_implement_specified_class_or_interface( | ||
ObjectManager $objectManager, | ||
InteractiveLoginEvent $event, | ||
TokenInterface $token | ||
): void { | ||
$event->getAuthenticationToken()->willReturn($token); | ||
|
||
$user = new User(); | ||
|
||
$token->getUser()->willReturn($user); | ||
|
||
$objectManager->persist($user)->shouldNotBeCalled(); | ||
$objectManager->flush()->shouldNotBeCalled(); | ||
|
||
$this->onSecurityInteractiveLogin($event); | ||
} | ||
|
||
function it_does_nothing_if_user_uses_the_recommended_encoder( | ||
ObjectManager $objectManager, | ||
InteractiveLoginEvent $event, | ||
TokenInterface $token | ||
): void { | ||
$event->getAuthenticationToken()->willReturn($token); | ||
|
||
$user = new FixtureUser(); | ||
$user->setEncoderName('newalgo'); | ||
|
||
$token->getUser()->willReturn($user); | ||
|
||
$objectManager->persist($user)->shouldNotBeCalled(); | ||
$objectManager->flush()->shouldNotBeCalled(); | ||
|
||
$this->onSecurityInteractiveLogin($event); | ||
|
||
assert($user->getEncoderName() === 'newalgo'); | ||
assert($user->getPlainPassword() === null); | ||
} | ||
|
||
function it_does_nothing_if_plain_password_could_not_be_resolved( | ||
ObjectManager $objectManager, | ||
InteractiveLoginEvent $event, | ||
TokenInterface $token | ||
): void { | ||
$request = new Request(); | ||
|
||
$event->getAuthenticationToken()->willReturn($token); | ||
$event->getRequest()->willReturn($request); | ||
|
||
$user = new FixtureUser(); | ||
$user->setEncoderName('oldalgo'); | ||
|
||
$token->getUser()->willReturn($user); | ||
|
||
$objectManager->persist($user)->shouldNotBeCalled(); | ||
$objectManager->flush()->shouldNotBeCalled(); | ||
|
||
$this->onSecurityInteractiveLogin($event); | ||
|
||
assert($user->getEncoderName() === 'oldalgo'); | ||
assert($user->getPlainPassword() === null); | ||
} | ||
|
||
function it_does_nothing_if_resolved_plain_password_is_null( | ||
ObjectManager $objectManager, | ||
InteractiveLoginEvent $event, | ||
TokenInterface $token | ||
): void { | ||
$request = new Request(); | ||
$request->request->set('_password', null); | ||
|
||
$event->getAuthenticationToken()->willReturn($token); | ||
$event->getRequest()->willReturn($request); | ||
|
||
$user = new FixtureUser(); | ||
$user->setEncoderName('oldalgo'); | ||
|
||
$token->getUser()->willReturn($user); | ||
|
||
$objectManager->persist($user)->shouldNotBeCalled(); | ||
$objectManager->flush()->shouldNotBeCalled(); | ||
|
||
$this->onSecurityInteractiveLogin($event); | ||
|
||
assert($user->getEncoderName() === 'oldalgo'); | ||
assert($user->getPlainPassword() === null); | ||
} | ||
|
||
function it_does_nothing_if_resolved_plain_password_is_empty( | ||
ObjectManager $objectManager, | ||
InteractiveLoginEvent $event, | ||
TokenInterface $token | ||
): void { | ||
$request = new Request(); | ||
$request->request->set('_password', ''); | ||
|
||
$event->getAuthenticationToken()->willReturn($token); | ||
$event->getRequest()->willReturn($request); | ||
|
||
$user = new FixtureUser(); | ||
$user->setEncoderName('oldalgo'); | ||
|
||
$token->getUser()->willReturn($user); | ||
|
||
$objectManager->persist($user)->shouldNotBeCalled(); | ||
$objectManager->flush()->shouldNotBeCalled(); | ||
|
||
$this->onSecurityInteractiveLogin($event); | ||
|
||
assert($user->getEncoderName() === 'oldalgo'); | ||
assert($user->getPlainPassword() === null); | ||
} | ||
|
||
function it_updates_the_encoder_and_plain_password_if_using_old_encoder_and_plain_password_could_be_resolved( | ||
ObjectManager $objectManager, | ||
InteractiveLoginEvent $event, | ||
TokenInterface $token | ||
): void { | ||
$request = new Request(); | ||
$request->request->set('_password', 'plainpassword'); | ||
|
||
$event->getAuthenticationToken()->willReturn($token); | ||
$event->getRequest()->willReturn($request); | ||
|
||
$user = new FixtureUser(); | ||
$user->setEncoderName('oldalgo'); | ||
|
||
$token->getUser()->willReturn($user); | ||
|
||
$objectManager->persist($user)->shouldBeCalled(); | ||
$objectManager->flush()->shouldBeCalled(); | ||
|
||
$this->onSecurityInteractiveLogin($event); | ||
|
||
assert($user->getEncoderName() === 'newalgo'); | ||
assert($user->getPlainPassword() === 'plainpassword'); | ||
} | ||
|
||
function it_updates_the_encoder_and_plain_password_if_using_default_null_encoder_and_plain_password_could_be_resolved( | ||
ObjectManager $objectManager, | ||
InteractiveLoginEvent $event, | ||
TokenInterface $token | ||
): void { | ||
$request = new Request(); | ||
$request->request->set('_password', 'plainpassword'); | ||
|
||
$event->getAuthenticationToken()->willReturn($token); | ||
$event->getRequest()->willReturn($request); | ||
|
||
$user = new FixtureUser(); | ||
$user->setEncoderName(null); | ||
|
||
$token->getUser()->willReturn($user); | ||
|
||
$objectManager->persist($user)->shouldBeCalled(); | ||
$objectManager->flush()->shouldBeCalled(); | ||
|
||
$this->onSecurityInteractiveLogin($event); | ||
|
||
assert($user->getEncoderName() === 'newalgo'); | ||
assert($user->getPlainPassword() === 'plainpassword'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Sylius package. | ||
* | ||
* (c) Paweł Jędrzejewski | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Sylius\Bundle\UserBundle\spec\Fixture; | ||
|
||
use Sylius\Component\User\Model\User; | ||
|
||
final class FixtureUser extends User implements FixtureUserInterface | ||
{ | ||
} |
20 changes: 20 additions & 0 deletions
20
src/Sylius/Bundle/UserBundle/spec/Fixture/FixtureUserInterface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Sylius package. | ||
* | ||
* (c) Paweł Jędrzejewski | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Sylius\Bundle\UserBundle\spec\Fixture; | ||
|
||
use Sylius\Component\User\Model\UserInterface; | ||
|
||
interface FixtureUserInterface extends UserInterface | ||
{ | ||
} |