diff --git a/src/Bridge/AuthCodeRepository.php b/src/Bridge/AuthCodeRepository.php index fb0dc529..8e7135b0 100644 --- a/src/Bridge/AuthCodeRepository.php +++ b/src/Bridge/AuthCodeRepository.php @@ -48,6 +48,6 @@ public function revokeAuthCode(string $codeId): void */ public function isAuthCodeRevoked(string $codeId): bool { - return Passport::authCode()->where('id', $codeId)->where('revoked', 1)->exists(); + return Passport::authCode()->where('id', $codeId)->where('revoked', 0)->doesntExist(); } } diff --git a/src/RefreshTokenRepository.php b/src/RefreshTokenRepository.php index bca0269e..61dfb990 100644 --- a/src/RefreshTokenRepository.php +++ b/src/RefreshTokenRepository.php @@ -67,10 +67,6 @@ public function revokeRefreshTokensByAccessTokenId($tokenId) */ public function isRefreshTokenRevoked($id) { - if ($token = $this->find($id)) { - return $token->revoked; - } - - return true; + return Passport::refreshToken()->where('id', $id)->where('revoked', 0)->doesntExist(); } } diff --git a/src/TokenRepository.php b/src/TokenRepository.php index b68f339b..5886b01f 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -97,11 +97,7 @@ public function revokeAccessToken($id) */ public function isAccessTokenRevoked($id) { - if ($token = $this->find($id)) { - return $token->revoked; - } - - return true; + return Passport::token()->where('id', $id)->where('revoked', 0)->doesntExist(); } /** diff --git a/tests/Feature/RevokedTest.php b/tests/Feature/RevokedTest.php new file mode 100644 index 00000000..2ba75896 --- /dev/null +++ b/tests/Feature/RevokedTest.php @@ -0,0 +1,149 @@ +<?php + +use Carbon\CarbonImmutable; +use Laravel\Passport\Bridge\AccessToken; +use Laravel\Passport\Bridge\AccessTokenRepository as BridgeAccessTokenRepository; +use Laravel\Passport\Bridge\AuthCode; +use Laravel\Passport\Bridge\AuthCodeRepository as BridgeAuthCodeRepository; +use Laravel\Passport\Bridge\RefreshToken; +use Laravel\Passport\Bridge\RefreshTokenRepository as BridgeRefreshTokenRepository; +use Laravel\Passport\RefreshTokenRepository; +use Laravel\Passport\Tests\Feature\PassportTestCase; +use Laravel\Passport\TokenRepository; +use Mockery as m; +use Orchestra\Testbench\Concerns\WithLaravelMigrations; + +class RevokedTest extends PassportTestCase +{ + use WithLaravelMigrations; + + public function test_it_can_determine_if_a_access_token_is_revoked() + { + $repository = $this->accessTokenRepository(); + $this->persistNewAccessToken($repository, 'tokenId'); + + $repository->revokeAccessToken('tokenId'); + + $this->assertTrue($repository->isAccessTokenRevoked('tokenId')); + } + + public function test_a_access_token_is_also_revoked_if_it_cannot_be_found() + { + $repository = $this->accessTokenRepository(); + + $this->assertTrue($repository->isAccessTokenRevoked('notExistingTokenId')); + } + + public function test_it_can_determine_if_a_access_token_is_not_revoked() + { + $repository = $this->accessTokenRepository(); + $this->persistNewAccessToken($repository, 'tokenId'); + + $this->assertFalse($repository->isAccessTokenRevoked('tokenId')); + } + + public function test_it_can_determine_if_a_auth_code_is_revoked() + { + $repository = $this->authCodeRepository(); + $this->persistNewAuthCode($repository, 'tokenId'); + + $repository->revokeAuthCode('tokenId'); + + $this->assertTrue($repository->isAuthCodeRevoked('tokenId')); + } + + public function test_a_auth_code_is_also_revoked_if_it_cannot_be_found() + { + $repository = $this->authCodeRepository(); + + $this->assertTrue($repository->isAuthCodeRevoked('notExistingTokenId')); + } + + public function test_it_can_determine_if_a_auth_code_is_not_revoked() + { + $repository = $this->authCodeRepository(); + $this->persistNewAuthCode($repository, 'tokenId'); + + $this->assertFalse($repository->isAuthCodeRevoked('tokenId')); + } + + public function test_it_can_determine_if_a_refresh_token_is_revoked() + { + $repository = $this->refreshTokenRepository(); + $this->persistNewRefreshToken($repository, 'tokenId'); + + $repository->revokeRefreshToken('tokenId'); + + $this->assertTrue($repository->isRefreshTokenRevoked('tokenId')); + } + + public function test_a_refresh_token_is_also_revoked_if_it_cannot_be_found() + { + $repository = $this->refreshTokenRepository(); + + $this->assertTrue($repository->isRefreshTokenRevoked('notExistingTokenId')); + } + + public function test_it_can_determine_if_a_refresh_token_is_not_revoked() + { + $repository = $this->refreshTokenRepository(); + $this->persistNewRefreshToken($repository, 'tokenId'); + + $this->assertFalse($repository->isRefreshTokenRevoked('tokenId')); + } + + private function accessTokenRepository(): BridgeAccessTokenRepository + { + $events = m::mock('Illuminate\Contracts\Events\Dispatcher'); + $events->shouldReceive('dispatch'); + + return new BridgeAccessTokenRepository(new TokenRepository, $events); + } + + private function persistNewAccessToken(BridgeAccessTokenRepository $repository, string $id): void + { + $accessToken = m::mock(AccessToken::class); + $accessToken->shouldReceive('getIdentifier')->andReturn($id); + $accessToken->shouldReceive('getUserIdentifier')->andReturn('1'); + $accessToken->shouldReceive('getClient->getIdentifier')->andReturn('clientId'); + $accessToken->shouldReceive('getScopes')->andReturn([]); + $accessToken->shouldReceive('getExpiryDateTime')->andReturn(CarbonImmutable::now()); + + $repository->persistNewAccessToken($accessToken); + } + + private function authCodeRepository(): BridgeAuthCodeRepository + { + return new BridgeAuthCodeRepository; + } + + private function persistNewAuthCode(BridgeAuthCodeRepository $repository, string $id): void + { + $authCode = m::mock(AuthCode::class); + $authCode->shouldReceive('getIdentifier')->andReturn($id); + $authCode->shouldReceive('getUserIdentifier')->andReturn('1'); + $authCode->shouldReceive('getClient->getIdentifier')->andReturn('clientId'); + $authCode->shouldReceive('getExpiryDateTime')->andReturn(CarbonImmutable::now()); + $authCode->shouldReceive('getScopes')->andReturn([]); + + $repository->persistNewAuthCode($authCode); + } + + private function refreshTokenRepository(): BridgeRefreshTokenRepository + { + $events = m::mock('Illuminate\Contracts\Events\Dispatcher'); + $events->shouldReceive('dispatch'); + + return new BridgeRefreshTokenRepository(new RefreshTokenRepository, $events); + } + + private function persistNewRefreshToken(BridgeRefreshTokenRepository $repository, string $id): void + { + $refreshToken = m::mock(RefreshToken::class); + $refreshToken->shouldReceive('getIdentifier')->andReturn($id); + $refreshToken->shouldReceive('getAccessToken->getIdentifier')->andReturn('accessTokenId'); + $refreshToken->shouldReceive('getExpiryDateTime')->andReturn(CarbonImmutable::now()); + + $repository->persistNewRefreshToken($refreshToken); + } +} diff --git a/tests/Unit/BridgeRefreshTokenRepositoryTest.php b/tests/Unit/BridgeRefreshTokenRepositoryTest.php index bfde6c31..2fc90957 100644 --- a/tests/Unit/BridgeRefreshTokenRepositoryTest.php +++ b/tests/Unit/BridgeRefreshTokenRepositoryTest.php @@ -2,6 +2,11 @@ namespace Laravel\Passport\Tests\Unit; +use Carbon\CarbonImmutable; +use Illuminate\Contracts\Events\Dispatcher; +use Laravel\Passport\Bridge\AccessToken; +use Laravel\Passport\Bridge\Client; +use Laravel\Passport\Bridge\RefreshToken; use Laravel\Passport\Bridge\RefreshTokenRepository as BridgeRefreshTokenRepository; use Laravel\Passport\RefreshTokenRepository; use Mockery as m; @@ -14,49 +19,43 @@ protected function tearDown(): void m::close(); } - public function test_it_can_determine_if_a_refresh_token_is_revoked() + public function test_access_tokens_can_be_persisted() { - $refreshToken = new RevokedRefreshToken; - $repository = $this->repository($refreshToken); + $expiration = CarbonImmutable::now(); - $this->assertTrue($repository->isRefreshTokenRevoked('tokenId')); - } + $refreshTokenRepository = m::mock(RefreshTokenRepository::class); + $events = m::mock(Dispatcher::class); - public function test_a_refresh_token_is_also_revoked_if_it_cannot_be_found() - { - $refreshToken = null; - $repository = $this->repository($refreshToken); + $refreshTokenRepository->shouldReceive('create')->once()->andReturnUsing(function ($array) use ($expiration) { + $this->assertEquals('1', $array['id']); + $this->assertEquals('2', $array['access_token_id']); + $this->assertFalse($array['revoked']); + $this->assertEquals($expiration, $array['expires_at']); + }); - $this->assertTrue($repository->isRefreshTokenRevoked('tokenId')); - } + $events->shouldReceive('dispatch')->once(); - public function test_it_can_determine_if_a_refresh_token_is_not_revoked() - { - $refreshToken = new ActiveRefreshToken; - $repository = $this->repository($refreshToken); + $accessToken = new AccessToken('3', [], m::mock(Client::class)); + $accessToken->setIdentifier('2'); + + $refreshToken = new RefreshToken; + $refreshToken->setIdentifier('1'); + $refreshToken->setExpiryDateTime($expiration); + $refreshToken->setAccessToken($accessToken); + + $repository = new BridgeRefreshTokenRepository($refreshTokenRepository, $events); - $this->assertFalse($repository->isRefreshTokenRevoked('tokenId')); + $repository->persistNewRefreshToken($refreshToken); } - private function repository($refreshToken): BridgeRefreshTokenRepository + public function test_can_get_new_refresh_token() { - $refreshTokenRepository = m::mock(RefreshTokenRepository::class)->makePartial(); - $refreshTokenRepository->shouldReceive('find') - ->with('tokenId') - ->andReturn($refreshToken); + $refreshTokenRepository = m::mock(RefreshTokenRepository::class); + $events = m::mock(Dispatcher::class); + $repository = new BridgeRefreshTokenRepository($refreshTokenRepository, $events); - $events = m::mock('Illuminate\Contracts\Events\Dispatcher'); + $token = $repository->getNewRefreshToken(); - return new BridgeRefreshTokenRepository($refreshTokenRepository, $events); + $this->assertInstanceOf(RefreshToken::class, $token); } } - -class ActiveRefreshToken -{ - public $revoked = false; -} - -class RevokedRefreshToken -{ - public $revoked = true; -}