diff --git a/src/Action/LoginAction.php b/src/Action/LoginAction.php index 3d71bfd6..d6fa4776 100644 --- a/src/Action/LoginAction.php +++ b/src/Action/LoginAction.php @@ -14,15 +14,19 @@ namespace Nucleos\UserAdminBundle\Action; use Nucleos\UserBundle\Event\GetResponseLoginEvent; +use Nucleos\UserBundle\Form\Type\LoginFormType; use Nucleos\UserBundle\Model\UserInterface; use Nucleos\UserBundle\NucleosUserEvents; use Sonata\AdminBundle\Admin\Pool; use Sonata\AdminBundle\Templating\TemplateRegistryInterface; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; @@ -37,7 +41,7 @@ final class LoginAction private EventDispatcherInterface $eventDispatcher; - private UrlGeneratorInterface $urlGenerator; + private RouterInterface $router; private AuthorizationCheckerInterface $authorizationChecker; @@ -47,28 +51,28 @@ final class LoginAction private TokenStorageInterface $tokenStorage; - private Session $session; - private ?CsrfTokenManagerInterface $csrfTokenManager = null; + private FormFactoryInterface $formFactory; + public function __construct( Environment $twig, EventDispatcherInterface $eventDispatcher, - UrlGeneratorInterface $urlGenerator, + RouterInterface $router, AuthorizationCheckerInterface $authorizationChecker, Pool $adminPool, TemplateRegistryInterface $templateRegistry, TokenStorageInterface $tokenStorage, - Session $session + FormFactoryInterface $formFactory ) { $this->twig = $twig; $this->eventDispatcher = $eventDispatcher; - $this->urlGenerator = $urlGenerator; + $this->router = $router; $this->authorizationChecker = $authorizationChecker; $this->adminPool = $adminPool; $this->templateRegistry = $templateRegistry; $this->tokenStorage = $tokenStorage; - $this->session = $session; + $this->formFactory = $formFactory; } /** @@ -77,10 +81,12 @@ public function __construct( */ public function __invoke(Request $request): Response { + $session = $request->hasSession() ? $request->getSession() : null; + if ($this->isAuthenticated()) { - $this->session->getFlashBag()->add('nucleos_user_admin_error', 'nucleos_user_admin_already_authenticated'); + $this->addFlash($session, 'nucleos_user_admin_error', 'nucleos_user_admin_already_authenticated'); - return new RedirectResponse($this->urlGenerator->generate('sonata_admin_dashboard')); + return new RedirectResponse($this->router->generate('sonata_admin_dashboard')); } $event = new GetResponseLoginEvent($request); @@ -90,10 +96,7 @@ public function __invoke(Request $request): Response return $event->getResponse(); } - $session = $request->hasSession() ? $request->getSession() : null; - - $authErrorKey = Security::AUTHENTICATION_ERROR; - $lastUsernameKey = Security::LAST_USERNAME; + $authErrorKey = Security::AUTHENTICATION_ERROR; // get the error if any (works with forward and redirect -- see below) if ($request->attributes->has($authErrorKey)) { @@ -111,21 +114,31 @@ public function __invoke(Request $request): Response if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) { $refererUri = $request->server->get('HTTP_REFERER', ''); - $url = '' !== $refererUri && $refererUri !== $request->getUri() ? $refererUri : $this->urlGenerator->generate('sonata_admin_dashboard'); + $url = '' !== $refererUri && $refererUri !== $request->getUri() ? $refererUri : $this->router->generate('sonata_admin_dashboard'); return new RedirectResponse($url); } + $form = $this->formFactory + ->create(LoginFormType::class, null, [ + 'action' => $this->router->generate('nucleos_user_admin_security_check'), + 'method' => 'POST', + ]) + ->add('save', SubmitType::class, [ + 'label' => 'security.login.submit', + ]) + ; + // last username entered by the user - $lastUsername = (null === $session) ? '' : $session->get($lastUsernameKey); return new Response($this->twig->render('@NucleosUserAdmin/Admin/Security/login.html.twig', [ + 'form' => $form->createView(), 'admin_pool' => $this->adminPool, 'base_template' => $this->templateRegistry->getTemplate('layout'), 'csrf_token' => $this->getCsrfToken(), 'error' => $error, - 'last_username' => $lastUsername, - 'reset_route' => $this->urlGenerator->generate('nucleos_user_admin_resetting_request'), + 'last_username' => $this->getLastUsername($session), + 'reset_route' => $this->router->generate('nucleos_user_admin_resetting_request'), ])); } @@ -134,6 +147,11 @@ public function setCsrfTokenManager(CsrfTokenManagerInterface $csrfTokenManager) $this->csrfTokenManager = $csrfTokenManager; } + private function getLastUsername(?SessionInterface $session): ?string + { + return (null === $session) ? '' : $session->get(Security::LAST_USERNAME); + } + private function isAuthenticated(): bool { $token = $this->tokenStorage->getToken(); @@ -151,4 +169,13 @@ private function getCsrfToken(): ?string { return null !== $this->csrfTokenManager ? $this->csrfTokenManager->getToken('authenticate')->getValue() : null; } + + private function addFlash(?SessionInterface $session, string $type, string $message): void + { + if (!$session instanceof Session) { + return; + } + + $session->getFlashBag()->add($type, $message); + } } diff --git a/src/Action/RequestAction.php b/src/Action/RequestAction.php index 2840ff6f..f859051a 100644 --- a/src/Action/RequestAction.php +++ b/src/Action/RequestAction.php @@ -13,12 +13,14 @@ namespace Nucleos\UserAdminBundle\Action; +use Nucleos\UserBundle\Form\Type\RequestPasswordFormType; use Sonata\AdminBundle\Admin\Pool; use Sonata\AdminBundle\Templating\TemplateRegistryInterface; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Twig\Environment; @@ -26,7 +28,7 @@ final class RequestAction { private Environment $twig; - private UrlGeneratorInterface $urlGenerator; + private RouterInterface $router; private AuthorizationCheckerInterface $authorizationChecker; @@ -34,34 +36,39 @@ final class RequestAction private TemplateRegistryInterface $templateRegistry; + private FormFactoryInterface $formFactory; + public function __construct( Environment $twig, - UrlGeneratorInterface $urlGenerator, + RouterInterface $router, AuthorizationCheckerInterface $authorizationChecker, Pool $adminPool, - TemplateRegistryInterface $templateRegistry + TemplateRegistryInterface $templateRegistry, + FormFactoryInterface $formFactory ) { $this->twig = $twig; - $this->urlGenerator = $urlGenerator; + $this->router = $router; $this->authorizationChecker = $authorizationChecker; $this->adminPool = $adminPool; $this->templateRegistry = $templateRegistry; + $this->formFactory = $formFactory; } public function __invoke(Request $request): Response { if ($this->authorizationChecker->isGranted('IS_AUTHENTICATED_FULLY')) { - return new RedirectResponse($this->urlGenerator->generate('sonata_admin_dashboard')); + return new RedirectResponse($this->router->generate('sonata_admin_dashboard')); } - return new Response( - $this->twig->render( - '@NucleosUserAdmin/Admin/Security/Resetting/request.html.twig', - [ - 'base_template' => $this->templateRegistry->getTemplate('layout'), - 'admin_pool' => $this->adminPool, - ] - ) - ); + $form = $this->formFactory->create(RequestPasswordFormType::class, null, [ + 'action' => $this->router->generate('nucleos_user_admin_resetting_send_email'), + 'method' => 'POST', + ]); + + return new Response($this->twig->render('@NucleosUserAdmin/Admin/Security/Resetting/request.html.twig', [ + 'form' => $form->createView(), + 'base_template' => $this->templateRegistry->getTemplate('layout'), + 'admin_pool' => $this->adminPool, + ])); } } diff --git a/src/Action/ResetAction.php b/src/Action/ResetAction.php index 881b8804..729ecea5 100644 --- a/src/Action/ResetAction.php +++ b/src/Action/ResetAction.php @@ -29,7 +29,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Exception\AccountStatusException; use Symfony\Contracts\Translation\TranslatorInterface; @@ -41,7 +41,7 @@ final class ResetAction private Environment $twig; - private UrlGeneratorInterface $urlGenerator; + private RouterInterface $router; private AuthorizationCheckerInterface $authorizationChecker; @@ -68,7 +68,7 @@ final class ResetAction */ public function __construct( Environment $twig, - UrlGeneratorInterface $urlGenerator, + RouterInterface $router, AuthorizationCheckerInterface $authorizationChecker, Pool $adminPool, TemplateRegistryInterface $templateRegistry, @@ -81,7 +81,7 @@ public function __construct( string $firewallName ) { $this->twig = $twig; - $this->urlGenerator = $urlGenerator; + $this->router = $router; $this->authorizationChecker = $authorizationChecker; $this->adminPool = $adminPool; $this->templateRegistry = $templateRegistry; @@ -101,7 +101,7 @@ public function __construct( public function __invoke(Request $request, string $token): Response { if ($this->authorizationChecker->isGranted('IS_AUTHENTICATED_FULLY')) { - return new RedirectResponse($this->urlGenerator->generate('sonata_admin_dashboard')); + return new RedirectResponse($this->router->generate('sonata_admin_dashboard')); } $user = $this->userManager->findUserByConfirmationToken($token); @@ -113,10 +113,13 @@ public function __invoke(Request $request, string $token): Response } if (!$user->isPasswordRequestNonExpired($this->resetTtl)) { - return new RedirectResponse($this->urlGenerator->generate('nucleos_user_admin_resetting_request')); + return new RedirectResponse($this->router->generate('nucleos_user_admin_resetting_request')); } $form = $this->formFactory->create(ResettingFormType::class, new Resetting($user), [ + 'action' => $this->router->generate('nucleos_user_admin_security_check', [ + 'token' => $token, + ]), 'validation_groups' => ['ResetPassword', 'Default'], ]); @@ -128,24 +131,19 @@ public function __invoke(Request $request, string $token): Response $this->translator->trans('resetting.flash.success', [], 'NucleosUserBundle') ); - $response = new RedirectResponse($this->urlGenerator->generate('sonata_admin_dashboard')); + $response = new RedirectResponse($this->router->generate('sonata_admin_dashboard')); $this->resetUser($user, $response); return $response; } - return new Response( - $this->twig->render( - '@NucleosUserAdmin/Admin/Security/Resetting/reset.html.twig', - [ - 'token' => $token, - 'form' => $form->createView(), - 'base_template' => $this->templateRegistry->getTemplate('layout'), - 'admin_pool' => $this->adminPool, - ] - ) - ); + return new Response($this->twig->render('@NucleosUserAdmin/Admin/Security/Resetting/reset.html.twig', [ + 'token' => $token, + 'form' => $form->createView(), + 'base_template' => $this->templateRegistry->getTemplate('layout'), + 'admin_pool' => $this->adminPool, + ])); } public function setLogger(LoggerInterface $logger): void diff --git a/src/Resources/config/action.php b/src/Resources/config/action.php index e9d297a1..c42a9707 100644 --- a/src/Resources/config/action.php +++ b/src/Resources/config/action.php @@ -30,6 +30,7 @@ ref('security.authorization_checker'), ref('sonata.admin.pool'), ref('sonata.admin.global_template_registry'), + ref('form.factory'), ]) ->set(SendEmailAction::class) @@ -82,7 +83,7 @@ ref('sonata.admin.pool'), ref('sonata.admin.global_template_registry'), ref('security.token_storage'), - ref('session'), + ref('form.factory'), ]) ->call('setCsrfTokenManager', [ ref('security.csrf.token_manager')->ignoreOnInvalid(), diff --git a/src/Resources/views/Admin/Security/Resetting/request.html.twig b/src/Resources/views/Admin/Security/Resetting/request.html.twig index dc37e9c3..dc101bb8 100644 --- a/src/Resources/views/Admin/Security/Resetting/request.html.twig +++ b/src/Resources/views/Admin/Security/Resetting/request.html.twig @@ -1,23 +1,19 @@ {% extends '@NucleosUserAdmin/Admin/Security/layout.html.twig' %} +{% form_theme form 'bootstrap_3_layout.html.twig' %} + {% block login_box_content %}

{{ 'resetting.request.submit'|trans({}, 'NucleosUserBundle') }}

-
-
- - -
+ {{ form_start(form) }} + + {% set actions %}{{ form_widget(form.save, { attr: { class: 'btn btn-primary btn-block' } }) }}{% endset %} + + {{ form_widget(form) }} + + {{ actions }} -
-
- -
-
-
+ {{ form_end(form) }} {% endblock %} diff --git a/src/Resources/views/Admin/Security/Resetting/reset.html.twig b/src/Resources/views/Admin/Security/Resetting/reset.html.twig index 9c5d24fa..9897e9f8 100644 --- a/src/Resources/views/Admin/Security/Resetting/reset.html.twig +++ b/src/Resources/views/Admin/Security/Resetting/reset.html.twig @@ -1,13 +1,19 @@ {% extends '@NucleosUserAdmin/Admin/Security/layout.html.twig' %} +{% form_theme form 'bootstrap_3_layout.html.twig' %} + {% block login_box_content %}

{{ 'resetting.reset.submit'|trans({}, 'NucleosUserBundle') }}

- {{ form_start(form, { 'action': path('nucleos_user_admin_resetting_reset', {'token': token}) }) }} + {{ form_start(form) }} + + {% set actions %}{{ form_widget(form.save, { attr: { class: 'btn btn-primary btn-block' } }) }}{% endset %} {{ form_widget(form) }} + {{ actions }} + {{ form_end(form) }} -{% endblock sonata_wrapper %} +{% endblock login_box_content %} diff --git a/src/Resources/views/Admin/Security/layout.html.twig b/src/Resources/views/Admin/Security/layout.html.twig index 4c669648..c6fb013d 100644 --- a/src/Resources/views/Admin/Security/layout.html.twig +++ b/src/Resources/views/Admin/Security/layout.html.twig @@ -17,13 +17,13 @@ diff --git a/src/Resources/views/Admin/Security/login.html.twig b/src/Resources/views/Admin/Security/login.html.twig index 62386a80..55eae3f3 100644 --- a/src/Resources/views/Admin/Security/login.html.twig +++ b/src/Resources/views/Admin/Security/login.html.twig @@ -1,5 +1,9 @@ {% extends '@NucleosUserAdmin/Admin/Security/layout.html.twig' %} +{% trans_default_domain 'NucleosUserAdminBundle' %} + +{% form_theme form 'bootstrap_3_layout.html.twig' %} + {% block login_box_content %} {% block sonata_admin_login_error %} {% if error %} @@ -13,46 +17,19 @@ {{ 'title_user_authentication'|trans({}, 'NucleosUserAdminBundle') }}

-
- - -
- - -
- -
- - -
- -
-
-
- -
-
-
- -
-
-
+ {{ form_start(form) }} + + {% set actions %}{{ form_widget(form.save, { attr: { class: 'btn btn-primary btn-block' } }) }}{% endset %} + + {{ form_rest(form) }} + + {{ actions }} + + {{ form_end(form) }} - {{ 'forgotten_password'|trans({}, 'NucleosUserAdminBundle') }} +
+ + {{ 'forgotten_password'|trans }} + +
{% endblock %} diff --git a/tests/Action/LoginActionTest.php b/tests/Action/LoginActionTest.php index 1b0eb764..4bcd01f1 100644 --- a/tests/Action/LoginActionTest.php +++ b/tests/Action/LoginActionTest.php @@ -20,11 +20,12 @@ use PHPUnit\Framework\TestCase; use Sonata\AdminBundle\Admin\Pool; use Sonata\AdminBundle\Templating\TemplateRegistryInterface; +use Symfony\Component\Form\Form; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; @@ -47,9 +48,9 @@ final class LoginActionTest extends TestCase protected $eventDispatcher; /** - * @var MockObject&UrlGeneratorInterface + * @var MockObject&RouterInterface */ - protected $urlGenerator; + protected $router; /** * @var AuthorizationCheckerInterface&MockObject @@ -69,32 +70,30 @@ final class LoginActionTest extends TestCase protected $tokenStorage; /** - * @var MockObject&Session + * @var CsrfTokenManagerInterface&MockObject */ - protected $session; + protected $csrfTokenManager; /** - * @var CsrfTokenManagerInterface&MockObject + * @var MockObject&FormFactoryInterface */ - protected $csrfTokenManager; + private $formFactory; protected function setUp(): void { $this->templating = $this->createMock(Environment::class); $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); - $this->urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $this->router = $this->createMock(RouterInterface::class); $this->authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class); $this->pool = PoolMockFactory::create(); $this->templateRegistry = $this->createMock(TemplateRegistryInterface::class); $this->tokenStorage = $this->createMock(TokenStorageInterface::class); - $this->session = $this->createMock(Session::class); $this->csrfTokenManager = $this->createMock(CsrfTokenManagerInterface::class); + $this->formFactory = $this->createMock(FormFactoryInterface::class); } public function testAlreadyAuthenticated(): void { - $request = new Request(); - $user = $this->createMock(UserInterface::class); $token = $this->createMock(TokenInterface::class); @@ -108,18 +107,12 @@ public function testAlreadyAuthenticated(): void ->willReturn($token) ; - $bag = $this->createMock(FlashBag::class); - $bag->expects(static::once()) - ->method('add') - ->with('nucleos_user_admin_error', 'nucleos_user_admin_already_authenticated') - ; + $session = new Session(); - $this->session - ->method('getFlashBag') - ->willReturn($bag) - ; + $request = new Request(); + $request->setSession($session); - $this->urlGenerator + $this->router ->method('generate') ->with('sonata_admin_dashboard') ->willReturn('/foo') @@ -130,6 +123,10 @@ public function testAlreadyAuthenticated(): void static::assertInstanceOf(RedirectResponse::class, $result); static::assertSame('/foo', $result->getTargetUrl()); + + static::assertSame([ + 'nucleos_user_admin_error' => ['nucleos_user_admin_already_authenticated'], + ], $session->getFlashBag()->all()); } /** @@ -147,7 +144,7 @@ public function testUserGrantedAdmin(string $referer, string $expectedRedirectUr ->willReturn(null) ; - $this->urlGenerator + $this->router ->method('generate') ->with('sonata_admin_dashboard') ->willReturn('/foo') @@ -215,7 +212,8 @@ static function (string $key) use ($sessionParameters): bool { 'csrf_token' => 'csrf-token', 'error' => $errorMessage, 'last_username' => $lastUsername, - 'reset_route' => '/foo', + 'reset_route' => '/reset', + 'form' => 'Form View', ]; $csrfToken = $this->createMock(CsrfToken::class); @@ -229,10 +227,37 @@ static function (string $key) use ($sessionParameters): bool { ->willReturn(null) ; - $this->urlGenerator + $form = $this->createMock(Form::class); + $form + ->method('isValid') + ->willReturn(true) + ; + $form + ->method('isSubmitted') + ->willReturn(false) + ; + $form + ->method('add') + ->willReturnSelf() + ; + $form->expects(static::once()) + ->method('createView') + ->willReturn('Form View') + ; + + $this->formFactory->expects(static::once()) + ->method('create') + ->willReturn($form) + ; + + $this->router ->method('generate') - ->with('nucleos_user_admin_resetting_request') - ->willReturn('/foo') + ->withConsecutive([ + 'nucleos_user_admin_security_check', + ], [ + 'nucleos_user_admin_resetting_request', + ]) + ->willReturn('/check', '/reset') ; $this->authorizationChecker->expects(static::once()) @@ -280,12 +305,12 @@ private function getAction(): LoginAction $action = new LoginAction( $this->templating, $this->eventDispatcher, - $this->urlGenerator, + $this->router, $this->authorizationChecker, $this->pool, $this->templateRegistry, $this->tokenStorage, - $this->session + $this->formFactory ); $action->setCsrfTokenManager($this->csrfTokenManager); diff --git a/tests/Action/RequestActionTest.php b/tests/Action/RequestActionTest.php index d4806764..6345cd98 100644 --- a/tests/Action/RequestActionTest.php +++ b/tests/Action/RequestActionTest.php @@ -19,9 +19,11 @@ use PHPUnit\Framework\TestCase; use Sonata\AdminBundle\Admin\Pool; use Sonata\AdminBundle\Templating\TemplateRegistryInterface; +use Symfony\Component\Form\Form; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Twig\Environment; @@ -33,9 +35,9 @@ final class RequestActionTest extends TestCase protected $templating; /** - * @var MockObject&UrlGeneratorInterface + * @var MockObject&RouterInterface */ - protected $urlGenerator; + protected $router; /** * @var AuthorizationCheckerInterface&MockObject @@ -49,13 +51,19 @@ final class RequestActionTest extends TestCase */ protected $templateRegistry; + /** + * @var MockObject&FormFactoryInterface + */ + private $formFactory; + protected function setUp(): void { $this->templating = $this->createMock(Environment::class); - $this->urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $this->router = $this->createMock(RouterInterface::class); $this->authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class); $this->pool = PoolMockFactory::create(); $this->templateRegistry = $this->createMock(TemplateRegistryInterface::class); + $this->formFactory = $this->createMock(FormFactoryInterface::class); } public function testAuthenticated(): void @@ -67,7 +75,7 @@ public function testAuthenticated(): void ->willReturn(true) ; - $this->urlGenerator + $this->router ->method('generate') ->with('sonata_admin_dashboard') ->willReturn('/foo') @@ -87,6 +95,7 @@ public function testUnauthenticated(): void $parameters = [ 'base_template' => 'base.html.twig', 'admin_pool' => $this->pool, + 'form' => 'Form View', ]; $this->authorizationChecker->expects(static::once()) @@ -106,6 +115,31 @@ public function testUnauthenticated(): void ->willReturn('base.html.twig') ; + $form = $this->createMock(Form::class); + $form + ->method('isValid') + ->willReturn(true) + ; + $form + ->method('isSubmitted') + ->willReturn(false) + ; + $form->expects(static::once()) + ->method('createView') + ->willReturn('Form View') + ; + + $this->formFactory->expects(static::once()) + ->method('create') + ->willReturn($form) + ; + + $this->router + ->method('generate') + ->with('nucleos_user_admin_resetting_send_email') + ->willReturn('/foo') + ; + $action = $this->getAction(); $result = $action($request); @@ -116,10 +150,11 @@ private function getAction(): RequestAction { return new RequestAction( $this->templating, - $this->urlGenerator, + $this->router, $this->authorizationChecker, $this->pool, - $this->templateRegistry + $this->templateRegistry, + $this->formFactory ); } } diff --git a/tests/Action/ResetActionTest.php b/tests/Action/ResetActionTest.php index 0335dfc3..068da636 100644 --- a/tests/Action/ResetActionTest.php +++ b/tests/Action/ResetActionTest.php @@ -30,7 +30,7 @@ use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment; @@ -43,9 +43,9 @@ final class ResetActionTest extends TestCase protected $templating; /** - * @var MockObject&UrlGeneratorInterface + * @var MockObject&RouterInterface */ - protected $urlGenerator; + protected $router; /** * @var AuthorizationCheckerInterface&MockObject @@ -91,7 +91,7 @@ final class ResetActionTest extends TestCase protected function setUp(): void { $this->templating = $this->createMock(Environment::class); - $this->urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $this->router = $this->createMock(RouterInterface::class); $this->authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class); $this->pool = PoolMockFactory::create(); $this->templateRegistry = $this->createMock(TemplateRegistryInterface::class); @@ -113,7 +113,7 @@ public function testAuthenticated(): void ->willReturn(true) ; - $this->urlGenerator + $this->router ->method('generate') ->with('sonata_admin_dashboard') ->willReturn('/foo') @@ -159,7 +159,7 @@ public function testPasswordRequestNonExpired(): void ->willReturn($user) ; - $this->urlGenerator + $this->router ->method('generate') ->with('nucleos_user_admin_resetting_request') ->willReturn('/foo') @@ -217,10 +217,10 @@ public function testReset(): void ->willReturn($form) ; - $this->urlGenerator + $this->router ->method('generate') - ->with('sonata_admin_dashboard') - ->willReturn('/foo') + ->with('nucleos_user_admin_security_check') + ->willReturn('/check') ; $this->templating @@ -319,24 +319,28 @@ static function (string $message): string { ->willReturn($form) ; - $this->urlGenerator + $this->router ->method('generate') - ->with('sonata_admin_dashboard') - ->willReturn('/foo') + ->withConsecutive([ + 'nucleos_user_admin_security_check', ['token' => 'token'], + ], [ + 'sonata_admin_dashboard', + ]) + ->willReturn('/check', '/dashboard') ; $action = $this->getAction(); $result = $action($request, 'token'); static::assertInstanceOf(RedirectResponse::class, $result); - static::assertSame('/foo', $result->getTargetUrl()); + static::assertSame('/dashboard', $result->getTargetUrl()); } private function getAction(): ResetAction { return new ResetAction( $this->templating, - $this->urlGenerator, + $this->router, $this->authorizationChecker, $this->pool, $this->templateRegistry, diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 0750d7ae..d3e39aca 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -23,3 +23,6 @@ exit(1); } + +// Workaround for phpunit Printer error +session_start();