Skip to content

Commit 0152527

Browse files
author
Robin Chalas
committed
bug symfony#25272 [SecurityBundle] fix setLogoutOnUserChange calls for context listeners (dmaicher)
This PR was squashed before being merged into the 3.4 branch (closes symfony#25272). Discussion ---------- [SecurityBundle] fix setLogoutOnUserChange calls for context listeners | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony#25267 | License | MIT | Doc PR | - As pointed out in symfony#25267 the `setLogoutOnUserChange` method calls were added to the parent definition `security.context_listener` instead of the concrete child definitions `security.context_listener.*`. ping @iltar @chalasr Commits ------- 4eff146 [SecurityBundle] fix setLogoutOnUserChange calls for context listeners
2 parents 4086b12 + 4eff146 commit 0152527

File tree

3 files changed

+53
-20
lines changed

3 files changed

+53
-20
lines changed

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -340,17 +340,6 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto
340340
return $firewall;
341341
})
342342
->end()
343-
->validate()
344-
->ifTrue(function ($v) {
345-
return (isset($v['stateless']) && true === $v['stateless']) || (isset($v['security']) && false === $v['security']);
346-
})
347-
->then(function ($v) {
348-
// this option doesn't change behavior when true when stateless, so prevent deprecations
349-
$v['logout_on_user_change'] = true;
350-
351-
return $v;
352-
})
353-
->end()
354343
;
355344
}
356345

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class SecurityExtension extends Extension
4343
private $factories = array();
4444
private $userProviderFactories = array();
4545
private $expressionLanguage;
46+
private $logoutOnUserChangeByContextKey = array();
4647

4748
public function __construct()
4849
{
@@ -276,12 +277,6 @@ private function createFirewalls($config, ContainerBuilder $container)
276277
$customUserChecker = true;
277278
}
278279

279-
if (!isset($firewall['logout_on_user_change']) || !$firewall['logout_on_user_change']) {
280-
@trigger_error(sprintf('Not setting "logout_on_user_change" to true on firewall "%s" is deprecated as of 3.4, it will always be true in 4.0.', $name), E_USER_DEPRECATED);
281-
}
282-
283-
$contextListenerDefinition->addMethodCall('setLogoutOnUserChange', array($firewall['logout_on_user_change']));
284-
285280
$configId = 'security.firewall.map.config.'.$name;
286281

287282
list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId);
@@ -370,7 +365,16 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
370365
$contextKey = $firewall['context'];
371366
}
372367

373-
$listeners[] = new Reference($this->createContextListener($container, $contextKey));
368+
if (!$logoutOnUserChange = $firewall['logout_on_user_change']) {
369+
@trigger_error(sprintf('Not setting "logout_on_user_change" to true on firewall "%s" is deprecated as of 3.4, it will always be true in 4.0.', $id), E_USER_DEPRECATED);
370+
}
371+
372+
if (isset($this->logoutOnUserChangeByContextKey[$contextKey]) && $this->logoutOnUserChangeByContextKey[$contextKey][1] !== $logoutOnUserChange) {
373+
throw new InvalidConfigurationException(sprintf('Firewalls "%s" and "%s" need to have the same value for option "logout_on_user_change" as they are sharing the context "%s"', $this->logoutOnUserChangeByContextKey[$contextKey][0], $id, $contextKey));
374+
}
375+
376+
$this->logoutOnUserChangeByContextKey[$contextKey] = array($id, $logoutOnUserChange);
377+
$listeners[] = new Reference($this->createContextListener($container, $contextKey, $logoutOnUserChange));
374378
}
375379

376380
$config->replaceArgument(6, $contextKey);
@@ -481,7 +485,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
481485
return array($matcher, $listeners, $exceptionListener);
482486
}
483487

484-
private function createContextListener($container, $contextKey)
488+
private function createContextListener($container, $contextKey, $logoutUserOnChange)
485489
{
486490
if (isset($this->contextListeners[$contextKey])) {
487491
return $this->contextListeners[$contextKey];
@@ -490,6 +494,7 @@ private function createContextListener($container, $contextKey)
490494
$listenerId = 'security.context_listener.'.count($this->contextListeners);
491495
$listener = $container->setDefinition($listenerId, new ChildDefinition('security.context_listener'));
492496
$listener->replaceArgument(2, $contextKey);
497+
$listener->addMethodCall('setLogoutOnUserChange', array($logoutUserOnChange));
493498

494499
return $this->contextListeners[$contextKey] = $listenerId;
495500
}

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,60 @@ public function testDisableRoleHierarchyVoter()
127127
* @group legacy
128128
* @expectedDeprecation Not setting "logout_on_user_change" to true on firewall "some_firewall" is deprecated as of 3.4, it will always be true in 4.0.
129129
*/
130-
public function testDeprecationForUserLogout()
130+
public function testConfiguresLogoutOnUserChangeForContextListenersCorrectly()
131131
{
132132
$container = $this->getRawContainer();
133133

134134
$container->loadFromExtension('security', array(
135135
'providers' => array(
136136
'default' => array('id' => 'foo'),
137137
),
138+
'firewalls' => array(
139+
'some_firewall' => array(
140+
'pattern' => '/.*',
141+
'http_basic' => null,
142+
'logout_on_user_change' => false,
143+
),
144+
'some_other_firewall' => array(
145+
'pattern' => '/.*',
146+
'http_basic' => null,
147+
'logout_on_user_change' => true,
148+
),
149+
),
150+
));
151+
152+
$container->compile();
153+
154+
$this->assertEquals(array(array('setLogoutOnUserChange', array(false))), $container->getDefinition('security.context_listener.0')->getMethodCalls());
155+
$this->assertEquals(array(array('setLogoutOnUserChange', array(true))), $container->getDefinition('security.context_listener.1')->getMethodCalls());
156+
}
138157

158+
/**
159+
* @group legacy
160+
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
161+
* @expectedExceptionMessage Firewalls "some_firewall" and "some_other_firewall" need to have the same value for option "logout_on_user_change" as they are sharing the context "my_context"
162+
*/
163+
public function testThrowsIfLogoutOnUserChangeDifferentForSharedContext()
164+
{
165+
$container = $this->getRawContainer();
166+
167+
$container->loadFromExtension('security', array(
168+
'providers' => array(
169+
'default' => array('id' => 'foo'),
170+
),
139171
'firewalls' => array(
140172
'some_firewall' => array(
141173
'pattern' => '/.*',
142174
'http_basic' => null,
175+
'context' => 'my_context',
143176
'logout_on_user_change' => false,
144177
),
178+
'some_other_firewall' => array(
179+
'pattern' => '/.*',
180+
'http_basic' => null,
181+
'context' => 'my_context',
182+
'logout_on_user_change' => true,
183+
),
145184
),
146185
));
147186

0 commit comments

Comments
 (0)