diff --git a/UPGRADE.md b/UPGRADE.md index 8a7186db7..366c709b6 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -84,6 +84,17 @@ Passport's `oauth_personal_access_clients` table has been redundant and unnecess In addition, the `passport.personal_access_client` configuration value, `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 + +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 + { + Passport::$registersJsonApiRoutes = true; + } + ## Upgrading To 12.0 From 11.x ### Migration Changes 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/ClientRepository.php b/src/ClientRepository.php index 0402fc7b8..94b9052f6 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; @@ -30,44 +31,26 @@ public function findActive(string|int $id): ?Client /** * Get a client instance for the given ID and user ID. * - * @param int|string $clientId - * @param mixed $userId - * @return \Laravel\Passport\Client|null + * @deprecated Use $user->clients()->find() + * + * @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); } /** * Get the client instances for the given user ID. * - * @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 Use $user->clients() * - * @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(); } /* @@ -188,6 +171,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 @@ -215,27 +200,16 @@ public function regenerateSecret(Client $client): bool } /** - * Determine if the given client is revoked. - * - * @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. * - * @param \Laravel\Passport\Client $client - * @return void + * @deprecated Will be removed in a future Laravel version. */ - public function delete(Client $client) + public function delete(Client $client): void { - $client->tokens()->update(['revoked' => true]); + $client->tokens()->with('refreshToken')->each(function (Token $token): void { + $token->refreshToken?->revoke(); + $token->revoke(); + }); $client->forceFill(['revoked' => true])->save(); } diff --git a/src/Http/Controllers/AuthorizedAccessTokenController.php b/src/Http/Controllers/AuthorizedAccessTokenController.php index f31aaf61d..ee82faa1b 100644 --- a/src/Http/Controllers/AuthorizedAccessTokenController.php +++ b/src/Http/Controllers/AuthorizedAccessTokenController.php @@ -2,66 +2,44 @@ 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; +/** + * @deprecated Will be removed in a future Laravel version. + */ 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)) { @@ -69,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 ca9117f2b..ebfa34447 100644 --- a/src/Http/Controllers/ClientController.php +++ b/src/Http/Controllers/ClientController.php @@ -3,75 +3,45 @@ 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; +/** + * @deprecated Will be removed in a future Laravel version. + */ 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(); @@ -90,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(); @@ -117,14 +83,10 @@ 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); diff --git a/src/Http/Controllers/PersonalAccessTokenController.php b/src/Http/Controllers/PersonalAccessTokenController.php index 565fd4fa9..55159159c 100644 --- a/src/Http/Controllers/PersonalAccessTokenController.php +++ b/src/Http/Controllers/PersonalAccessTokenController.php @@ -5,64 +5,48 @@ 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; +/** + * @deprecated Will be removed in a future Laravel version. + */ 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( @@ -72,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 0d726e708..946f7aa52 100644 --- a/src/Http/Controllers/ScopeController.php +++ b/src/Http/Controllers/ScopeController.php @@ -2,16 +2,20 @@ namespace Laravel\Passport\Http\Controllers; +use Illuminate\Support\Collection; use Laravel\Passport\Passport; +/** + * @deprecated Will be removed in a future Laravel version. + */ 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 e14d11c3d..fdb3676ee 100644 --- a/src/Http/Rules/RedirectRule.php +++ b/src/Http/Rules/RedirectRule.php @@ -5,30 +5,23 @@ use Illuminate\Contracts\Validation\Factory; use Illuminate\Contracts\Validation\Rule; +/** + * @deprecated Will be removed in a future Laravel version. + */ 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]); @@ -44,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/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 { /** diff --git a/src/Passport.php b/src/Passport.php index 503e650f2..629846416 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -148,6 +148,13 @@ class Passport */ public static bool $registersRoutes = true; + /** + * Indicates if Passport JSON API routes will be registered. + * + * @var bool + */ + public static $registersJsonApiRoutes = false; + /** * Enable the implicit grant type. */ diff --git a/src/RefreshTokenRepository.php b/src/RefreshTokenRepository.php deleted file mode 100644 index 61dfb9900..000000000 --- a/src/RefreshTokenRepository.php +++ /dev/null @@ -1,72 +0,0 @@ -create($attributes); - } - - /** - * Gets a refresh token by the given ID. - * - * @param string $id - * @return \Laravel\Passport\RefreshToken - */ - public function find($id) - { - return Passport::refreshToken()->where('id', $id)->first(); - } - - /** - * Stores the given token instance. - * - * @param \Laravel\Passport\RefreshToken $token - * @return void - */ - public function save(RefreshToken $token) - { - $token->save(); - } - - /** - * Revokes the refresh token. - * - * @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. - * - * @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. - * - * @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 d64935927..50ff19738 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -2,120 +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. - * - * @param array $attributes - * @return \Laravel\Passport\Token - */ - public function create($attributes) - { - return Passport::token()->create($attributes); - } - - /** - * Get a token by the given ID. - * - * @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. * - * @param string $id - * @param int $userId - * @return \Laravel\Passport\Token|null - */ - public function findForUser($id, $userId) - { - return Passport::token()->where('id', $id)->where('user_id', $userId)->first(); - } - - /** - * Get the token instances for the given user ID. + * @deprecated Use $user->tokens()->find() * - * @param mixed $userId - * @return \Illuminate\Database\Eloquent\Collection + * @param \Laravel\Passport\HasApiTokens $user */ - public function forUser($userId) + public function findForUser(string $id, Authenticatable $user): ?Token { - return Passport::token()->where('user_id', $userId)->get(); + return $user->tokens() + ->with('client') + ->where('revoked', false) + ->where('expires_at', '>', Date::now()) + ->find($id); } /** - * Get a valid token instance for the given user and client. - * - * @deprecated use findValidToken - * - * @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. - * - * @param \Laravel\Passport\Token $token - * @return void - */ - public function save(Token $token) - { - $token->save(); - } - - /** - * Revoke an access token. - * - * @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. + * Get the token instances for the given user ID. * - * @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 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..55a5f5eb5 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,7 +184,7 @@ 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; @@ -186,7 +192,7 @@ public function test_clients_can_be_deleted() $clients->shouldReceive('delete')->once()->with( m::type(Client::class) - )->andReturn('response'); + ); $validator = m::mock(Factory::class); @@ -207,7 +213,7 @@ 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; @@ -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();