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

Skip to content

Commit 050d686

Browse files
feature #23295 [Security] Lazy load user providers (chalasr)
This PR was merged into the 3.4 branch. Discussion ---------- [Security] Lazy load user providers | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a Commits ------- d7914a6 [Security] Lazy load user providers
2 parents bd30a27 + d7914a6 commit 050d686

File tree

6 files changed

+57
-18
lines changed

6 files changed

+57
-18
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ private function createFirewalls($config, ContainerBuilder $container)
245245
foreach ($providerIds as $userProviderId) {
246246
$userProviders[] = new Reference($userProviderId);
247247
}
248-
$arguments[1] = $userProviders;
248+
$arguments[1] = new IteratorArgument($userProviders);
249249
$definition->setArguments($arguments);
250250

251251
$customUserChecker = false;
@@ -613,7 +613,7 @@ private function createUserDaoProvider($name, $provider, ContainerBuilder $conta
613613

614614
$container
615615
->setDefinition($name, new ChildDefinition('security.user.provider.chain'))
616-
->addArgument($providers);
616+
->addArgument(new IteratorArgument($providers));
617617

618618
return $name;
619619
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
1516
use Symfony\Component\DependencyInjection\Reference;
1617
use Symfony\Bundle\SecurityBundle\SecurityBundle;
1718
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
@@ -57,10 +58,10 @@ public function testUserProviders()
5758
$this->assertEquals(array(), array_diff($providers, $expectedProviders));
5859

5960
// chain provider
60-
$this->assertEquals(array(array(
61+
$this->assertEquals(array(new IteratorArgument(array(
6162
new Reference('security.user.provider.concrete.service'),
6263
new Reference('security.user.provider.concrete.basic'),
63-
)), $container->getDefinition('security.user.provider.concrete.chain')->getArguments());
64+
))), $container->getDefinition('security.user.provider.concrete.chain')->getArguments());
6465
}
6566

6667
public function testFirewalls()

src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,26 @@ public function testSupportsClassWhenNotSupported()
172172
$this->assertFalse($provider->supportsClass('foo'));
173173
}
174174

175+
public function testAcceptsTraversable()
176+
{
177+
$provider1 = $this->getProvider();
178+
$provider1
179+
->expects($this->once())
180+
->method('refreshUser')
181+
->will($this->throwException(new UnsupportedUserException('unsupported')))
182+
;
183+
184+
$provider2 = $this->getProvider();
185+
$provider2
186+
->expects($this->once())
187+
->method('refreshUser')
188+
->will($this->returnValue($account = $this->getAccount()))
189+
;
190+
191+
$provider = new ChainUserProvider(new \ArrayObject(array($provider1, $provider2)));
192+
$this->assertSame($account, $provider->refreshUser($this->getAccount()));
193+
}
194+
175195
protected function getAccount()
176196
{
177197
return $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();

src/Symfony/Component/Security/Core/User/ChainUserProvider.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ class ChainUserProvider implements UserProviderInterface
2626
{
2727
private $providers;
2828

29-
public function __construct(array $providers)
29+
/**
30+
* @param iterable|UserProviderInterface[] $providers
31+
*/
32+
public function __construct($providers)
3033
{
3134
$this->providers = $providers;
3235
}
@@ -36,6 +39,10 @@ public function __construct(array $providers)
3639
*/
3740
public function getProviders()
3841
{
42+
if ($this->providers instanceof \Traversable) {
43+
return iterator_to_array($this->providers);
44+
}
45+
3946
return $this->providers;
4047
}
4148

src/Symfony/Component/Security/Http/Firewall/ContextListener.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,20 @@ class ContextListener implements ListenerInterface
4444
private $registered;
4545
private $trustResolver;
4646

47-
public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
47+
/**
48+
* @param TokenStorageInterface $tokenStorage
49+
* @param iterable|UserProviderInterface[] $userProviders
50+
* @param string $contextKey
51+
* @param LoggerInterface|null $logger
52+
* @param EventDispatcherInterface|null $dispatcher
53+
* @param AuthenticationTrustResolverInterface|null $trustResolver
54+
*/
55+
public function __construct(TokenStorageInterface $tokenStorage, $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
4856
{
4957
if (empty($contextKey)) {
5058
throw new \InvalidArgumentException('$contextKey must not be empty.');
5159
}
5260

53-
foreach ($userProviders as $userProvider) {
54-
if (!$userProvider instanceof UserProviderInterface) {
55-
throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "Symfony\Component\Security\Core\User\UserProviderInterface".', get_class($userProvider)));
56-
}
57-
}
58-
5961
$this->tokenStorage = $tokenStorage;
6062
$this->userProviders = $userProviders;
6163
$this->contextKey = $contextKey;
@@ -158,6 +160,10 @@ protected function refreshUser(TokenInterface $token)
158160
$userNotFoundByProvider = false;
159161

160162
foreach ($this->userProviders as $provider) {
163+
if (!$provider instanceof UserProviderInterface) {
164+
throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "%s".', get_class($provider), UserProviderInterface::class));
165+
}
166+
161167
try {
162168
$refreshedUser = $provider->refreshUser($user);
163169
$token->setUser($refreshedUser);

src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,7 @@ public function testItRequiresContextKey()
5353
*/
5454
public function testUserProvidersNeedToImplementAnInterface()
5555
{
56-
new ContextListener(
57-
$this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock(),
58-
array(new \stdClass()),
59-
'key123'
60-
);
56+
$this->handleEventWithPreviousSession(new TokenStorage(), array(new \stdClass()));
6157
}
6258

6359
public function testOnKernelResponseWillAddSession()
@@ -287,6 +283,15 @@ public function testRuntimeExceptionIsThrownIfNoSupportingUserProviderWasRegiste
287283
$this->handleEventWithPreviousSession(new TokenStorage(), array(new NotSupportingUserProvider(), new NotSupportingUserProvider()));
288284
}
289285

286+
public function testAcceptsProvidersAsTraversable()
287+
{
288+
$tokenStorage = new TokenStorage();
289+
$refreshedUser = new User('foobar', 'baz');
290+
$this->handleEventWithPreviousSession($tokenStorage, new \ArrayObject(array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser))));
291+
292+
$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
293+
}
294+
290295
protected function runSessionOnKernelResponse($newToken, $original = null)
291296
{
292297
$session = new Session(new MockArraySessionStorage());
@@ -315,7 +320,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null)
315320
return $session;
316321
}
317322

318-
private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, array $userProviders)
323+
private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders)
319324
{
320325
$session = new Session(new MockArraySessionStorage());
321326
$session->set('_security_context_key', serialize(new UsernamePasswordToken(new User('foo', 'bar'), '', 'context_key')));

0 commit comments

Comments
 (0)