From 375fcfc1960f56a5032291f605c5da4f41d88087 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Thu, 8 Aug 2024 21:06:23 +0330 Subject: [PATCH 01/13] deprecate json api --- src/Bridge/AccessTokenRepository.php | 15 ++----- src/Bridge/RefreshTokenRepository.php | 16 +++----- src/ClientRepository.php | 10 +++++ .../AuthorizedAccessTokenController.php | 3 ++ src/Http/Controllers/ClientController.php | 3 ++ .../PersonalAccessTokenController.php | 3 ++ src/Http/Controllers/ScopeController.php | 3 ++ src/Http/Rules/RedirectRule.php | 3 ++ src/PersonalAccessTokenFactory.php | 16 ++------ src/RefreshTokenRepository.php | 15 +++++++ src/Scope.php | 5 +++ src/TokenRepository.php | 21 +++++++++- .../BridgeAccessTokenRepositoryTest.php | 39 +++++++------------ .../BridgeRefreshTokenRepositoryTest.php | 34 +++++++--------- tests/Feature/RevokedTest.php | 6 +-- 15 files changed, 108 insertions(+), 84 deletions(-) rename tests/{Unit => Feature}/BridgeAccessTokenRepositoryTest.php (55%) rename tests/{Unit => Feature}/BridgeRefreshTokenRepositoryTest.php (52%) diff --git a/src/Bridge/AccessTokenRepository.php b/src/Bridge/AccessTokenRepository.php index cf918c738..e95391447 100644 --- a/src/Bridge/AccessTokenRepository.php +++ b/src/Bridge/AccessTokenRepository.php @@ -6,7 +6,6 @@ use Illuminate\Contracts\Events\Dispatcher; use Laravel\Passport\Events\AccessTokenCreated; use Laravel\Passport\Passport; -use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; @@ -15,11 +14,6 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface { use FormatsScopesForStorage; - /** - * The token repository instance. - */ - protected TokenRepository $tokenRepository; - /** * The event dispatcher instance. */ @@ -28,10 +22,9 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface /** * Create a new repository instance. */ - public function __construct(TokenRepository $tokenRepository, Dispatcher $events) + public function __construct(Dispatcher $events) { $this->events = $events; - $this->tokenRepository = $tokenRepository; } /** @@ -50,7 +43,7 @@ public function getNewToken( */ public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity): void { - $this->tokenRepository->create([ + Passport::token()->create([ 'id' => $id = $accessTokenEntity->getIdentifier(), 'user_id' => $userId = $accessTokenEntity->getUserIdentifier(), 'client_id' => $clientId = $accessTokenEntity->getClient()->getIdentifier(), @@ -69,7 +62,7 @@ public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEnt */ public function revokeAccessToken(string $tokenId): void { - $this->tokenRepository->revokeAccessToken($tokenId); + Passport::token()->whereKey($tokenId)->update(['revoked' => true]); } /** @@ -77,6 +70,6 @@ public function revokeAccessToken(string $tokenId): void */ public function isAccessTokenRevoked(string $tokenId): bool { - return $this->tokenRepository->isAccessTokenRevoked($tokenId); + return Passport::token()->whereKey($tokenId)->where('revoked', false)->doesntExist(); } } diff --git a/src/Bridge/RefreshTokenRepository.php b/src/Bridge/RefreshTokenRepository.php index 3a35b57cb..19227e9a1 100644 --- a/src/Bridge/RefreshTokenRepository.php +++ b/src/Bridge/RefreshTokenRepository.php @@ -4,17 +4,12 @@ use Illuminate\Contracts\Events\Dispatcher; use Laravel\Passport\Events\RefreshTokenCreated; -use Laravel\Passport\RefreshTokenRepository as PassportRefreshTokenRepository; +use Laravel\Passport\Passport; use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; class RefreshTokenRepository implements RefreshTokenRepositoryInterface { - /** - * The refresh token repository instance. - */ - protected PassportRefreshTokenRepository $refreshTokenRepository; - /** * The event dispatcher instance. */ @@ -23,10 +18,9 @@ class RefreshTokenRepository implements RefreshTokenRepositoryInterface /** * Create a new repository instance. */ - public function __construct(PassportRefreshTokenRepository $refreshTokenRepository, Dispatcher $events) + public function __construct(Dispatcher $events) { $this->events = $events; - $this->refreshTokenRepository = $refreshTokenRepository; } /** @@ -42,7 +36,7 @@ public function getNewRefreshToken(): ?RefreshTokenEntityInterface */ public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity): void { - $this->refreshTokenRepository->create([ + Passport::refreshToken()->create([ 'id' => $id = $refreshTokenEntity->getIdentifier(), 'access_token_id' => $accessTokenId = $refreshTokenEntity->getAccessToken()->getIdentifier(), 'revoked' => false, @@ -57,7 +51,7 @@ public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshToken */ public function revokeRefreshToken(string $tokenId): void { - $this->refreshTokenRepository->revokeRefreshToken($tokenId); + Passport::refreshToken()->whereKey($tokenId)->update(['revoked' => true]); } /** @@ -65,6 +59,6 @@ public function revokeRefreshToken(string $tokenId): void */ public function isRefreshTokenRevoked(string $tokenId): bool { - return $this->refreshTokenRepository->isRefreshTokenRevoked($tokenId); + return Passport::refreshToken()->whereKey($tokenId)->where('revoked', false)->doesntExist(); } } diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 61ecab47d..86e798575 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -36,6 +36,8 @@ public function findActive($id) /** * Get a client instance for the given ID and user ID. * + * @deprecated Use $user->clients()->find() + * * @param int|string $clientId * @param mixed $userId * @return \Laravel\Passport\Client|null @@ -53,6 +55,8 @@ public function findForUser($clientId, $userId) /** * Get the client instances for the given user ID. * + * @deprecated Use $user->clients() + * * @param mixed $userId * @return \Illuminate\Database\Eloquent\Collection */ @@ -66,6 +70,8 @@ public function forUser($userId) /** * Get the active client instances for the given user ID. * + * @deprecated Will be removed in a future Laravel version. + * * @param mixed $userId * @return \Illuminate\Database\Eloquent\Collection */ @@ -203,6 +209,8 @@ public function regenerateSecret(Client $client) /** * Determine if the given client is revoked. * + * @deprecated Will be removed in a future Laravel version. + * * @param int|string $id * @return bool */ @@ -216,6 +224,8 @@ public function revoked($id) /** * Delete the given client. * + * @deprecated Will be removed in a future Laravel version. + * * @param \Laravel\Passport\Client $client * @return void */ diff --git a/src/Http/Controllers/AuthorizedAccessTokenController.php b/src/Http/Controllers/AuthorizedAccessTokenController.php index f31aaf61d..5817a0943 100644 --- a/src/Http/Controllers/AuthorizedAccessTokenController.php +++ b/src/Http/Controllers/AuthorizedAccessTokenController.php @@ -7,6 +7,9 @@ use Laravel\Passport\RefreshTokenRepository; use Laravel\Passport\TokenRepository; +/** + * @deprecated Will be removed in a future Laravel version. + */ class AuthorizedAccessTokenController { /** diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index ca9117f2b..6680df9eb 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -8,6 +8,9 @@ use Laravel\Passport\ClientRepository; use Laravel\Passport\Http\Rules\RedirectRule; +/** + * @deprecated Will be removed in a future Laravel version. + */ class ClientController { /** diff --git a/src/Http/Controllers/PersonalAccessTokenController.php b/src/Http/Controllers/PersonalAccessTokenController.php index 565fd4fa9..a334c2749 100644 --- a/src/Http/Controllers/PersonalAccessTokenController.php +++ b/src/Http/Controllers/PersonalAccessTokenController.php @@ -8,6 +8,9 @@ use Laravel\Passport\Passport; use Laravel\Passport\TokenRepository; +/** + * @deprecated Will be removed in a future Laravel version. + */ class PersonalAccessTokenController { /** diff --git a/src/Http/Controllers/ScopeController.php b/src/Http/Controllers/ScopeController.php index 0d726e708..bca10fe0a 100644 --- a/src/Http/Controllers/ScopeController.php +++ b/src/Http/Controllers/ScopeController.php @@ -4,6 +4,9 @@ use Laravel\Passport\Passport; +/** + * @deprecated Will be removed in a future Laravel version. + */ class ScopeController { /** diff --git a/src/Http/Rules/RedirectRule.php b/src/Http/Rules/RedirectRule.php index e14d11c3d..345deba10 100644 --- a/src/Http/Rules/RedirectRule.php +++ b/src/Http/Rules/RedirectRule.php @@ -5,6 +5,9 @@ use Illuminate\Contracts\Validation\Factory; use Illuminate\Contracts\Validation\Rule; +/** + * @deprecated Will be removed in a future Laravel version. + */ class RedirectRule implements Rule { /** diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index ed825e00a..147faad45 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -25,13 +25,6 @@ class PersonalAccessTokenFactory */ protected $clients; - /** - * The token repository instance. - * - * @var \Laravel\Passport\TokenRepository - */ - protected $tokens; - /** * The JWT token parser instance. * @@ -44,17 +37,14 @@ class PersonalAccessTokenFactory * * @param \League\OAuth2\Server\AuthorizationServer $server * @param \Laravel\Passport\ClientRepository $clients - * @param \Laravel\Passport\TokenRepository $tokens * @param \Lcobucci\JWT\Parser $jwt * @return void */ public function __construct(AuthorizationServer $server, ClientRepository $clients, - TokenRepository $tokens, JwtParser $jwt) { $this->jwt = $jwt; - $this->tokens = $tokens; $this->server = $server; $this->clients = $clients; } @@ -75,10 +65,10 @@ public function make($userId, string $name, array $scopes, string $provider) ); $token = tap($this->findAccessToken($response), function ($token) use ($userId, $name) { - $this->tokens->save($token->forceFill([ + $token->forceFill([ 'user_id' => $userId, 'name' => $name, - ])); + ])->save(); }); return new PersonalAccessTokenResult( @@ -136,7 +126,7 @@ protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $ */ public function findAccessToken(array $response) { - return $this->tokens->find( + return Passport::token()->find( $this->jwt->parse($response['access_token'])->claims()->get('jti') ); } diff --git a/src/RefreshTokenRepository.php b/src/RefreshTokenRepository.php index 61dfb9900..cbd8da42b 100644 --- a/src/RefreshTokenRepository.php +++ b/src/RefreshTokenRepository.php @@ -2,11 +2,16 @@ namespace Laravel\Passport; +/** + * @deprecated Will be removed in a future Laravel version. + */ class RefreshTokenRepository { /** * Creates a new refresh token. * + * @deprecated Will be removed in a future Laravel version. + * * @param array $attributes * @return \Laravel\Passport\RefreshToken */ @@ -18,6 +23,8 @@ public function create($attributes) /** * Gets a refresh token by the given ID. * + * @deprecated Will be removed in a future Laravel version. + * * @param string $id * @return \Laravel\Passport\RefreshToken */ @@ -29,6 +36,8 @@ public function find($id) /** * Stores the given token instance. * + * @deprecated Will be removed in a future Laravel version. + * * @param \Laravel\Passport\RefreshToken $token * @return void */ @@ -40,6 +49,8 @@ public function save(RefreshToken $token) /** * Revokes the refresh token. * + * @deprecated Will be removed in a future Laravel version. + * * @param string $id * @return mixed */ @@ -51,6 +62,8 @@ public function revokeRefreshToken($id) /** * Revokes refresh tokens by access token id. * + * @deprecated Will be removed in a future Laravel version. + * * @param string $tokenId * @return mixed */ @@ -62,6 +75,8 @@ public function revokeRefreshTokensByAccessTokenId($tokenId) /** * Checks if the refresh token has been revoked. * + * @deprecated Will be removed in a future Laravel version. + * * @param string $id * @return bool */ diff --git a/src/Scope.php b/src/Scope.php index 127b6789f..1fd95453b 100644 --- a/src/Scope.php +++ b/src/Scope.php @@ -34,6 +34,11 @@ public function __construct($id, $description) $this->description = $description; } + public static function make(string $id): ?static + { + return isset(Passport::$scopes[$id]) ? new static($id, Passport::$scopes[$id]) : null; + } + /** * Get the instance as an array. * diff --git a/src/TokenRepository.php b/src/TokenRepository.php index d64935927..ba3a7b619 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -4,11 +4,16 @@ use Carbon\Carbon; +/** + * @deprecated Will be removed in a future Laravel version. + */ class TokenRepository { /** * Creates a new Access Token. * + * @deprecated Will be removed in a future Laravel version. + * * @param array $attributes * @return \Laravel\Passport\Token */ @@ -20,6 +25,8 @@ public function create($attributes) /** * Get a token by the given ID. * + * @deprecated Will be removed in a future Laravel version. + * * @param string $id * @return \Laravel\Passport\Token */ @@ -31,6 +38,8 @@ public function find($id) /** * Get a token by the given user ID and token ID. * + * @deprecated Use $user->tokens()->find() + * * @param string $id * @param int $userId * @return \Laravel\Passport\Token|null @@ -43,6 +52,8 @@ public function findForUser($id, $userId) /** * Get the token instances for the given user ID. * + * @deprecated User $user->tokens() + * * @param mixed $userId * @return \Illuminate\Database\Eloquent\Collection */ @@ -54,7 +65,7 @@ public function forUser($userId) /** * Get a valid token instance for the given user and client. * - * @deprecated use findValidToken + * @deprecated Will be removed in a future Laravel version. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param \Laravel\Passport\Client $client @@ -72,6 +83,8 @@ public function getValidToken($user, $client) /** * Store the given token instance. * + * @deprecated Will be removed in a future Laravel version. + * * @param \Laravel\Passport\Token $token * @return void */ @@ -83,6 +96,8 @@ public function save(Token $token) /** * Revoke an access token. * + * @deprecated Will be removed in a future Laravel version. + * * @param string $id * @return mixed */ @@ -94,6 +109,8 @@ public function revokeAccessToken($id) /** * Check if the access token has been revoked. * + * @deprecated Will be removed in a future Laravel version. + * * @param string $id * @return bool */ @@ -105,6 +122,8 @@ public function isAccessTokenRevoked($id) /** * Find a valid token for the given user and client. * + * @deprecated Will be removed in a future Laravel version. + * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param \Laravel\Passport\Client $client * @return \Laravel\Passport\Token|null diff --git a/tests/Unit/BridgeAccessTokenRepositoryTest.php b/tests/Feature/BridgeAccessTokenRepositoryTest.php similarity index 55% rename from tests/Unit/BridgeAccessTokenRepositoryTest.php rename to tests/Feature/BridgeAccessTokenRepositoryTest.php index 6f64b658a..d73b799c1 100644 --- a/tests/Unit/BridgeAccessTokenRepositoryTest.php +++ b/tests/Feature/BridgeAccessTokenRepositoryTest.php @@ -1,59 +1,50 @@ shouldReceive('create')->once()->andReturnUsing(function ($array) use ($expiration) { - $this->assertEquals(1, $array['id']); - $this->assertEquals(2, $array['user_id']); - $this->assertEquals('client-id', $array['client_id']); - $this->assertEquals(['scopes'], $array['scopes']); - $this->assertEquals(false, $array['revoked']); - $this->assertInstanceOf(DateTime::class, $array['created_at']); - $this->assertInstanceOf(DateTime::class, $array['updated_at']); - $this->assertEquals($expiration, $array['expires_at']); - }); - $events->shouldReceive('dispatch')->once(); $accessToken = new AccessToken(2, [new Scope('scopes')], new Client('client-id', 'name', ['redirect'])); $accessToken->setIdentifier(1); $accessToken->setExpiryDateTime($expiration); - $repository = new AccessTokenRepository($tokenRepository, $events); + $repository = new AccessTokenRepository($events); $repository->persistNewAccessToken($accessToken); + + $this->assertDatabaseHas('oauth_access_tokens', [ + 'id' => '1', + 'user_id' => '2', + 'client_id' => 'client-id', + 'scopes' => '["scopes"]', + 'revoked' => false, + 'expires_at' => $expiration, + ]); } public function test_can_get_new_access_token() { - $tokenRepository = m::mock(TokenRepository::class); $events = m::mock(Dispatcher::class); - $repository = new AccessTokenRepository($tokenRepository, $events); + $repository = new AccessTokenRepository($events); $client = new Client('client-id', 'name', ['redirect']); $scopes = [new Scope('place-orders'), new Scope('check-status')]; $userIdentifier = 123; diff --git a/tests/Unit/BridgeRefreshTokenRepositoryTest.php b/tests/Feature/BridgeRefreshTokenRepositoryTest.php similarity index 52% rename from tests/Unit/BridgeRefreshTokenRepositoryTest.php rename to tests/Feature/BridgeRefreshTokenRepositoryTest.php index 2fc909579..7d87c41a0 100644 --- a/tests/Unit/BridgeRefreshTokenRepositoryTest.php +++ b/tests/Feature/BridgeRefreshTokenRepositoryTest.php @@ -1,38 +1,26 @@ 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']); - }); - $events->shouldReceive('dispatch')->once(); $accessToken = new AccessToken('3', [], m::mock(Client::class)); @@ -43,16 +31,22 @@ public function test_access_tokens_can_be_persisted() $refreshToken->setExpiryDateTime($expiration); $refreshToken->setAccessToken($accessToken); - $repository = new BridgeRefreshTokenRepository($refreshTokenRepository, $events); + $repository = new RefreshTokenRepository($events); $repository->persistNewRefreshToken($refreshToken); + + $this->assertDatabaseHas('oauth_refresh_tokens', [ + 'id' => '1', + 'access_token_id' => '2', + 'revoked' => false, + 'expires_at' => $expiration, + ]); } public function test_can_get_new_refresh_token() { - $refreshTokenRepository = m::mock(RefreshTokenRepository::class); $events = m::mock(Dispatcher::class); - $repository = new BridgeRefreshTokenRepository($refreshTokenRepository, $events); + $repository = new RefreshTokenRepository($events); $token = $repository->getNewRefreshToken(); diff --git a/tests/Feature/RevokedTest.php b/tests/Feature/RevokedTest.php index 2ba758967..9a61f3dc4 100644 --- a/tests/Feature/RevokedTest.php +++ b/tests/Feature/RevokedTest.php @@ -7,9 +7,7 @@ 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; @@ -97,7 +95,7 @@ private function accessTokenRepository(): BridgeAccessTokenRepository $events = m::mock('Illuminate\Contracts\Events\Dispatcher'); $events->shouldReceive('dispatch'); - return new BridgeAccessTokenRepository(new TokenRepository, $events); + return new BridgeAccessTokenRepository($events); } private function persistNewAccessToken(BridgeAccessTokenRepository $repository, string $id): void @@ -134,7 +132,7 @@ private function refreshTokenRepository(): BridgeRefreshTokenRepository $events = m::mock('Illuminate\Contracts\Events\Dispatcher'); $events->shouldReceive('dispatch'); - return new BridgeRefreshTokenRepository(new RefreshTokenRepository, $events); + return new BridgeRefreshTokenRepository($events); } private function persistNewRefreshToken(BridgeRefreshTokenRepository $repository, string $id): void From 408f701ca99957ce5c233edd0def165abe1db7b1 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Thu, 8 Aug 2024 21:06:35 +0330 Subject: [PATCH 02/13] wip --- routes/web.php | 101 ++++++++++++++++++++++++----------------------- src/Passport.php | 7 ++++ 2 files changed, 59 insertions(+), 49 deletions(-) diff --git a/routes/web.php b/routes/web.php index fa2ecf3fe..a92887790 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,7 @@ 'AccessTokenController@issueToken', @@ -32,53 +33,55 @@ 'as' => 'authorizations.deny', ]); - Route::get('/tokens', [ - 'uses' => 'AuthorizedAccessTokenController@forUser', - 'as' => 'tokens.index', - ]); - - Route::delete('/tokens/{token_id}', [ - 'uses' => 'AuthorizedAccessTokenController@destroy', - 'as' => 'tokens.destroy', - ]); - - Route::get('/clients', [ - 'uses' => 'ClientController@forUser', - 'as' => 'clients.index', - ]); - - Route::post('/clients', [ - 'uses' => 'ClientController@store', - 'as' => 'clients.store', - ]); - - Route::put('/clients/{client_id}', [ - 'uses' => 'ClientController@update', - 'as' => 'clients.update', - ]); - - Route::delete('/clients/{client_id}', [ - 'uses' => 'ClientController@destroy', - 'as' => 'clients.destroy', - ]); - - Route::get('/scopes', [ - 'uses' => 'ScopeController@all', - 'as' => 'scopes.index', - ]); - - Route::get('/personal-access-tokens', [ - 'uses' => 'PersonalAccessTokenController@forUser', - 'as' => 'personal.tokens.index', - ]); - - Route::post('/personal-access-tokens', [ - 'uses' => 'PersonalAccessTokenController@store', - 'as' => 'personal.tokens.store', - ]); - - Route::delete('/personal-access-tokens/{token_id}', [ - 'uses' => 'PersonalAccessTokenController@destroy', - 'as' => 'personal.tokens.destroy', - ]); + if (Passport::$registersJsonApiRoutes) { + Route::get('/tokens', [ + 'uses' => 'AuthorizedAccessTokenController@forUser', + 'as' => 'tokens.index', + ]); + + Route::delete('/tokens/{token_id}', [ + 'uses' => 'AuthorizedAccessTokenController@destroy', + 'as' => 'tokens.destroy', + ]); + + Route::get('/clients', [ + 'uses' => 'ClientController@forUser', + 'as' => 'clients.index', + ]); + + Route::post('/clients', [ + 'uses' => 'ClientController@store', + 'as' => 'clients.store', + ]); + + Route::put('/clients/{client_id}', [ + 'uses' => 'ClientController@update', + 'as' => 'clients.update', + ]); + + Route::delete('/clients/{client_id}', [ + 'uses' => 'ClientController@destroy', + 'as' => 'clients.destroy', + ]); + + Route::get('/scopes', [ + 'uses' => 'ScopeController@all', + 'as' => 'scopes.index', + ]); + + Route::get('/personal-access-tokens', [ + 'uses' => 'PersonalAccessTokenController@forUser', + 'as' => 'personal.tokens.index', + ]); + + Route::post('/personal-access-tokens', [ + 'uses' => 'PersonalAccessTokenController@store', + 'as' => 'personal.tokens.store', + ]); + + Route::delete('/personal-access-tokens/{token_id}', [ + 'uses' => 'PersonalAccessTokenController@destroy', + 'as' => 'personal.tokens.destroy', + ]); + } }); diff --git a/src/Passport.php b/src/Passport.php index d24412f5b..73516417c 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -177,6 +177,13 @@ class Passport */ public static $registersRoutes = true; + /** + * Indicates if Passport JSON API routes will be registered. + * + * @var bool + */ + public static $registersJsonApiRoutes = false; + /** * Enable the implicit grant type. * From 56a9883d2fec0cd2cff00b44c64971cd3e12f0ca Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Thu, 8 Aug 2024 21:14:27 +0330 Subject: [PATCH 03/13] upgrade guide --- UPGRADE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/UPGRADE.md b/UPGRADE.md index 0421175e6..03ec08f90 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -61,6 +61,17 @@ Passport's `oauth_personal_access_clients` table has been redundant and unnecess In addition, the `Laravel\Passport\PersonalAccessClient` model, `Passport::$personalAccessClientModel` property, `Passport::usePersonalAccessClientModel()`, `Passport::personalAccessClientModel()`, and `Passport::personalAccessClient()` methods have been removed. +### JSON API Deprecation + +PR: https://github.com/laravel/passport/pull/1778 + +Passport's JSON API has been deprecated in favor of new Jetstream OAuth features. If you wish, you may continue using deprecated JSON API by setting `Passport::$registersJsonApiRoutes` to `true` within the `boot` method of your application's `App\Providers\AppServiceProvider` class: + + public function boot(): void + { + Passport::$registersJsonApiRoutes = true; + } + ## Upgrading To 12.0 From 11.x ### Migration Changes From ac7ed35e3558599a1c0fc2d8ab94816db388a308 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Wed, 14 Aug 2024 07:47:40 +0330 Subject: [PATCH 04/13] wip --- src/ClientRepository.php | 2 ++ src/Http/Rules/UriRule.php | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 86e798575..f5c908496 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -175,6 +175,8 @@ public function createAuthorizationCodeGrantClient( /** * Update the given client. * + * @deprecated Will be removed in a future Laravel version. + * * @param string[] $redirectUris */ public function update(Client $client, string $name, array $redirectUris): bool diff --git a/src/Http/Rules/UriRule.php b/src/Http/Rules/UriRule.php index f6d02c65e..653671e5b 100644 --- a/src/Http/Rules/UriRule.php +++ b/src/Http/Rules/UriRule.php @@ -4,6 +4,9 @@ use Illuminate\Contracts\Validation\Rule; +/** + * @deprecated Will be removed in a future Laravel version. + */ class UriRule implements Rule { /** From d6927136484289283c5fcdd8c91fd82390fd2a6e Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Wed, 14 Aug 2024 23:26:14 +0330 Subject: [PATCH 05/13] wip --- src/Client.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Client.php b/src/Client.php index f211670dc..6af6fbced 100644 --- a/src/Client.php +++ b/src/Client.php @@ -154,6 +154,8 @@ protected function redirectUris(): Attribute /** * Determine if the client is a "first party" client. * + * @deprecated Will be removed in a future Laravel version. + * * @return bool */ public function firstParty() From fe1085869f0277f18d2b2d4032815a75b0adc3b8 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Thu, 15 Aug 2024 01:49:12 +0330 Subject: [PATCH 06/13] wip --- src/Scope.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Scope.php b/src/Scope.php index 1fd95453b..127b6789f 100644 --- a/src/Scope.php +++ b/src/Scope.php @@ -34,11 +34,6 @@ public function __construct($id, $description) $this->description = $description; } - public static function make(string $id): ?static - { - return isset(Passport::$scopes[$id]) ? new static($id, Passport::$scopes[$id]) : null; - } - /** * Get the instance as an array. * From 35569211b99461291e7522a01345f0d4560f006b Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Thu, 22 Aug 2024 17:08:35 +0330 Subject: [PATCH 07/13] fix tests --- src/Bridge/AccessTokenRepository.php | 8 +------- .../BridgeAccessTokenRepositoryTest.php | 20 ++++++++----------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/Bridge/AccessTokenRepository.php b/src/Bridge/AccessTokenRepository.php index 4e4065643..f1ddf6ef6 100644 --- a/src/Bridge/AccessTokenRepository.php +++ b/src/Bridge/AccessTokenRepository.php @@ -7,7 +7,6 @@ use Laravel\Passport\Events\AccessTokenCreated; use Laravel\Passport\Events\AccessTokenRevoked; use Laravel\Passport\Passport; -use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; @@ -16,11 +15,6 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface { use FormatsScopesForStorage; - /** - * The token repository instance. - */ - protected TokenRepository $tokenRepository; - /** * The event dispatcher instance. */ @@ -69,7 +63,7 @@ public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEnt */ public function revokeAccessToken(string $tokenId): void { - if (Passport::token()->whereKey($tokenId)->update(['revoked' => true])) { + if (Passport::token()->newQuery()->whereKey($tokenId)->update(['revoked' => true])) { $this->events->dispatch(new AccessTokenRevoked($tokenId)); } } diff --git a/tests/Feature/BridgeAccessTokenRepositoryTest.php b/tests/Feature/BridgeAccessTokenRepositoryTest.php index 8efbb5e52..7a570ebac 100644 --- a/tests/Feature/BridgeAccessTokenRepositoryTest.php +++ b/tests/Feature/BridgeAccessTokenRepositoryTest.php @@ -43,30 +43,26 @@ public function test_access_tokens_can_be_persisted() public function test_access_tokens_can_be_revoked() { - $tokenRepository = m::mock(TokenRepository::class); $events = m::mock(Dispatcher::class); + $events->shouldReceive('dispatch')->twice(); - $tokenRepository->shouldReceive('revokeAccessToken')->with('token-id')->once()->andReturn(1); - $events->shouldReceive('dispatch')->once(); + $accessToken = new AccessToken(2, [], new Client('client-id', 'name', ['redirect'])); + $accessToken->setIdentifier('token-id'); + $accessToken->setExpiryDateTime(CarbonImmutable::now()); - $repository = new AccessTokenRepository($tokenRepository, $events); - $repository->revokeAccessToken('token-id'); + $repository = new AccessTokenRepository($events); + $repository->persistNewAccessToken($accessToken); - $this->expectNotToPerformAssertions(); + $repository->revokeAccessToken('token-id'); } public function test_access_token_revoke_event_is_not_dispatched_when_nothing_happened() { - $tokenRepository = m::mock(TokenRepository::class); $events = m::mock(Dispatcher::class); - - $tokenRepository->shouldReceive('revokeAccessToken')->with('token-id')->once()->andReturn(0); $events->shouldNotReceive('dispatch'); - $repository = new AccessTokenRepository($tokenRepository, $events); + $repository = new AccessTokenRepository($events); $repository->revokeAccessToken('token-id'); - - $this->expectNotToPerformAssertions(); } public function test_can_get_new_access_token() From 84d9d4aa81bdbc088526d7a109ca52e579c4cb8c Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Thu, 22 Aug 2024 17:13:49 +0330 Subject: [PATCH 08/13] formatting --- src/Bridge/AccessTokenRepository.php | 4 ++-- src/Bridge/RefreshTokenRepository.php | 6 +++--- src/PersonalAccessTokenFactory.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Bridge/AccessTokenRepository.php b/src/Bridge/AccessTokenRepository.php index f1ddf6ef6..15bd69e97 100644 --- a/src/Bridge/AccessTokenRepository.php +++ b/src/Bridge/AccessTokenRepository.php @@ -44,7 +44,7 @@ public function getNewToken( */ public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity): void { - Passport::token()->create([ + Passport::token()->newQuery()->create([ 'id' => $id = $accessTokenEntity->getIdentifier(), 'user_id' => $userId = $accessTokenEntity->getUserIdentifier(), 'client_id' => $clientId = $accessTokenEntity->getClient()->getIdentifier(), @@ -73,6 +73,6 @@ public function revokeAccessToken(string $tokenId): void */ public function isAccessTokenRevoked(string $tokenId): bool { - return Passport::token()->whereKey($tokenId)->where('revoked', false)->doesntExist(); + return Passport::token()->newQuery()->whereKey($tokenId)->where('revoked', false)->doesntExist(); } } diff --git a/src/Bridge/RefreshTokenRepository.php b/src/Bridge/RefreshTokenRepository.php index 19227e9a1..f4cfa09e3 100644 --- a/src/Bridge/RefreshTokenRepository.php +++ b/src/Bridge/RefreshTokenRepository.php @@ -36,7 +36,7 @@ public function getNewRefreshToken(): ?RefreshTokenEntityInterface */ public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity): void { - Passport::refreshToken()->create([ + Passport::refreshToken()->newQuery()->create([ 'id' => $id = $refreshTokenEntity->getIdentifier(), 'access_token_id' => $accessTokenId = $refreshTokenEntity->getAccessToken()->getIdentifier(), 'revoked' => false, @@ -51,7 +51,7 @@ public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshToken */ public function revokeRefreshToken(string $tokenId): void { - Passport::refreshToken()->whereKey($tokenId)->update(['revoked' => true]); + Passport::refreshToken()->newQuery()->whereKey($tokenId)->update(['revoked' => true]); } /** @@ -59,6 +59,6 @@ public function revokeRefreshToken(string $tokenId): void */ public function isRefreshTokenRevoked(string $tokenId): bool { - return Passport::refreshToken()->whereKey($tokenId)->where('revoked', false)->doesntExist(); + return Passport::refreshToken()->newQuery()->whereKey($tokenId)->where('revoked', false)->doesntExist(); } } diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index cdd0069c4..2badb1cb8 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -104,7 +104,7 @@ protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $ */ public function findAccessToken(array $response) { - return Passport::token()->find( + return Passport::token()->newQuery()->find( $this->jwt->parse($response['access_token'])->claims()->get('jti') ); } From 6c37c4ba64b9b9502cc7939c92910e723750f8a7 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Fri, 23 Aug 2024 21:02:34 +0330 Subject: [PATCH 09/13] wip --- src/Client.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Client.php b/src/Client.php index 6af6fbced..f211670dc 100644 --- a/src/Client.php +++ b/src/Client.php @@ -154,8 +154,6 @@ protected function redirectUris(): Attribute /** * Determine if the client is a "first party" client. * - * @deprecated Will be removed in a future Laravel version. - * * @return bool */ public function firstParty() From e9b836127f4ab6661fec1c5428557da601413dbf Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Tue, 8 Oct 2024 12:57:00 +0330 Subject: [PATCH 10/13] fix bugs --- src/ClientRepository.php | 66 ++------- .../AuthorizedAccessTokenController.php | 52 ++----- src/Http/Controllers/ClientController.php | 73 +++------- .../PersonalAccessTokenController.php | 59 +++----- src/Http/Controllers/ScopeController.php | 5 +- src/Http/Rules/RedirectRule.php | 20 +-- src/RefreshTokenRepository.php | 87 ------------ src/TokenRepository.php | 132 +++--------------- .../AuthorizedAccessTokenControllerTest.php | 25 ++-- tests/Unit/ClientControllerTest.php | 52 ++++--- .../PersonalAccessTokenControllerTest.php | 29 ++-- tests/Unit/TokenGuardTest.php | 2 - 12 files changed, 138 insertions(+), 464 deletions(-) delete mode 100644 src/RefreshTokenRepository.php diff --git a/src/ClientRepository.php b/src/ClientRepository.php index ce219aede..3b95602a5 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Str; use RuntimeException; @@ -32,18 +33,11 @@ public function findActive(string|int $id): ?Client * * @deprecated Use $user->clients()->find() * - * @param int|string $clientId - * @param mixed $userId - * @return \Laravel\Passport\Client|null + * @param \Laravel\Passport\HasApiTokens $user */ - public function findForUser($clientId, $userId) + public function findForUser(string|int $clientId, Authenticatable $user): ?Client { - $client = Passport::client(); - - return $client - ->where($client->getKeyName(), $clientId) - ->where('user_id', $userId) - ->first(); + return $user->clients()->where('revoked', false)->find($clientId); } /** @@ -51,29 +45,12 @@ public function findForUser($clientId, $userId) * * @deprecated Use $user->clients() * - * @param mixed $userId - * @return \Illuminate\Database\Eloquent\Collection - */ - public function forUser($userId) - { - return Passport::client() - ->where('user_id', $userId) - ->orderBy('name', 'asc')->get(); - } - - /** - * Get the active client instances for the given user ID. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param mixed $userId - * @return \Illuminate\Database\Eloquent\Collection + * @param \Laravel\Passport\HasApiTokens $user + * @return \Illuminate\Database\Eloquent\Collection */ - public function activeForUser($userId) + public function forUser(Authenticatable $user): Collection { - return $this->forUser($userId)->reject(function ($client) { - return $client->revoked; - })->values(); + return $user->clients()->where('revoked', false)->orderBy('name')->get(); } /* @@ -223,31 +200,16 @@ public function regenerateSecret(Client $client): bool } /** - * Determine if the given client is revoked. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param int|string $id - * @return bool - */ - public function revoked($id) - { - $client = $this->find($id); - - return is_null($client) || $client->revoked; - } - - /** - * Delete the given client. + * Revoke the given client and its tokens. * * @deprecated Will be removed in a future Laravel version. - * - * @param \Laravel\Passport\Client $client - * @return void */ - public function delete(Client $client) + public function revoke(Client $client): void { - $client->tokens()->update(['revoked' => true]); + $client->tokens()->with('refreshToken')->each(function (Token $token): void { + $token->revoke(); + $token->refreshToken?->revoke(); + }); $client->forceFill(['revoked' => true])->save(); } diff --git a/src/Http/Controllers/AuthorizedAccessTokenController.php b/src/Http/Controllers/AuthorizedAccessTokenController.php index 5817a0943..ee82faa1b 100644 --- a/src/Http/Controllers/AuthorizedAccessTokenController.php +++ b/src/Http/Controllers/AuthorizedAccessTokenController.php @@ -2,9 +2,10 @@ namespace Laravel\Passport\Http\Controllers; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\Request; use Illuminate\Http\Response; -use Laravel\Passport\RefreshTokenRepository; +use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; /** @@ -12,59 +13,33 @@ */ class AuthorizedAccessTokenController { - /** - * The token repository implementation. - * - * @var \Laravel\Passport\TokenRepository - */ - protected $tokenRepository; - - /** - * The refresh token repository implementation. - * - * @var \Laravel\Passport\RefreshTokenRepository - */ - protected $refreshTokenRepository; - /** * Create a new controller instance. - * - * @param \Laravel\Passport\TokenRepository $tokenRepository - * @param \Laravel\Passport\RefreshTokenRepository $refreshTokenRepository - * @return void */ - public function __construct(TokenRepository $tokenRepository, RefreshTokenRepository $refreshTokenRepository) - { - $this->tokenRepository = $tokenRepository; - $this->refreshTokenRepository = $refreshTokenRepository; + public function __construct( + protected TokenRepository $tokenRepository + ) { } /** * Get all of the authorized tokens for the authenticated user. * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Database\Eloquent\Collection + * @return \Illuminate\Database\Eloquent\Collection */ - public function forUser(Request $request) + public function forUser(Request $request): Collection { - $tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier()); - - return $tokens->load('client')->filter(function ($token) { - return ! $token->client->firstParty() && ! $token->revoked; - })->values(); + return $this->tokenRepository->forUser($request->user()) + ->reject(fn (Token $token): bool => $token->client->revoked || $token->client->firstParty()) + ->values(); } /** * Delete the given token. - * - * @param \Illuminate\Http\Request $request - * @param string $tokenId - * @return \Illuminate\Http\Response */ - public function destroy(Request $request, $tokenId) + public function destroy(Request $request, string $tokenId): Response { $token = $this->tokenRepository->findForUser( - $tokenId, $request->user()->getAuthIdentifier() + $tokenId, $request->user() ); if (is_null($token)) { @@ -72,8 +47,7 @@ public function destroy(Request $request, $tokenId) } $token->revoke(); - - $this->refreshTokenRepository->revokeRefreshTokensByAccessTokenId($tokenId); + $token->refreshToken?->revoke(); return new Response('', Response::HTTP_NO_CONTENT); } diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index 6680df9eb..36b59ec4c 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -3,8 +3,10 @@ namespace Laravel\Passport\Http\Controllers; use Illuminate\Contracts\Validation\Factory as ValidationFactory; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\Request; use Illuminate\Http\Response; +use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; use Laravel\Passport\Http\Rules\RedirectRule; @@ -13,68 +15,33 @@ */ class ClientController { - /** - * The client repository instance. - * - * @var \Laravel\Passport\ClientRepository - */ - protected $clients; - - /** - * The validation factory implementation. - * - * @var \Illuminate\Contracts\Validation\Factory - */ - protected $validation; - - /** - * The redirect validation rule. - * - * @var \Laravel\Passport\Http\Rules\RedirectRule - */ - protected $redirectRule; - /** * Create a client controller instance. - * - * @param \Laravel\Passport\ClientRepository $clients - * @param \Illuminate\Contracts\Validation\Factory $validation - * @param \Laravel\Passport\Http\Rules\RedirectRule $redirectRule - * @return void */ public function __construct( - ClientRepository $clients, - ValidationFactory $validation, - RedirectRule $redirectRule + protected ClientRepository $clients, + protected ValidationFactory $validation, + protected RedirectRule $redirectRule ) { - $this->clients = $clients; - $this->validation = $validation; - $this->redirectRule = $redirectRule; } /** * Get all of the clients for the authenticated user. * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Database\Eloquent\Collection + * @return \Illuminate\Database\Eloquent\Collection */ - public function forUser(Request $request) + public function forUser(Request $request): Collection { - $userId = $request->user()->getAuthIdentifier(); - - return $this->clients->activeForUser($userId); + return $this->clients->forUser($request->user()); } /** * Store a new client. - * - * @param \Illuminate\Http\Request $request - * @return \Laravel\Passport\Client|array */ - public function store(Request $request) + public function store(Request $request): Client { $this->validation->make($request->all(), [ - 'name' => 'required|max:191', + 'name' => ['required', 'string', 'max:255'], 'redirect' => ['required', $this->redirectRule], 'confidential' => 'boolean', ])->validate(); @@ -93,21 +60,17 @@ public function store(Request $request) /** * Update the given client. - * - * @param \Illuminate\Http\Request $request - * @param string $clientId - * @return \Illuminate\Http\Response|\Laravel\Passport\Client */ - public function update(Request $request, $clientId) + public function update(Request $request, string|int $clientId): Response|Client { - $client = $this->clients->findForUser($clientId, $request->user()->getAuthIdentifier()); + $client = $this->clients->findForUser($clientId, $request->user()); if (! $client) { return new Response('', 404); } $this->validation->make($request->all(), [ - 'name' => 'required|max:191', + 'name' => ['required', 'string', 'max:255'], 'redirect' => ['required', $this->redirectRule], ])->validate(); @@ -120,20 +83,16 @@ public function update(Request $request, $clientId) /** * Delete the given client. - * - * @param \Illuminate\Http\Request $request - * @param string $clientId - * @return \Illuminate\Http\Response */ - public function destroy(Request $request, $clientId) + public function destroy(Request $request, string|int $clientId): Response { - $client = $this->clients->findForUser($clientId, $request->user()->getAuthIdentifier()); + $client = $this->clients->findForUser($clientId, $request->user()); if (! $client) { return new Response('', 404); } - $this->clients->delete($client); + $this->clients->revoke($client); return new Response('', Response::HTTP_NO_CONTENT); } diff --git a/src/Http/Controllers/PersonalAccessTokenController.php b/src/Http/Controllers/PersonalAccessTokenController.php index a334c2749..55159159c 100644 --- a/src/Http/Controllers/PersonalAccessTokenController.php +++ b/src/Http/Controllers/PersonalAccessTokenController.php @@ -5,7 +5,10 @@ use Illuminate\Contracts\Validation\Factory as ValidationFactory; use Illuminate\Http\Request; use Illuminate\Http\Response; +use Illuminate\Validation\Rule; use Laravel\Passport\Passport; +use Laravel\Passport\PersonalAccessTokenResult; +use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; /** @@ -13,59 +16,37 @@ */ class PersonalAccessTokenController { - /** - * The token repository implementation. - * - * @var \Laravel\Passport\TokenRepository - */ - protected $tokenRepository; - - /** - * The validation factory implementation. - * - * @var \Illuminate\Contracts\Validation\Factory - */ - protected $validation; - /** * Create a controller instance. - * - * @param \Laravel\Passport\TokenRepository $tokenRepository - * @param \Illuminate\Contracts\Validation\Factory $validation - * @return void */ - public function __construct(TokenRepository $tokenRepository, ValidationFactory $validation) - { - $this->validation = $validation; - $this->tokenRepository = $tokenRepository; + public function __construct( + protected TokenRepository $tokenRepository, + protected ValidationFactory $validation + ) { } /** * Get all of the personal access tokens for the authenticated user. * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Database\Eloquent\Collection + * @return \Illuminate\Database\Eloquent\Collection */ public function forUser(Request $request) { - $tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier()); - - return $tokens->load('client')->filter(function ($token) { - return $token->client->hasGrantType('personal_access') && ! $token->revoked; - })->values(); + return $this->tokenRepository->forUser($request->user()) + ->filter( + fn (Token $token): bool => ! $token->client->revoked && $token->client->hasGrantType('personal_access') + ) + ->values(); } /** * Create a new personal access token for the user. - * - * @param \Illuminate\Http\Request $request - * @return \Laravel\Passport\PersonalAccessTokenResult */ - public function store(Request $request) + public function store(Request $request): PersonalAccessTokenResult { $this->validation->make($request->all(), [ - 'name' => 'required|max:191', - 'scopes' => 'array|in:'.implode(',', Passport::scopeIds()), + 'name' => ['required', 'max:255'], + 'scopes' => ['array', Rule::in(Passport::scopeIds())], ])->validate(); return $request->user()->createToken( @@ -75,15 +56,11 @@ public function store(Request $request) /** * Delete the given token. - * - * @param \Illuminate\Http\Request $request - * @param string $tokenId - * @return \Illuminate\Http\Response */ - public function destroy(Request $request, $tokenId) + public function destroy(Request $request, string $tokenId): Response { $token = $this->tokenRepository->findForUser( - $tokenId, $request->user()->getAuthIdentifier() + $tokenId, $request->user() ); if (is_null($token)) { diff --git a/src/Http/Controllers/ScopeController.php b/src/Http/Controllers/ScopeController.php index bca10fe0a..946f7aa52 100644 --- a/src/Http/Controllers/ScopeController.php +++ b/src/Http/Controllers/ScopeController.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Http\Controllers; +use Illuminate\Support\Collection; use Laravel\Passport\Passport; /** @@ -12,9 +13,9 @@ class ScopeController /** * Get all of the available scopes for the application. * - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ - public function all() + public function all(): Collection { return Passport::scopes(); } diff --git a/src/Http/Rules/RedirectRule.php b/src/Http/Rules/RedirectRule.php index 345deba10..fdb3676ee 100644 --- a/src/Http/Rules/RedirectRule.php +++ b/src/Http/Rules/RedirectRule.php @@ -10,28 +10,18 @@ */ class RedirectRule implements Rule { - /** - * The validator instance. - * - * @var \Illuminate\Contracts\Validation\Factory - */ - protected $validator; - /** * Create a new rule instance. - * - * @param \Illuminate\Contracts\Validation\Factory $validator - * @return void */ - public function __construct(Factory $validator) - { - $this->validator = $validator; + public function __construct( + protected Factory $validator + ) { } /** * {@inheritdoc} */ - public function passes($attribute, $value) + public function passes($attribute, $value): bool { foreach (explode(',', $value) as $redirect) { $validator = $this->validator->make(['redirect' => $redirect], ['redirect' => new UriRule]); @@ -47,7 +37,7 @@ public function passes($attribute, $value) /** * {@inheritdoc} */ - public function message() + public function message(): string { return 'One or more redirects have an invalid URI format.'; } diff --git a/src/RefreshTokenRepository.php b/src/RefreshTokenRepository.php deleted file mode 100644 index cbd8da42b..000000000 --- a/src/RefreshTokenRepository.php +++ /dev/null @@ -1,87 +0,0 @@ -create($attributes); - } - - /** - * Gets a refresh token by the given ID. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param string $id - * @return \Laravel\Passport\RefreshToken - */ - public function find($id) - { - return Passport::refreshToken()->where('id', $id)->first(); - } - - /** - * Stores the given token instance. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param \Laravel\Passport\RefreshToken $token - * @return void - */ - public function save(RefreshToken $token) - { - $token->save(); - } - - /** - * Revokes the refresh token. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param string $id - * @return mixed - */ - public function revokeRefreshToken($id) - { - return Passport::refreshToken()->where('id', $id)->update(['revoked' => true]); - } - - /** - * Revokes refresh tokens by access token id. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param string $tokenId - * @return mixed - */ - public function revokeRefreshTokensByAccessTokenId($tokenId) - { - return Passport::refreshToken()->where('access_token_id', $tokenId)->update(['revoked' => true]); - } - - /** - * Checks if the refresh token has been revoked. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param string $id - * @return bool - */ - public function isRefreshTokenRevoked($id) - { - return Passport::refreshToken()->where('id', $id)->where('revoked', 0)->doesntExist(); - } -} diff --git a/src/TokenRepository.php b/src/TokenRepository.php index ba3a7b619..50ff19738 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -2,139 +2,45 @@ namespace Laravel\Passport; -use Carbon\Carbon; +use Illuminate\Contracts\Auth\Authenticatable; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Support\Facades\Date; /** * @deprecated Will be removed in a future Laravel version. */ class TokenRepository { - /** - * Creates a new Access Token. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param array $attributes - * @return \Laravel\Passport\Token - */ - public function create($attributes) - { - return Passport::token()->create($attributes); - } - - /** - * Get a token by the given ID. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param string $id - * @return \Laravel\Passport\Token - */ - public function find($id) - { - return Passport::token()->where('id', $id)->first(); - } - /** * Get a token by the given user ID and token ID. * * @deprecated Use $user->tokens()->find() * - * @param string $id - * @param int $userId - * @return \Laravel\Passport\Token|null + * @param \Laravel\Passport\HasApiTokens $user */ - public function findForUser($id, $userId) + public function findForUser(string $id, Authenticatable $user): ?Token { - return Passport::token()->where('id', $id)->where('user_id', $userId)->first(); + return $user->tokens() + ->with('client') + ->where('revoked', false) + ->where('expires_at', '>', Date::now()) + ->find($id); } /** * Get the token instances for the given user ID. * - * @deprecated User $user->tokens() - * - * @param mixed $userId - * @return \Illuminate\Database\Eloquent\Collection - */ - public function forUser($userId) - { - return Passport::token()->where('user_id', $userId)->get(); - } - - /** - * Get a valid token instance for the given user and client. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param \Illuminate\Contracts\Auth\Authenticatable $user - * @param \Laravel\Passport\Client $client - * @return \Laravel\Passport\Token|null - */ - public function getValidToken($user, $client) - { - return $client->tokens() - ->whereUserId($user->getAuthIdentifier()) - ->where('revoked', 0) - ->where('expires_at', '>', Carbon::now()) - ->first(); - } - - /** - * Store the given token instance. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param \Laravel\Passport\Token $token - * @return void - */ - public function save(Token $token) - { - $token->save(); - } - - /** - * Revoke an access token. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param string $id - * @return mixed - */ - public function revokeAccessToken($id) - { - return Passport::token()->where('id', $id)->update(['revoked' => true]); - } - - /** - * Check if the access token has been revoked. - * - * @deprecated Will be removed in a future Laravel version. - * - * @param string $id - * @return bool - */ - public function isAccessTokenRevoked($id) - { - return Passport::token()->where('id', $id)->where('revoked', 0)->doesntExist(); - } - - /** - * Find a valid token for the given user and client. - * - * @deprecated Will be removed in a future Laravel version. + * @deprecated Use $user->tokens() * - * @param \Illuminate\Contracts\Auth\Authenticatable $user - * @param \Laravel\Passport\Client $client - * @return \Laravel\Passport\Token|null + * @param \Laravel\Passport\HasApiTokens $user + * @return \Illuminate\Database\Eloquent\Collection */ - public function findValidToken($user, $client) + public function forUser(Authenticatable $user): Collection { - return $client->tokens() - ->whereUserId($user->getAuthIdentifier()) - ->where('revoked', 0) - ->where('expires_at', '>', Carbon::now()) - ->latest('expires_at') - ->first(); + return $user->tokens() + ->with('client') + ->where('revoked', false) + ->where('expires_at', '>', Date::now()) + ->get(); } } diff --git a/tests/Unit/AuthorizedAccessTokenControllerTest.php b/tests/Unit/AuthorizedAccessTokenControllerTest.php index 25fdb512a..042c316ab 100644 --- a/tests/Unit/AuthorizedAccessTokenControllerTest.php +++ b/tests/Unit/AuthorizedAccessTokenControllerTest.php @@ -2,10 +2,11 @@ namespace Laravel\Passport\Tests\Unit; +use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Http\Request; use Laravel\Passport\Client; use Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController; -use Laravel\Passport\RefreshTokenRepository; +use Laravel\Passport\RefreshToken; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; @@ -21,11 +22,6 @@ class AuthorizedAccessTokenControllerTest extends TestCase */ protected $tokenRepository; - /** - * @var \Mockery\Mock|\Laravel\Passport\RefreshTokenRepository - */ - protected $refreshTokenRepository; - /** * @var AuthorizedAccessTokenController */ @@ -34,8 +30,7 @@ class AuthorizedAccessTokenControllerTest extends TestCase protected function setUp(): void { $this->tokenRepository = m::mock(TokenRepository::class); - $this->refreshTokenRepository = m::mock(RefreshTokenRepository::class); - $this->controller = new AuthorizedAccessTokenController($this->tokenRepository, $this->refreshTokenRepository); + $this->controller = new AuthorizedAccessTokenController($this->tokenRepository); } protected function tearDown(): void @@ -52,7 +47,6 @@ public function test_tokens_can_be_retrieved_for_users() $token1 = new Token; $token2 = new Token; - $userTokens = m::mock(); $client1 = new Client; $client1->grant_types = ['personal_access']; $client2 = new Client; @@ -60,14 +54,14 @@ public function test_tokens_can_be_retrieved_for_users() $client2->user_id = 2; $token1->client = $client1; $token2->client = $client2; - $userTokens->shouldReceive('load')->with('client')->andReturn(collect([ + $userTokens = (new Token)->newCollection([ $token1, $token2, - ])); + ]); $this->tokenRepository->shouldReceive('forUser')->andReturn($userTokens); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; @@ -85,13 +79,14 @@ public function test_tokens_can_be_deleted() $token1 = m::mock(Token::class.'[revoke]'); $token1->id = 1; + $token1->refreshToken = m::mock(RefreshToken::class); + $token1->refreshToken->shouldReceive('revoke')->once(); $token1->shouldReceive('revoke')->once(); $this->tokenRepository->shouldReceive('findForUser')->andReturn($token1); - $this->refreshTokenRepository->shouldReceive('revokeRefreshTokensByAccessTokenId')->once(); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; @@ -109,7 +104,7 @@ public function test_not_found_response_is_returned_if_user_doesnt_have_token() $this->tokenRepository->shouldReceive('findForUser')->with(3, 1)->andReturnNull(); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; diff --git a/tests/Unit/ClientControllerTest.php b/tests/Unit/ClientControllerTest.php index 9d360f173..0053ca5c4 100644 --- a/tests/Unit/ClientControllerTest.php +++ b/tests/Unit/ClientControllerTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Validation\Factory; use Illuminate\Http\Request; use Laravel\Passport\Client; @@ -19,26 +20,30 @@ class ClientControllerTest extends TestCase public function test_all_the_clients_for_the_current_user_can_be_retrieved() { - $clients = m::mock(ClientRepository::class); - $clients->shouldReceive('activeForUser')->once()->with(1)->andReturn($client = m::mock()); - $client->shouldReceive('makeVisible')->with('secret')->andReturn($client); + $clientRepository = m::mock(ClientRepository::class); + $clientRepository->shouldReceive('forUser')->once()->with(1) + ->andReturn($clients = (new Client)->newCollection()); + + $user = m::mock(Authenticatable::class); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); - $request = m::mock(Request::class); - $request->shouldReceive('user')->andReturn(new ClientControllerFakeUser); + $request = Request::create('/', 'GET'); + $request->setUserResolver(fn () => $user); $controller = new ClientController( - $clients, + $clientRepository, m::mock(Factory::class), m::mock(RedirectRule::class) ); - $this->assertEquals($client, $controller->forUser($request)); + $this->assertEquals($clients, $controller->forUser($request)); } public function test_clients_can_be_stored() { $clients = m::mock(ClientRepository::class); - $user = new ClientControllerFakeUser; + $user = m::mock(Authenticatable::class); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request = Request::create('/', 'GET', ['name' => 'client name', 'redirect' => 'http://localhost']); $request->setUserResolver(fn () => $user); @@ -55,7 +60,7 @@ public function test_clients_can_be_stored() 'name' => 'client name', 'redirect' => 'http://localhost', ], [ - 'name' => 'required|max:191', + 'name' => ['required', 'string', 'max:255'], 'redirect' => ['required', $redirectRule], 'confidential' => 'boolean', ])->andReturn($validator); @@ -71,7 +76,8 @@ public function test_clients_can_be_stored() public function test_public_clients_can_be_stored() { $clients = m::mock(ClientRepository::class); - $user = new ClientControllerFakeUser; + $user = m::mock(Authenticatable::class); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request = Request::create( '/', @@ -93,7 +99,7 @@ public function test_public_clients_can_be_stored() 'redirect' => 'http://localhost', 'confidential' => false, ], [ - 'name' => 'required|max:191', + 'name' => ['required', 'string', 'max:255'], 'redirect' => ['required', $redirectRule], 'confidential' => 'boolean', ])->andReturn($validator); @@ -115,7 +121,7 @@ public function test_clients_can_be_updated() $request = Request::create('/', 'GET', ['name' => 'client name', 'redirect' => 'http://localhost']); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; @@ -132,7 +138,7 @@ public function test_clients_can_be_updated() 'name' => 'client name', 'redirect' => 'http://localhost', ], [ - 'name' => 'required|max:191', + 'name' => ['required', 'string', 'max:255'], 'redirect' => ['required', $redirectRule], ])->andReturn($validator); $validator->shouldReceive('validate')->once(); @@ -152,7 +158,7 @@ public function test_404_response_if_client_doesnt_belong_to_user() $request = Request::create('/', 'GET', ['name' => 'client name', 'redirect' => 'http://localhost']); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; @@ -178,13 +184,13 @@ public function test_clients_can_be_deleted() $request = Request::create('/', 'GET', ['name' => 'client name', 'redirect' => 'http://localhost']); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); - $clients->shouldReceive('delete')->once()->with( + $clients->shouldReceive('revoke')->once()->with( m::type(Client::class) )->andReturn('response'); @@ -207,13 +213,13 @@ public function test_404_response_if_client_doesnt_belong_to_user_on_delete() $request = Request::create('/', 'GET', ['name' => 'client name', 'redirect' => 'http://localhost']); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; }); - $clients->shouldReceive('delete')->never(); + $clients->shouldReceive('revoke')->never(); $validator = m::mock(Factory::class); @@ -224,13 +230,3 @@ public function test_404_response_if_client_doesnt_belong_to_user_on_delete() $this->assertSame(404, $controller->destroy($request, 1)->status()); } } - -class ClientControllerFakeUser extends \Illuminate\Foundation\Auth\User -{ - public $id = 1; - - public function getAuthIdentifier() - { - return $this->id; - } -} diff --git a/tests/Unit/PersonalAccessTokenControllerTest.php b/tests/Unit/PersonalAccessTokenControllerTest.php index 49638825e..8f57c8a54 100644 --- a/tests/Unit/PersonalAccessTokenControllerTest.php +++ b/tests/Unit/PersonalAccessTokenControllerTest.php @@ -2,11 +2,14 @@ namespace Laravel\Passport\Tests\Unit; +use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Validation\Factory; use Illuminate\Http\Request; +use Illuminate\Validation\Rule; use Laravel\Passport\Client; use Laravel\Passport\Http\Controllers\PersonalAccessTokenController; use Laravel\Passport\Passport; +use Laravel\Passport\PersonalAccessTokenResult; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; @@ -24,19 +27,17 @@ public function test_tokens_can_be_retrieved_for_users() $token1 = new Token; $token2 = new Token; - - $userTokens = m::mock(); $token1->client = new Client(['grant_types' => ['personal_access']]); $token2->client = new Client(['grant_types' => []]); - $userTokens->shouldReceive('load')->with('client')->andReturn(collect([ + $userTokens = (new Token)->newCollection([ $token1, $token2, - ])); + ]); $tokenRepository = m::mock(TokenRepository::class); $tokenRepository->shouldReceive('forUser')->andReturn($userTokens); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; @@ -56,14 +57,16 @@ public function test_tokens_can_be_updated() 'user-admin' => 'second', ]); + $result = m::mock(PersonalAccessTokenResult::class); + $request = Request::create('/', 'GET', ['name' => 'token name', 'scopes' => ['user', 'user-admin']]); - $request->setUserResolver(function () { - $user = m::mock(); + $request->setUserResolver(function () use ($result) { + $user = m::mock(Authenticatable::class); $user->shouldReceive('createToken') ->once() ->with('token name', ['user', 'user-admin']) - ->andReturn('response'); + ->andReturn($result); return $user; }); @@ -73,15 +76,15 @@ public function test_tokens_can_be_updated() 'name' => 'token name', 'scopes' => ['user', 'user-admin'], ], [ - 'name' => 'required|max:191', - 'scopes' => 'array|in:'.implode(',', Passport::scopeIds()), + 'name' => ['required', 'max:255'], + 'scopes' => ['array', Rule::in(Passport::scopeIds())], ])->andReturn($validator); $validator->shouldReceive('validate')->once(); $tokenRepository = m::mock(TokenRepository::class); $controller = new PersonalAccessTokenController($tokenRepository, $validator); - $this->assertSame('response', $controller->store($request)); + $this->assertSame($result, $controller->store($request)); } public function test_tokens_can_be_deleted() @@ -96,7 +99,7 @@ public function test_tokens_can_be_deleted() $tokenRepository->shouldReceive('findForUser')->andReturn($token1); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; @@ -118,7 +121,7 @@ public function test_not_found_response_is_returned_if_user_doesnt_have_token() $tokenRepository->shouldReceive('findForUser')->with(3, 1)->andReturnNull(); $request->setUserResolver(function () { - $user = m::mock(); + $user = m::mock(Authenticatable::class); $user->shouldReceive('getAuthIdentifier')->andReturn(1); return $user; diff --git a/tests/Unit/TokenGuardTest.php b/tests/Unit/TokenGuardTest.php index b6ecd8e64..5427f07cd 100644 --- a/tests/Unit/TokenGuardTest.php +++ b/tests/Unit/TokenGuardTest.php @@ -57,7 +57,6 @@ public function test_user_can_be_pulled_via_bearer_token() ]); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $clients->shouldReceive('revoked')->with(1)->andReturn(false); $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); $user = $guard->user(); @@ -90,7 +89,6 @@ public function test_user_is_resolved_only_once() ]); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $clients->shouldReceive('revoked')->with(1)->andReturn(false); $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); $user = $guard->user(); From 57204f740c29fab2cf69cf98ff61afe488d53f7b Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Tue, 8 Oct 2024 13:19:05 +0330 Subject: [PATCH 11/13] formatting --- src/ClientRepository.php | 4 ++-- src/Http/Controllers/ClientController.php | 2 +- tests/Unit/ClientControllerTest.php | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 3b95602a5..94b9052f6 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -204,11 +204,11 @@ public function regenerateSecret(Client $client): bool * * @deprecated Will be removed in a future Laravel version. */ - public function revoke(Client $client): void + public function delete(Client $client): void { $client->tokens()->with('refreshToken')->each(function (Token $token): void { - $token->revoke(); $token->refreshToken?->revoke(); + $token->revoke(); }); $client->forceFill(['revoked' => true])->save(); diff --git a/src/Http/Controllers/ClientController.php b/src/Http/Controllers/ClientController.php index 36b59ec4c..ebfa34447 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -92,7 +92,7 @@ public function destroy(Request $request, string|int $clientId): Response return new Response('', 404); } - $this->clients->revoke($client); + $this->clients->delete($client); return new Response('', Response::HTTP_NO_CONTENT); } diff --git a/tests/Unit/ClientControllerTest.php b/tests/Unit/ClientControllerTest.php index 0053ca5c4..55a5f5eb5 100644 --- a/tests/Unit/ClientControllerTest.php +++ b/tests/Unit/ClientControllerTest.php @@ -190,9 +190,9 @@ public function test_clients_can_be_deleted() return $user; }); - $clients->shouldReceive('revoke')->once()->with( + $clients->shouldReceive('delete')->once()->with( m::type(Client::class) - )->andReturn('response'); + ); $validator = m::mock(Factory::class); @@ -219,7 +219,7 @@ public function test_404_response_if_client_doesnt_belong_to_user_on_delete() return $user; }); - $clients->shouldReceive('revoke')->never(); + $clients->shouldReceive('delete')->never(); $validator = m::mock(Factory::class); From 2c76b40a0fa84ea9e956e5556e85aa3eeefd560c Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Tue, 8 Oct 2024 13:30:11 +0330 Subject: [PATCH 12/13] upgrade guide --- UPGRADE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 358199b43..61c87edd6 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -88,7 +88,7 @@ In addition, the `passport.personal_access_client` configuration value, `Laravel PR: https://github.com/laravel/passport/pull/1778 -Passport's JSON API has been deprecated in favor of new Jetstream OAuth features. If you wish, you may continue using deprecated JSON API by setting `Passport::$registersJsonApiRoutes` to `true` within the `boot` method of your application's `App\Providers\AppServiceProvider` class: +Passport's JSON API has been deprecated, as it falls outside the core purpose of Passport as an OAuth2 server implementation. If you wish, you may copy these routes and controllers to your application or continue using deprecated JSON API by setting `Passport::$registersJsonApiRoutes` to `true` within the `boot` method of your application's `App\Providers\AppServiceProvider` class: public function boot(): void { From cf4ee182431eeacbaff82eb64fda82a95354d29f Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 8 Oct 2024 08:42:23 -0500 Subject: [PATCH 13/13] Update UPGRADE.md --- UPGRADE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 61c87edd6..366c709b6 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -88,7 +88,7 @@ In addition, the `passport.personal_access_client` configuration value, `Laravel PR: https://github.com/laravel/passport/pull/1778 -Passport's JSON API has been deprecated, as it falls outside the core purpose of Passport as an OAuth2 server implementation. If you wish, you may copy these routes and controllers to your application or continue using deprecated JSON API by setting `Passport::$registersJsonApiRoutes` to `true` within the `boot` method of your application's `App\Providers\AppServiceProvider` class: +The JSON API provided by Passport has been deprecated. If you need to continue using the deprecated JSON API, you can do so by setting `Passport::$registersJsonApiRoutes` to `true` within the `boot` method of your application’s `App\Providers\AppServiceProvider` class. Alternatively, you may also copy the relevant routes and controllers into your application as needed: public function boot(): void {