8000 [SecurityBundle][Routing] Add `LogoutRouteLoader` · symfony/symfony@e2775a9 · GitHub
[go: up one dir, main page]

Skip to content

Commit e2775a9

Browse files
committed
[SecurityBundle][Routing] Add LogoutRouteLoader
1 parent 43066ff commit e2775a9

File tree

5 files changed

+98
-1
lines changed

5 files changed

+98
-1
lines changed

src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Deprecate `Security::ACCESS_DENIED_ERROR`, `AUTHENTICATION_ERROR` and `LAST_USERNAME` constants, use the ones on `SecurityRequestAttributes` instead
8+
* Add `LogoutRouteLoader`
89

910
6.3
1011
---

src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

+14-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
use Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher;
5050
use Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher;
5151
use Symfony\Component\PasswordHasher\Hasher\SodiumPasswordHasher;
52+
use Symfony\Component\Routing\Loader\ContainerLoader;
5253
use Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy;
5354
use Symfony\Component\Security\Core\Authorization\Strategy\ConsensusStrategy;
5455
use Symfony\Component\Security\Core\Authorization\Strategy\PriorityStrategy;
@@ -170,6 +171,11 @@ public function load(array $configs, ContainerBuilder $container)
170171
}
171172

172173
$this->createFirewalls($config, $container);
174+
175+
if (!$container::willBeAvailable('symfony/routing', ContainerLoader::class, ['symfony/security/bundle'])) {
176+
$container->removeDefinition('security.route_loader.logout');
177+
}
178+
173179
$this->createAuthorization($config, $container);
174180
$this->createRoleHierarchy($config, $container);
175181

@@ -307,7 +313,7 @@ private function createFirewalls(array $config, ContainerBuilder $container): vo
307313

308314
// load firewall map
309315
$mapDef = $container->getDefinition('security.firewall.map');
310-
$map = $authenticationProviders = $contextRefs = $authenticators = [];
316+
$map = $authenticationProviders = $contextRefs = $authenticators = $configs = [];
311317
foreach ($firewalls as $name => $firewall) {
312318
if (isset($firewall['user_checker']) && 'security.user_checker' !== $firewall['user_checker']) {
313319
$customUserChecker = true;
@@ -317,6 +323,8 @@ private function createFirewalls(array $config, ContainerBuilder $container): vo
317323

318324
[$matcher, $listeners, $exceptionListener, $logoutListener, $firewallAuthenticators] = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId);
319325

326+
$configs[] = new Reference($configId);
327+
320328
if (!$firewallAuthenticators) {
321329
$authenticators[$name] = null;
322330
} else {
@@ -354,6 +362,11 @@ private function createFirewalls(array $config, ContainerBuilder $container): vo
354362
if (!$customUserChecker) {
355363
$container->setAlias(UserCheckerInterface::class, new Alias('security.user_checker', false));
356364
}
365+
366+
$container
367+
->getDefinition('security.route_loader.logout')
368+
->replaceArgument(0, new IteratorArgument($configs))
369+
;
357370
}
358371

359372
private function createFirewall(ContainerBuilder $container, string $id, array $firewall, array &$authenticationProviders, array $providerIds, string $configId): array

src/Symfony/Bundle/SecurityBundle/Resources/config/security.php

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

1414
use Symfony\Bundle\SecurityBundle\CacheWarmer\ExpressionCacheWarmer;
1515
use Symfony\Bundle\SecurityBundle\EventListener\FirewallListener;
16+
use Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader;
1617
use Symfony\Bundle\SecurityBundle\Security;
1718
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
1819
use Symfony\Bundle\SecurityBundle\Security\FirewallContext;
@@ -229,6 +230,12 @@
229230
service('security.token_storage')->nullOnInvalid(),
230231
])
231232

233+
->set('security.route_loader.logout', LogoutRouteLoader::class)
234+
->args([
235+
abstract_arg('Firewall config iterator'),
236+
])
237+
->tag('routing.route_loader')
238+
232239
// Provisioning
233240
->set('security.user.provider.missing', MissingUserProvider::class)
234241
->abstract()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\SecurityBundle\Routing;
13+
14+
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
15+
use Symfony\Component\Routing\Route;
16+
use Symfony\Component\Routing\RouteCollection;
17+
18+
class LogoutRouteLoader
19+
{
20+
/**
21+
* @param iterable<FirewallConfig> $firewallConfigs
22+
*/
23+
public function __construct(
24+
private readonly iterable $firewallConfigs
25+
) {
26+
}
27+
28+
public function __invoke(): RouteCollection
29+
{
30+
$collection = new RouteCollection();
31+
32+
foreach ($this->firewallConfigs as $config) {
33+
if (!$logoutConfig = $config->getLogout()) {
34+
continue;
35+
}
36+
37+
$collection->add('_logout_'.$config->getName(), new Route($logoutConfig['path']));
38+
}
39+
40+
return $collection;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\SecurityBundle\Tests\Routing;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader;
16+
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
17+
use Symfony\Component\Routing\Route;
18+
use Symfony\Component\Routing\RouteCollection;
19+
20+
class LogoutRouteLoaderTest extends TestCase
21+
{
22+
public function testLoad()
23+
{
24+
$loader = new LogoutRouteLoader([
25+
new FirewallConfig('dev', 'security.user_checker'),
26+
new FirewallConfig('main', 'security.user_checker', logout: ['path' => '/logout']),
27+
]);
28+
$collection = $loader();
29+
30+
self::assertInstanceOf(RouteCollection::class, $collection);
31+
self::assertCount(1, $collection);
32+
self::assertEquals(new Route('/logout'), $collection->get('_logout_main'));
33+
}
34+
}

0 commit comments

Comments
 (0)
0