Merge branch '4.4' into 5.0
* 4.4: [Yaml] Throw on unquoted exclamation mark Use supportsClass where possible
This commit is contained in:
commit
6c1265cdaa
@ -70,24 +70,49 @@ class ChainUserProviderTest extends TestCase
|
||||
$provider1 = $this->getProvider();
|
||||
$provider1
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
->willThrowException(new UnsupportedUserException('unsupported'))
|
||||
->method('supportsClass')
|
||||
->willReturn(false)
|
||||
;
|
||||
|
||||
$provider2 = $this->getProvider();
|
||||
$provider2
|
||||
->expects($this->once())
|
||||
->method('supportsClass')
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$provider2
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
->willThrowException(new UnsupportedUserException('unsupported'))
|
||||
;
|
||||
|
||||
$provider3 = $this->getProvider();
|
||||
$provider3
|
||||
->expects($this->once())
|
||||
->method('supportsClass')
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$provider3
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
->willReturn($account = $this->getAccount())
|
||||
;
|
||||
|
||||
$provider = new ChainUserProvider([$provider1, $provider2]);
|
||||
$provider = new ChainUserProvider([$provider1, $provider2, $provider3]);
|
||||
$this->assertSame($account, $provider->refreshUser($this->getAccount()));
|
||||
}
|
||||
|
||||
public function testRefreshUserAgain()
|
||||
{
|
||||
$provider1 = $this->getProvider();
|
||||
$provider1
|
||||
->expects($this->once())
|
||||
->method('supportsClass')
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$provider1
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
@ -95,6 +120,12 @@ class ChainUserProviderTest extends TestCase
|
||||
;
|
||||
|
||||
$provider2 = $this->getProvider();
|
||||
$provider2
|
||||
->expects($this->once())
|
||||
->method('supportsClass')
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$provider2
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
@ -109,6 +140,12 @@ class ChainUserProviderTest extends TestCase
|
||||
{
|
||||
$this->expectException('Symfony\Component\Security\Core\Exception\UnsupportedUserException');
|
||||
$provider1 = $this->getProvider();
|
||||
$provider1
|
||||
->expects($this->once())
|
||||
->method('supportsClass')
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$provider1
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
@ -116,6 +153,12 @@ class ChainUserProviderTest extends TestCase
|
||||
;
|
||||
|
||||
$provider2 = $this->getProvider();
|
||||
$provider2
|
||||
->expects($this->once())
|
||||
->method('supportsClass')
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$provider2
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
@ -173,6 +216,12 @@ class ChainUserProviderTest extends TestCase
|
||||
public function testAcceptsTraversable()
|
||||
{
|
||||
$provider1 = $this->getProvider();
|
||||
$provider1
|
||||
->expects($this->once())
|
||||
->method('supportsClass')
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$provider1
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
@ -180,6 +229,12 @@ class ChainUserProviderTest extends TestCase
|
||||
;
|
||||
|
||||
$provider2 = $this->getProvider();
|
||||
$provider2
|
||||
->expects($this->once())
|
||||
->method('supportsClass')
|
||||
->willReturn(true)
|
||||
;
|
||||
|
||||
$provider2
|
||||
->expects($this->once())
|
||||
->method('refreshUser')
|
||||
|
@ -73,6 +73,10 @@ class ChainUserProvider implements UserProviderInterface, PasswordUpgraderInterf
|
||||
|
||||
foreach ($this->providers as $provider) {
|
||||
try {
|
||||
if (!$provider->supportsClass(\get_class($user))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $provider->refreshUser($user);
|
||||
} catch (UnsupportedUserException $e) {
|
||||
// try next one
|
||||
|
@ -201,12 +201,17 @@ class ContextListener extends AbstractListener
|
||||
|
||||
$userNotFoundByProvider = false;
|
||||
$userDeauthenticated = false;
|
||||
$userClass = \get_class($user);
|
||||
|
||||
foreach ($this->userProviders as $provider) {
|
||||
if (!$provider instanceof UserProviderInterface) {
|
||||
throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "%s".', \get_class($provider), UserProviderInterface::class));
|
||||
}
|
||||
|
||||
if (!$provider->supportsClass($userClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$refreshedUser = $provider->refreshUser($user);
|
||||
$newToken = clone $token;
|
||||
@ -263,7 +268,7 @@ class ContextListener extends AbstractListener
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new \RuntimeException(sprintf('There is no user provider for user "%s".', \get_class($user)));
|
||||
throw new \RuntimeException(sprintf('There is no user provider for user "%s".', $userClass));
|
||||
}
|
||||
|
||||
private function safelyUnserialize(string $serializedToken)
|
||||
|
@ -253,7 +253,7 @@ class ContextListenerTest extends TestCase
|
||||
public function testIfTokenIsDeauthenticated()
|
||||
{
|
||||
$refreshedUser = new User('foobar', 'baz');
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)]);
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)]);
|
||||
|
||||
$this->assertNull($tokenStorage->getToken());
|
||||
}
|
||||
@ -275,7 +275,7 @@ class ContextListenerTest extends TestCase
|
||||
$rememberMeServices = $this->createMock(RememberMeServicesInterface::class);
|
||||
$rememberMeServices->expects($this->once())->method('loginFail');
|
||||
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], null, $rememberMeServices);
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)], null, $rememberMeServices);
|
||||
|
||||
$this->assertNull($tokenStorage->getToken());
|
||||
}
|
||||
@ -283,7 +283,7 @@ class ContextListenerTest extends TestCase
|
||||
public function testTryAllUserProvidersUntilASupportingUserProviderIsFound()
|
||||
{
|
||||
$refreshedUser = new User('foobar', 'baz');
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], $refreshedUser);
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)], $refreshedUser);
|
||||
|
||||
$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
|
||||
}
|
||||
@ -291,14 +291,14 @@ class ContextListenerTest extends TestCase
|
||||
public function testNextSupportingUserProviderIsTriedIfPreviousSupportingUserProviderDidNotLoadTheUser()
|
||||
{
|
||||
$refreshedUser = new User('foobar', 'baz');
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new SupportingUserProvider(), new SupportingUserProvider($refreshedUser)], $refreshedUser);
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)], $refreshedUser);
|
||||
|
||||
$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
|
||||
}
|
||||
|
||||
public function testTokenIsSetToNullIfNoUserWasLoadedByTheRegisteredUserProviders()
|
||||
{
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(), new SupportingUserProvider()]);
|
||||
$tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider()]);
|
||||
|
||||
$this->assertNull($tokenStorage->getToken());
|
||||
}
|
||||
@ -306,13 +306,13 @@ class ContextListenerTest extends TestCase
|
||||
public function testRuntimeExceptionIsThrownIfNoSupportingUserProviderWasRegistered()
|
||||
{
|
||||
$this->expectException('RuntimeException');
|
||||
$this->handleEventWithPreviousSession([new NotSupportingUserProvider(), new NotSupportingUserProvider()]);
|
||||
$this->handleEventWithPreviousSession([new NotSupportingUserProvider(false), new NotSupportingUserProvider(true)]);
|
||||
}
|
||||
|
||||
public function testAcceptsProvidersAsTraversable()
|
||||
{
|
||||
$refreshedUser = new User('foobar', 'baz');
|
||||
$tokenStorage = $this->handleEventWithPreviousSession(new \ArrayObject([new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)]), $refreshedUser);
|
||||
$tokenStorage = $this->handleEventWithPreviousSession(new \ArrayObject([new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)]), $refreshedUser);
|
||||
|
||||
$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
|
||||
}
|
||||
@ -338,7 +338,7 @@ class ContextListenerTest extends TestCase
|
||||
$this->assertNotEquals($event->getRefreshedToken()->getUser(), $user);
|
||||
});
|
||||
|
||||
$listener = new ContextListener($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], 'context_key', null, $eventDispatcher);
|
||||
$listener = new ContextListener($tokenStorage, [new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)], 'context_key', null, $eventDispatcher);
|
||||
$listener(new RequestEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST));
|
||||
|
||||
$this->assertNull($tokenStorage->getToken());
|
||||
@ -422,6 +422,14 @@ class ContextListenerTest extends TestCase
|
||||
|
||||
class NotSupportingUserProvider implements UserProviderInterface
|
||||
{
|
||||
/** @var bool */
|
||||
private $throwsUnsupportedException;
|
||||
|
||||
public function __construct($throwsUnsupportedException)
|
||||
{
|
||||
$this->throwsUnsupportedException = $throwsUnsupportedException;
|
||||
}
|
||||
|
||||
public function loadUserByUsername($username): UserInterface
|
||||
{
|
||||
throw new UsernameNotFoundException();
|
||||
@ -429,7 +437,11 @@ class NotSupportingUserProvider implements UserProviderInterface
|
||||
|
||||
public function refreshUser(UserInterface $user): UserInterface
|
||||
{
|
||||
throw new UnsupportedUserException();
|
||||
if ($this->throwsUnsupportedException) {
|
||||
throw new UnsupportedUserException();
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function supportsClass($class): bool
|
||||
|
@ -679,6 +679,10 @@ class Inline
|
||||
$nextOffset = $i + $tagLength + 1;
|
||||
$nextOffset += strspn($value, ' ', $nextOffset);
|
||||
|
||||
if ('' === $tag && (!isset($value[$nextOffset]) || \in_array($value[$nextOffset], [']', '}', ','], true))) {
|
||||
throw new ParseException(sprintf('Using the unquoted scalar value "!" is not supported. You must quote it.', $value), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
|
||||
}
|
||||
|
||||
// Is followed by a scalar and is a built-in tag
|
||||
if ('' !== $tag && (!isset($value[$nextOffset]) || !\in_array($value[$nextOffset], ['[', '{'], true)) && ('!' === $tag[0] || 'str' === $tag || 'php/const' === $tag || 'php/object' === $tag)) {
|
||||
// Manage in {@link self::evaluateScalar()}
|
||||
|
@ -737,4 +737,69 @@ class InlineTest extends TestCase
|
||||
'negative octal number' => [-28, '-034'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider unquotedExclamationMarkThrowsProvider
|
||||
*/
|
||||
public function testUnquotedExclamationMarkThrows(string $value)
|
||||
{
|
||||
$this->expectException(ParseException::class);
|
||||
$this->expectExceptionMessageRegExp('/^Using the unquoted scalar value "!" is not supported\. You must quote it at line 1 \(near "/');
|
||||
|
||||
Inline::parse($value);
|
||||
}
|
||||
|
||||
public function unquotedExclamationMarkThrowsProvider()
|
||||
{
|
||||
return [
|
||||
['!'],
|
||||
['! '],
|
||||
['! '],
|
||||
[' ! '],
|
||||
['[!]'],
|
||||
['[! ]'],
|
||||
['[! ]'],
|
||||
['[!, "foo"]'],
|
||||
['["foo", !, "ccc"]'],
|
||||
['{foo: !}'],
|
||||
['{foo: !}'],
|
||||
['{foo: !, bar: "ccc"}'],
|
||||
['{bar: "ccc", foo: ! }'],
|
||||
['!]]]'],
|
||||
['!}'],
|
||||
['!,}foo,]'],
|
||||
['! [!]'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider quotedExclamationMarkProvider
|
||||
*/
|
||||
public function testQuotedExclamationMark($expected, string $value)
|
||||
{
|
||||
$this->assertSame($expected, Inline::parse($value));
|
||||
}
|
||||
|
||||
// This provider should stay consistent with unquotedExclamationMarkThrowsProvider
|
||||
public function quotedExclamationMarkProvider()
|
||||
{
|
||||
return [
|
||||
['!', '"!"'],
|
||||
['! ', '"! "'],
|
||||
[' !', '" !"'],
|
||||
[' ! ', '" ! "'],
|
||||
[['!'], '["!"]'],
|
||||
[['! '], '["! "]'],
|
||||
[['!', 'foo'], '["!", "foo"]'],
|
||||
[['foo', '!', 'ccc'], '["foo", "!", "ccc"]'],
|
||||
[['foo' => '!'], '{foo: "!"}'],
|
||||
[['foo' => ' !'], '{foo: " !"}'],
|
||||
[['foo' => '!', 'bar' => 'ccc'], '{foo: "!", bar: "ccc"}'],
|
||||
[['bar' => 'ccc', 'foo' => '! '], '{bar: "ccc", foo: "! "}'],
|
||||
['!]]]', '"!]]]"'],
|
||||
['!}', '"!}"'],
|
||||
['!,}foo,]', '"!,}foo,]"'],
|
||||
[['!'], '! ["!"]'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user