Skip to content

Commit 70e68d2

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

File tree

5 files changed

+79
-1
lines changed

5 files changed

+79
-1
lines changed

src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
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

Lines changed: 14 additions & 1 deletion
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

Lines changed: 7 additions & 0 deletions
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()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Symfony\Bundle\SecurityBundle\Routing;
4+
5+
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
6+
use Symfony\Component\Routing\Route;
7+
use Symfony\Component\Routing\RouteCollection;
8+
9+
class LogoutRouteLoader
10+
{
11+
/**
12+
* @param iterable<FirewallConfig> $firewallConfigs
13+
*/
14+
public function __construct(
15+
private readonly iterable $firewallConfigs
16+
) {}
17+
18+
public function __invoke(): RouteCollection
19+
{
20+
$collection = new RouteCollection();
21+
22+
foreach ($this->firewallConfigs as $config) {
23+
if (!$logoutConfig = $config->getLogout()) {
24+
continue;
25+
}
26+
27+
$collection->add('_logout_'.$config->getName(), new Route($logoutConfig['path']));
28+
}
29+
30+
return $collection;
31+
}
32+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Symfony\Bundle\SecurityBundle\Tests\Routing;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Symfony\Bundle\SecurityBundle\Routing\LogoutRouteLoader;
7+
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
8+
use Symfony\Component\Routing\Route;
9+
use Symfony\Component\Routing\RouteCollection;
10+
11+
class LogoutRouteLoaderTest extends TestCase
12+
{
13+
public function testLoad(): void
14+
{
15+
$loader = new LogoutRouteLoader([
16+
new FirewallConfig('dev', 'security.user_checker'),
17+
new FirewallConfig('main', 'security.user_checker', logout: ['path' => '/logout']),
18+
]);
19+
$collection = $loader();
20+
21+
self::assertInstanceOf(RouteCollection::class, $collection);
22+
self::assertCount(1, $collection);
23+
self::assertEquals(new Route('/logout'), $collection->get('_logout_main'));
24+
}
25+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy