Skip to content

Commit

Permalink
Use supportsClass where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
linaori committed Dec 20, 2019
1 parent c4aa926 commit 0cfaf60
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 12 deletions.
61 changes: 58 additions & 3 deletions Core/Tests/User/ChainUserProviderTest.php
Expand Up @@ -68,31 +68,62 @@ public function testRefreshUser()
$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')
->willThrowException(new UsernameNotFoundException('not found'))
;

$provider2 = $this->getProvider();
$provider2
->expects($this->once())
->method('supportsClass')
->willReturn(true)
;

$provider2
->expects($this->once())
->method('refreshUser')
Expand All @@ -107,13 +138,25 @@ public function testRefreshUserThrowsUnsupportedUserException()
{
$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')
->willThrowException(new UnsupportedUserException('unsupported'))
;

$provider2 = $this->getProvider();
$provider2
->expects($this->once())
->method('supportsClass')
->willReturn(true)
;

$provider2
->expects($this->once())
->method('refreshUser')
Expand Down Expand Up @@ -171,13 +214,25 @@ public function testSupportsClassWhenNotSupported()
public function testAcceptsTraversable()
{
$provider1 = $this->getProvider();
$provider1
->expects($this->once())
->method('supportsClass')
->willReturn(true)
;

$provider1
->expects($this->once())
->method('refreshUser')
->willThrowException(new UnsupportedUserException('unsupported'))
;

$provider2 = $this->getProvider();
$provider2
->expects($this->once())
->method('supportsClass')
->willReturn(true)
;

$provider2
->expects($this->once())
->method('refreshUser')
Expand Down
4 changes: 4 additions & 0 deletions Core/User/ChainUserProvider.php
Expand Up @@ -73,6 +73,10 @@ public function refreshUser(UserInterface $user)

foreach ($this->providers as $provider) {
try {
if (!$provider->supportsClass(\get_class($user))) {
continue;
}

return $provider->refreshUser($user);
} catch (UnsupportedUserException $e) {
// try next one
Expand Down
7 changes: 6 additions & 1 deletion Http/Firewall/ContextListener.php
Expand Up @@ -168,12 +168,17 @@ protected function refreshUser(TokenInterface $token)

$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;
Expand Down Expand Up @@ -233,7 +238,7 @@ protected function refreshUser(TokenInterface $token)
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($serializedToken)
Expand Down
28 changes: 20 additions & 8 deletions Http/Tests/Firewall/ContextListenerTest.php
Expand Up @@ -256,7 +256,7 @@ public function testIfTokenIsDeauthenticatedTriggersDeprecations()
{
$tokenStorage = new TokenStorage();
$refreshedUser = new User('foobar', 'baz');
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)]);
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)]);

$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
}
Expand All @@ -265,7 +265,7 @@ public function testIfTokenIsDeauthenticated()
{
$tokenStorage = new TokenStorage();
$refreshedUser = new User('foobar', 'baz');
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], null, true);
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)], null, true);

$this->assertNull($tokenStorage->getToken());
}
Expand All @@ -287,7 +287,7 @@ public function testRememberMeGetsCanceledIfTokenIsDeauthenticated()
$rememberMeServices = $this->createMock(RememberMeServicesInterface::class);
$rememberMeServices->expects($this->once())->method('loginFail');

$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], null, true, $rememberMeServices);
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)], null, true, $rememberMeServices);

$this->assertNull($tokenStorage->getToken());
}
Expand All @@ -296,7 +296,7 @@ public function testTryAllUserProvidersUntilASupportingUserProviderIsFound()
{
$tokenStorage = new TokenStorage();
$refreshedUser = new User('foobar', 'baz');
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], $refreshedUser);
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)], $refreshedUser);

$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
}
Expand All @@ -313,22 +313,22 @@ public function testNextSupportingUserProviderIsTriedIfPreviousSupportingUserPro
public function testTokenIsSetToNullIfNoUserWasLoadedByTheRegisteredUserProviders()
{
$tokenStorage = new TokenStorage();
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider()]);
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider()]);

$this->assertNull($tokenStorage->getToken());
}

public function testRuntimeExceptionIsThrownIfNoSupportingUserProviderWasRegistered()
{
$this->expectException('RuntimeException');
$this->handleEventWithPreviousSession(new TokenStorage(), [new NotSupportingUserProvider(), new NotSupportingUserProvider()]);
$this->handleEventWithPreviousSession(new TokenStorage(), [new NotSupportingUserProvider(false), new NotSupportingUserProvider(true)]);
}

public function testAcceptsProvidersAsTraversable()
{
$tokenStorage = new TokenStorage();
$refreshedUser = new User('foobar', 'baz');
$this->handleEventWithPreviousSession($tokenStorage, new \ArrayObject([new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)]), $refreshedUser);
$this->handleEventWithPreviousSession($tokenStorage, new \ArrayObject([new NotSupportingUserProvider(true), new NotSupportingUserProvider(false), new SupportingUserProvider($refreshedUser)]), $refreshedUser);

$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
}
Expand Down Expand Up @@ -383,14 +383,26 @@ private function handleEventWithPreviousSession(TokenStorageInterface $tokenStor

class NotSupportingUserProvider implements UserProviderInterface
{
/** @var bool */
private $throwsUnsupportedException;

public function __construct($throwsUnsupportedException)
{
$this->throwsUnsupportedException = $throwsUnsupportedException;
}

public function loadUserByUsername($username)
{
throw new UsernameNotFoundException();
}

public function refreshUser(UserInterface $user)
{
throw new UnsupportedUserException();
if ($this->throwsUnsupportedException) {
throw new UnsupportedUserException();
}

return $user;
}

public function supportsClass($class)
Expand Down

0 comments on commit 0cfaf60

Please sign in to comment.