From 82ba644837ac5743990e5c0f96af4fe421e3168c Mon Sep 17 00:00:00 2001 From: Jeroen Thora Date: Wed, 24 Nov 2021 19:04:29 +0100 Subject: [PATCH] [AdminBundle] Add support for csrf token on logout url in admin interface --- UPGRADE-6.2.md | 7 +++ .../AdminPanel/AdminPanelLogoutAction.php | 52 +++++++++++++++++++ .../AdminPanel/DefaultAdminPanelAdaptor.php | 29 ++++++++--- .../AdminBundle/Resources/config/services.yml | 2 +- .../_admin_panel_logout_action.html.twig | 11 ++++ .../DefaultAdminPanelAdapterTest.php | 43 ++++++++++++--- .../skeleton/config/security.yaml | 1 + .../skeleton/config/security_sf5.yaml | 1 + 8 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 UPGRADE-6.2.md create mode 100644 src/Kunstmaan/AdminBundle/Helper/AdminPanel/AdminPanelLogoutAction.php create mode 100644 src/Kunstmaan/AdminBundle/Resources/views/AdminPanel/_admin_panel_logout_action.html.twig diff --git a/UPGRADE-6.2.md b/UPGRADE-6.2.md new file mode 100644 index 0000000000..e018b219dc --- /dev/null +++ b/UPGRADE-6.2.md @@ -0,0 +1,7 @@ +UPGRADE FROM 6.1 to 6.2 +======================== + +AdminBundle +----------- + +* Not passing a value for "$logoutUrlGenerator" in "Kunstmaan\AdminBundle\Helper\AdminPanel\DefaultAdminPanelAdaptor::__construct" is deprecated and will be required in 7.0. diff --git a/src/Kunstmaan/AdminBundle/Helper/AdminPanel/AdminPanelLogoutAction.php b/src/Kunstmaan/AdminBundle/Helper/AdminPanel/AdminPanelLogoutAction.php new file mode 100644 index 0000000000..4037cd034d --- /dev/null +++ b/src/Kunstmaan/AdminBundle/Helper/AdminPanel/AdminPanelLogoutAction.php @@ -0,0 +1,52 @@ +logoutUrl = $url; + $this->label = $label; + $this->icon = $icon; + if (!empty($template)) { + $this->template = $template; + } + } + + public function getLogoutUrl(): string + { + return $this->logoutUrl; + } + + public function getUrl(): array + { + return []; + } + + public function getIcon(): ?string + { + return $this->icon; + } + + public function getLabel(): string + { + return $this->label; + } + + public function getTemplate(): string + { + return $this->template; + } +} diff --git a/src/Kunstmaan/AdminBundle/Helper/AdminPanel/DefaultAdminPanelAdaptor.php b/src/Kunstmaan/AdminBundle/Helper/AdminPanel/DefaultAdminPanelAdaptor.php index cf0af6430e..e62d2199d4 100644 --- a/src/Kunstmaan/AdminBundle/Helper/AdminPanel/DefaultAdminPanelAdaptor.php +++ b/src/Kunstmaan/AdminBundle/Helper/AdminPanel/DefaultAdminPanelAdaptor.php @@ -3,6 +3,7 @@ namespace Kunstmaan\AdminBundle\Helper\AdminPanel; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; class DefaultAdminPanelAdaptor implements AdminPanelAdaptorInterface { @@ -10,10 +11,17 @@ class DefaultAdminPanelAdaptor implements AdminPanelAdaptorInterface * @var TokenStorageInterface */ protected $tokenStorage; + /** @var LogoutUrlGenerator|null */ + private $logoutUrlGenerator; - public function __construct(TokenStorageInterface $tokenStorage) + public function __construct(TokenStorageInterface $tokenStorage, LogoutUrlGenerator $logoutUrlGenerator = null) { $this->tokenStorage = $tokenStorage; + $this->logoutUrlGenerator = $logoutUrlGenerator; + + if (null === $logoutUrlGenerator) { + trigger_deprecation('kunstmaan/admin-bundle', '6.2', 'Not passing a value for "$logoutUrlGenerator" in "%s" is deprecated and will be required in 7.0.', __METHOD__); + } } /** @@ -54,11 +62,20 @@ protected function getChangePasswordAction() protected function getLogoutAction() { - return new AdminPanelAction( - [ - 'path' => 'kunstmaan_admin_logout', - 'attrs' => ['id' => 'app__logout', 'title' => 'logout'], - ], + // NEXT_MAJOR remove check + if (null === $this->logoutUrlGenerator) { + return new AdminPanelAction( + [ + 'path' => 'kunstmaan_admin_logout', + 'attrs' => ['id' => 'app__logout', 'title' => 'logout'], + ], + '', + 'sign-out' + ); + } + + return new AdminPanelLogoutAction( + $this->logoutUrlGenerator->getLogoutUrl(), '', 'sign-out' ); diff --git a/src/Kunstmaan/AdminBundle/Resources/config/services.yml b/src/Kunstmaan/AdminBundle/Resources/config/services.yml index 4bcb1fd590..0ff3ab56b0 100644 --- a/src/Kunstmaan/AdminBundle/Resources/config/services.yml +++ b/src/Kunstmaan/AdminBundle/Resources/config/services.yml @@ -212,7 +212,7 @@ services: kunstmaan_admin.admin_panel.adaptor: class: Kunstmaan\AdminBundle\Helper\AdminPanel\DefaultAdminPanelAdaptor - arguments: ['@security.token_storage'] + arguments: ['@security.token_storage', '@security.logout_url_generator'] tags: - { name: 'kunstmaan_admin.admin_panel.adaptor' } diff --git a/src/Kunstmaan/AdminBundle/Resources/views/AdminPanel/_admin_panel_logout_action.html.twig b/src/Kunstmaan/AdminBundle/Resources/views/AdminPanel/_admin_panel_logout_action.html.twig new file mode 100644 index 0000000000..cfb3d4a64a --- /dev/null +++ b/src/Kunstmaan/AdminBundle/Resources/views/AdminPanel/_admin_panel_logout_action.html.twig @@ -0,0 +1,11 @@ +
  • + + {% if action.getIcon() is not null %} + + {% endif %} + {% if (action.getLabel()) is not empty %} +   + {{ action.getLabel() }} + {% endif %} + +
  • diff --git a/src/Kunstmaan/AdminBundle/Tests/Helper/AdminPanel/DefaultAdminPanelAdapterTest.php b/src/Kunstmaan/AdminBundle/Tests/Helper/AdminPanel/DefaultAdminPanelAdapterTest.php index 91d30387f7..a9aa182658 100644 --- a/src/Kunstmaan/AdminBundle/Tests/Helper/AdminPanel/DefaultAdminPanelAdapterTest.php +++ b/src/Kunstmaan/AdminBundle/Tests/Helper/AdminPanel/DefaultAdminPanelAdapterTest.php @@ -4,19 +4,50 @@ use Kunstmaan\AdminBundle\Entity\User; use Kunstmaan\AdminBundle\Helper\AdminPanel\AdminPanelAction; +use Kunstmaan\AdminBundle\Helper\AdminPanel\AdminPanelLogoutAction; use Kunstmaan\AdminBundle\Helper\AdminPanel\DefaultAdminPanelAdaptor; use PHPUnit\Framework\TestCase; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; +use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; class DefaultAdminPanelAdapterTest extends TestCase { + use ExpectDeprecationTrait; + public function testAdminPanelAdapter() { - $token = $this->createMock(TokenInterface::class); - $storage = $this->createMock(TokenStorageInterface::class); - $storage->expects($this->once())->method('getToken')->willReturn($token); - $token->expects($this->once())->method('getUser')->willReturn((new User())->setUsername('test')); + $requestStack = new RequestStack(); + $requestStack->push(new Request()); + + $storage = new TokenStorage(); + $storage->setToken(new UsernamePasswordToken((new User())->setUsername('test'), 'password', 'main')); + + $logoutUrlGenerator = new LogoutUrlGenerator($requestStack, null, $storage); + $logoutUrlGenerator->registerListener('main', '/logout', 'logout', '_token'); + + $adapter = new DefaultAdminPanelAdaptor($storage, $logoutUrlGenerator); + $actions = $adapter->getAdminPanelActions(); + + $this->assertCount(3, $actions); + $this->assertInstanceOf(AdminPanelAction::class, $actions[0]); + $this->assertInstanceOf(AdminPanelAction::class, $actions[1]); + $this->assertInstanceOf(AdminPanelLogoutAction::class, $actions[2]); + } + + /** + * @group legacy + */ + public function testAdminPanelAdapterConstructorDeprecation() + { + $this->expectDeprecation('Since kunstmaan/admin-bundle 6.2: Not passing a value for "$logoutUrlGenerator" in "Kunstmaan\AdminBundle\Helper\AdminPanel\DefaultAdminPanelAdaptor::__construct" is deprecated and will be required in 7.0.'); + + $storage = new TokenStorage(); + $storage->setToken(new UsernamePasswordToken((new User())->setUsername('test'), 'password', 'main')); + $adapter = new DefaultAdminPanelAdaptor($storage); $actions = $adapter->getAdminPanelActions(); diff --git a/src/Kunstmaan/GeneratorBundle/Resources/SensioGeneratorBundle/skeleton/config/security.yaml b/src/Kunstmaan/GeneratorBundle/Resources/SensioGeneratorBundle/skeleton/config/security.yaml index 66c9eceae6..22742eb4a1 100644 --- a/src/Kunstmaan/GeneratorBundle/Resources/SensioGeneratorBundle/skeleton/config/security.yaml +++ b/src/Kunstmaan/GeneratorBundle/Resources/SensioGeneratorBundle/skeleton/config/security.yaml @@ -25,6 +25,7 @@ security: logout: path: kunstmaan_admin_logout target: KunstmaanAdminBundle_homepage + csrf_token_generator: 'security.csrf.token_manager' anonymous: true remember_me: secret: "%kernel.secret%" diff --git a/src/Kunstmaan/GeneratorBundle/Resources/SensioGeneratorBundle/skeleton/config/security_sf5.yaml b/src/Kunstmaan/GeneratorBundle/Resources/SensioGeneratorBundle/skeleton/config/security_sf5.yaml index 6de1d65cd9..140b2a07dd 100644 --- a/src/Kunstmaan/GeneratorBundle/Resources/SensioGeneratorBundle/skeleton/config/security_sf5.yaml +++ b/src/Kunstmaan/GeneratorBundle/Resources/SensioGeneratorBundle/skeleton/config/security_sf5.yaml @@ -27,6 +27,7 @@ security: logout: path: kunstmaan_admin_logout target: KunstmaanAdminBundle_homepage + csrf_token_generator: 'security.csrf.token_manager' remember_me: secret: "%kernel.secret%" lifetime: 604800