Merge branch '3.4'

* 3.4:
  Add exculde verbosity test
  [Security] Lazy load user providers
This commit is contained in:
Nicolas Grekas 2017-07-11 15:48:21 +02:00
commit 6db73d3f4e
7 changed files with 83 additions and 27 deletions

View File

@ -223,7 +223,7 @@ class SecurityExtension extends Extension
foreach ($providerIds as $userProviderId) {
$userProviders[] = new Reference($userProviderId);
}
$arguments[1] = $userProviders;
$arguments[1] = new IteratorArgument($userProviders);
$definition->setArguments($arguments);
$customUserChecker = false;
@ -591,7 +591,7 @@ class SecurityExtension extends Extension
$container
->setDefinition($name, new ChildDefinition('security.user.provider.chain'))
->addArgument($providers);
->addArgument(new IteratorArgument($providers));
return $name;
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
@ -57,10 +58,10 @@ abstract class CompleteConfigurationTest extends TestCase
$this->assertEquals(array(), array_diff($providers, $expectedProviders));
// chain provider
$this->assertEquals(array(array(
$this->assertEquals(array(new IteratorArgument(array(
new Reference('security.user.provider.concrete.service'),
new Reference('security.user.provider.concrete.basic'),
)), $container->getDefinition('security.user.provider.concrete.chain')->getArguments());
))), $container->getDefinition('security.user.provider.concrete.chain')->getArguments());
}
public function testFirewalls()

View File

@ -172,6 +172,26 @@ class ChainUserProviderTest extends TestCase
$this->assertFalse($provider->supportsClass('foo'));
}
public function testAcceptsTraversable()
{
$provider1 = $this->getProvider();
$provider1
->expects($this->once())
->method('refreshUser')
->will($this->throwException(new UnsupportedUserException('unsupported')))
;
$provider2 = $this->getProvider();
$provider2
->expects($this->once())
->method('refreshUser')
->will($this->returnValue($account = $this->getAccount()))
;
$provider = new ChainUserProvider(new \ArrayObject(array($provider1, $provider2)));
$this->assertSame($account, $provider->refreshUser($this->getAccount()));
}
protected function getAccount()
{
return $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();

View File

@ -26,7 +26,10 @@ class ChainUserProvider implements UserProviderInterface
{
private $providers;
public function __construct(array $providers)
/**
* @param iterable|UserProviderInterface[] $providers
*/
public function __construct(iterable $providers)
{
$this->providers = $providers;
}
@ -36,6 +39,10 @@ class ChainUserProvider implements UserProviderInterface
*/
public function getProviders()
{
if ($this->providers instanceof \Traversable) {
return iterator_to_array($this->providers);
}
return $this->providers;
}

View File

@ -44,18 +44,20 @@ class ContextListener implements ListenerInterface
private $registered;
private $trustResolver;
public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
/**
* @param TokenStorageInterface $tokenStorage
* @param iterable|UserProviderInterface[] $userProviders
* @param string $contextKey
* @param LoggerInterface|null $logger
* @param EventDispatcherInterface|null $dispatcher
* @param AuthenticationTrustResolverInterface|null $trustResolver
*/
public function __construct(TokenStorageInterface $tokenStorage, iterable $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
{
if (empty($contextKey)) {
throw new \InvalidArgumentException('$contextKey must not be empty.');
}
foreach ($userProviders as $userProvider) {
if (!$userProvider instanceof UserProviderInterface) {
throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "Symfony\Component\Security\Core\User\UserProviderInterface".', get_class($userProvider)));
}
}
$this->tokenStorage = $tokenStorage;
$this->userProviders = $userProviders;
$this->contextKey = $contextKey;
@ -158,6 +160,10 @@ class ContextListener implements ListenerInterface
$userNotFoundByProvider = false;
foreach ($this->userProviders as $provider) {
if (!$provider instanceof UserProviderInterface) {
throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "%s".', get_class($provider), UserProviderInterface::class));
}
try {
$refreshedUser = $provider->refreshUser($user);
$token->setUser($refreshedUser);

View File

@ -53,11 +53,7 @@ class ContextListenerTest extends TestCase
*/
public function testUserProvidersNeedToImplementAnInterface()
{
new ContextListener(
$this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock(),
array(new \stdClass()),
'key123'
);
$this->handleEventWithPreviousSession(new TokenStorage(), array(new \stdClass()));
}
public function testOnKernelResponseWillAddSession()
@ -287,6 +283,15 @@ class ContextListenerTest extends TestCase
$this->handleEventWithPreviousSession(new TokenStorage(), array(new NotSupportingUserProvider(), new NotSupportingUserProvider()));
}
public function testAcceptsProvidersAsTraversable()
{
$tokenStorage = new TokenStorage();
$refreshedUser = new User('foobar', 'baz');
$this->handleEventWithPreviousSession($tokenStorage, new \ArrayObject(array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser))));
$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
}
protected function runSessionOnKernelResponse($newToken, $original = null)
{
$session = new Session(new MockArraySessionStorage());
@ -315,7 +320,7 @@ class ContextListenerTest extends TestCase
return $session;
}
private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, array $userProviders)
private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders)
{
$session = new Session(new MockArraySessionStorage());
$session->set('_security_context_key', serialize(new UsernamePasswordToken(new User('foo', 'bar'), '', 'context_key')));

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\VarDumper\Tests\Caster;
use PHPUnit\Framework\TestCase;
use Symfony\Component\VarDumper\Caster\Caster;
use Symfony\Component\VarDumper\Caster\ExceptionCaster;
use Symfony\Component\VarDumper\Caster\FrameStub;
use Symfony\Component\VarDumper\Cloner\VarCloner;
@ -43,9 +44,9 @@ Exception {
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 27
#line: 28
trace: {
%sExceptionCasterTest.php:27: {
%sExceptionCasterTest.php:28: {
: {
: return new \Exception(''.$msg);
: }
@ -72,7 +73,7 @@ EODUMP;
$expectedDump = <<<'EODUMP'
{
%sExceptionCasterTest.php:27: {
%sExceptionCasterTest.php:28: {
: {
: return new \Exception(''.$msg);
: }
@ -101,9 +102,9 @@ Exception {
#message: "1"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 27
#line: 28
trace: {
%sExceptionCasterTest.php:27: {
%sExceptionCasterTest.php:28: {
: {
: return new \Exception(''.$msg);
: }
@ -129,9 +130,9 @@ Exception {
#message: "1"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 27
#line: 28
trace: {
%sExceptionCasterTest.php: 27
%sExceptionCasterTest.php: 28
%sExceptionCasterTest.php: %d
%A
EODUMP;
@ -157,10 +158,10 @@ EODUMP;
#<span class=sf-dump-protected title="Protected property">code</span>: <span class=sf-dump-num>0</span>
#<span class=sf-dump-protected title="Protected property">file</span>: "<span class=sf-dump-str title="%sExceptionCasterTest.php
%d characters"><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%s%eVarDumper</span><span class=sf-dump-ellipsis>%e</span>Tests%eCaster%eExceptionCasterTest.php</span>"
#<span class=sf-dump-protected title="Protected property">line</span>: <span class=sf-dump-num>27</span>
#<span class=sf-dump-protected title="Protected property">line</span>: <span class=sf-dump-num>28</span>
<span class=sf-dump-meta>trace</span>: {<samp>
<span class=sf-dump-meta title="%sExceptionCasterTest.php
Stack level %d."><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%s%eVarDumper</span><span class=sf-dump-ellipsis>%e</span>Tests%eCaster%eExceptionCasterTest.php</span>: <span class=sf-dump-num>27</span>
Stack level %d."><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%s%eVarDumper</span><span class=sf-dump-ellipsis>%e</span>Tests%eCaster%eExceptionCasterTest.php</span>: <span class=sf-dump-num>28</span>
&hellip;%d
</samp>}
</samp>}
@ -222,4 +223,20 @@ EODUMP;
$this->assertDumpMatchesFormat($expectedDump, $f);
}
public function testExcludeVerbosity()
{
$e = $this->getTestException('foo');
$expectedDump = <<<'EODUMP'
Exception {
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 28
}
EODUMP;
$this->assertDumpMatchesFormat($expectedDump, $e, Caster::EXCLUDE_VERBOSE);
}
}