Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c5407ce

Browse files
MatTheCatnicolas-grekas
authored andcommitted
[SecurityBundle] Make firewalls event dispatcher traceable on debug mode
1 parent e480a66 commit c5407ce

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
* Modify "icon.svg" to improve accessibility for blind/low vision users
1111
* Make `Security::login()` return the authenticator response
1212
* Deprecate the `security.firewalls.logout.csrf_token_generator` config option, use `security.firewalls.logout.csrf_token_manager` instead
13+
* Make firewalls event dispatcher traceable on debug mode
1314

1415
6.2
1516
---
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\ContainerInterface;
17+
use Symfony\Component\DependencyInjection\Reference;
18+
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
19+
20+
/**
21+
* @author Mathieu Lechat <[email protected]>
22+
*/
23+
class MakeFirewallsEventDispatcherTraceablePass implements CompilerPassInterface
24+
{
25+
public function process(ContainerBuilder $container)
26+
{
27+
if (!$container->has('event_dispatcher') || !$container->hasParameter('security.firewalls')) {
28+
return;
29+
}
30+
31+
if (!$container->getParameter('kernel.debug') || !$container->has('debug.stopwatch')) {
32+
return;
33+
}
34+
35+
$dispatchersId = [];
36+
37+
foreach ($container->getParameter('security.firewalls') as $firewallName) {
38+
$dispatcherId = 'security.event_dispatcher.'.$firewallName;
39+
40+
if (!$container->has($dispatcherId)) {
41+
continue;
42+
}
43+
44+
$dispatchersId[$dispatcherId] = 'debug.'.$dispatcherId;
45+
46+
$container->register($dispatchersId[$dispatcherId], TraceableEventDispatcher::class)
47+
->setDecoratedService($dispatcherId)
48+
->setArguments([
49+
new Reference($dispatchersId[$dispatcherId].'.inner'),
50+
new Reference('debug.stopwatch'),
51+
new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE),
52+
new Reference('request_stack', ContainerInterface::NULL_ON_INVALID_REFERENCE),
53+
]);
54+
}
55+
56+
foreach (['kernel.event_subscriber', 'kernel.event_listener'] as $tagName) {
57+
foreach ($container->findTaggedServiceIds($tagName) as $taggedServiceId => $tags) {
58+
$taggedServiceDefinition = $container->findDefinition($taggedServiceId);
59+
$taggedServiceDefinition->clearTag($tagName);
60+
61+
foreach ($tags as $tag) {
62+
if ($dispatcherId = $tag['dispatcher'] ?? null) {
63+
$tag['dispatcher'] = $dispatchersId[$dispatcherId] ?? $dispatcherId;
64+
}
65+
$taggedServiceDefinition->addTag($tagName, $tag);
66+
}
67+
}
68+
}
69+
}
70+
}

src/Symfony/Bundle/SecurityBundle/SecurityBundle.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
1616
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSessionDomainConstraintPass;
1717
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\CleanRememberMeVerifierPass;
18+
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\MakeFirewallsEventDispatcherTraceablePass;
1819
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterCsrfFeaturesPass;
1920
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterEntryPointPass;
2021
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterGlobalSecurityEventListenersPass;
@@ -92,5 +93,8 @@ public function build(ContainerBuilder $container)
9293
AuthenticationEvents::ALIASES,
9394
SecurityEvents::ALIASES
9495
)));
96+
97+
// must be registered before DecoratorServicePass
98+
$container->addCompilerPass(new MakeFirewallsEventDispatcherTraceablePass(), PassConfig::TYPE_OPTIMIZE, 10);
9599
}
96100
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\DependencyInjection\Compiler;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
16+
use Symfony\Bundle\SecurityBundle\SecurityBundle;
17+
use Symfony\Component\DependencyInjection\Compiler\DecoratorServicePass;
18+
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
19+
use Symfony\Component\DependencyInjection\ContainerBuilder;
20+
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
21+
use Symfony\Component\EventDispatcher\EventDispatcher;
22+
use Symfony\Component\Stopwatch\Stopwatch;
23+
24+
class MakeFirewallsEventDispatcherTraceablePassTest extends TestCase
25+
{
26+
private $container;
27+
28+
protected function setUp(): void
29+
{
30+
$this->container = new ContainerBuilder();
31+
$this->container->register('request_stack', \stdClass::class);
32+
$this->container->register('event_dispatcher', EventDispatcher::class);
33+
$this->container->register('debug.stopwatch', Stopwatch::class);
34+
35+
$this->container->registerExtension(new SecurityExtension());
36+
$this->container->loadFromExtension('security', [
37+
'firewalls' => ['main' => ['pattern' => '/', 'http_basic' => true]],
38+
]);
39+
40+
$this->container->addCompilerPass(new DecoratorServicePass(), PassConfig::TYPE_OPTIMIZE);
41+
$this->container->getCompilerPassConfig()->setRemovingPasses([]);
42+
$this->container->getCompilerPassConfig()->setAfterRemovingPasses([]);
43+
44+
$securityBundle = new SecurityBundle();
45+
$securityBundle->build($this->container);
46+
}
47+
48+
public function testEventDispatcherIsDecoratedOnDebugMode()
49+
{
50+
$this->container->setParameter('kernel.debug', true);
51+
52+
$this->container->compile();
53+
54+
$dispatcherDefinition = $this->container->findDefinition('security.event_dispatcher.main');
55+
56+
$this->assertSame(TraceableEventDispatcher::class, $dispatcherDefinition->getClass());
57+
$this->assertSame(
58+
[['name' => 'security.event_dispatcher.main']],
59+
$dispatcherDefinition->getTag('event_dispatcher.dispatcher')
60+
);
61+
}
62+
63+
public function testEventDispatcherIsNotDecoratedOnNonDebugMode()
64+
{
65+
$this->container->setParameter('kernel.debug', false);
66+
67+
$this->container->compile();
68+
69+
$dispatcherDefinition = $this->container->findDefinition('security.event_dispatcher.main');
70+
71+
$this->assertSame(EventDispatcher::class, $dispatcherDefinition->getClass());
72+
}
73+
}

0 commit comments

Comments
 (0)