Skip to content

Commit f712492

Browse files
[13.x] Fix user-token relations (#1773)
* fix user-token relations * fix tests
1 parent ef640ef commit f712492

File tree

6 files changed

+45
-27
lines changed

6 files changed

+45
-27
lines changed

src/HasApiTokens.php

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Laravel\Passport;
44

55
use Illuminate\Container\Container;
6+
use LogicException;
67

78
trait HasApiTokens
89
{
@@ -30,7 +31,18 @@ public function clients()
3031
*/
3132
public function tokens()
3233
{
33-
return $this->hasMany(Passport::tokenModel(), 'user_id')->orderBy('created_at', 'desc');
34+
return $this->hasMany(Passport::tokenModel(), 'user_id')
35+
->where(function ($query) {
36+
$query->whereHas('client', function ($query) {
37+
$query->where(function ($query) {
38+
$provider = $this->getProvider();
39+
40+
$query->when($provider === config('auth.guards.api.provider'), function ($query) {
41+
$query->orWhereNull('provider');
42+
})->orWhere('provider', $provider);
43+
});
44+
});
45+
});
3446
}
3547

3648
/**
@@ -70,22 +82,18 @@ public function createToken($name, array $scopes = [])
7082

7183
/**
7284
* Get the user provider name.
73-
*
74-
* @return string|null
7585
*/
76-
public function getProvider(): ?string
86+
public function getProvider(): string
7787
{
7888
$providers = collect(config('auth.guards'))->where('driver', 'passport')->pluck('provider')->all();
7989

8090
foreach (config('auth.providers') as $provider => $config) {
81-
if (in_array($provider, $providers)
82-
&& (($config['driver'] === 'eloquent' && is_a($this, $config['model']))
83-
|| ($config['driver'] === 'database' && $config['table'] === $this->getTable()))) {
91+
if (in_array($provider, $providers) && $config['driver'] === 'eloquent' && is_a($this, $config['model'])) {
8492
return $provider;
8593
}
8694
}
8795

88-
return null;
96+
throw new LogicException('Unable to determine authentication provider for this model from configuration.');
8997
}
9098

9199
/**

src/PersonalAccessTokenFactory.php

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ public function __construct(AuthorizationServer $server,
6565
* @param mixed $userId
6666
* @param string $name
6767
* @param string[] $scopes
68-
* @param string|null $provider
68+
* @param string $provider
6969
* @return \Laravel\Passport\PersonalAccessTokenResult
7070
*/
71-
public function make($userId, string $name, array $scopes = [], ?string $provider = null)
71+
public function make($userId, string $name, array $scopes, string $provider)
7272
{
7373
$response = $this->dispatchRequestToAuthorizationServer(
7474
$this->createRequest($userId, $scopes, $provider)
@@ -91,14 +91,12 @@ public function make($userId, string $name, array $scopes = [], ?string $provide
9191
*
9292
* @param mixed $userId
9393
* @param string[] $scopes
94-
* @param string|null $provider
94+
* @param string $provider
9595
* @return \Psr\Http\Message\ServerRequestInterface
9696
*/
97-
protected function createRequest($userId, array $scopes, ?string $provider)
97+
protected function createRequest($userId, array $scopes, string $provider)
9898
{
99-
$config = $provider
100-
? config("passport.personal_access_client.$provider", config('passport.personal_access_client'))
101-
: config('passport.personal_access_client');
99+
$config = config("passport.personal_access_client.$provider", config('passport.personal_access_client'));
102100

103101
$client = isset($config['id']) ? $this->clients->findActive($config['id']) : null;
104102

src/Token.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,13 @@ public function refreshToken()
6868
/**
6969
* Get the user that the token belongs to.
7070
*
71+
* @deprecated Will be removed in a future Laravel version.
72+
*
7173
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
7274
*/
7375
public function user()
7476
{
75-
$provider = config('auth.guards.api.provider');
77+
$provider = $this->client->provider ?: config('auth.guards.api.provider');
7678

7779
$model = config('auth.providers.'.$provider.'.model');
7880

tests/Feature/AccessTokenControllerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public function testGettingAccessTokenWithPasswordGrant()
145145
$token = $this->app->make(PersonalAccessTokenFactory::class)->findAccessToken($decodedResponse);
146146
$this->assertInstanceOf(Token::class, $token);
147147
$this->assertFalse($token->revoked);
148-
$this->assertTrue($token->user->is($user));
148+
$this->assertSame($user->getAuthIdentifier(), $token->user_id);
149149
$this->assertTrue($token->client->is($client));
150150
$this->assertNull($token->name);
151151
$this->assertLessThanOrEqual(5, CarbonImmutable::now()->addSeconds($expiresInSeconds)->diffInSeconds($token->expires_at));

tests/Feature/HasApiTokensTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function testGetProvider()
1616
config([
1717
'auth.providers.admins' => ['driver' => 'eloquent', 'model' => AdminHasApiTokensStub::class],
1818
'auth.guards.api-admins' => ['driver' => 'passport', 'provider' => 'admins'],
19-
'auth.providers.customers' => ['driver' => 'database', 'table' => 'customer_has_api_tokens_stubs'],
19+
'auth.providers.customers' => ['driver' => 'eloquent', 'model' => CustomerHasApiTokensStub::class],
2020
'auth.guards.api-customers' => ['driver' => 'passport', 'provider' => 'customers'],
2121
]);
2222

tests/Feature/PersonalAccessTokenFactoryTest.php

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Contracts\Hashing\Hasher;
66
use Illuminate\Foundation\Auth\User as Authenticatable;
7+
use Illuminate\Support\Facades\DB;
78
use Laravel\Passport\Client;
89
use Laravel\Passport\Database\Factories\ClientFactory;
910
use Laravel\Passport\HasApiTokens;
@@ -53,7 +54,7 @@ public function testIssueTokenWithDifferentProviders()
5354
config([
5455
'auth.providers.admins' => ['driver' => 'eloquent', 'model' => AdminProviderStub::class],
5556
'auth.guards.api-admins' => ['driver' => 'passport', 'provider' => 'admins'],
56-
'auth.providers.customers' => ['driver' => 'database', 'table' => 'customer_provider_stubs'],
57+
'auth.providers.customers' => ['driver' => 'eloquent', 'model' => CustomerProviderStub::class],
5758
'auth.guards.api-customers' => ['driver' => 'passport', 'provider' => 'customers'],
5859
'passport.personal_access_client' => ['id' => $client->getKey(), 'secret' => $client->plainSecret],
5960
'passport.personal_access_client.admins' => ['id' => $adminClient->getKey(), 'secret' => $adminClient->plainSecret],
@@ -80,25 +81,34 @@ public function testIssueTokenWithDifferentProviders()
8081
$this->assertInstanceOf(PersonalAccessTokenResult::class, $customerToken);
8182
$this->assertSame($customerClient->getKey(), $customerToken->token->client_id);
8283
$this->assertSame($customer->getAuthIdentifier(), $customerToken->token->user_id);
84+
85+
DB::enableQueryLog();
86+
$userTokens = $user->tokens()->pluck('id')->all();
87+
$adminTokens = $admin->tokens()->pluck('id')->all();
88+
$customerTokens = $customer->tokens()->pluck('id')->all();
89+
DB::disableQueryLog();
90+
91+
$queries = DB::getRawQueryLog();
92+
$this->assertStringContainsString('and ("provider" is null or "provider" = \'users\')', $queries[0]['raw_query']);
93+
$this->assertStringContainsString('and ("provider" = \'admins\')', $queries[1]['raw_query']);
94+
$this->assertStringContainsString('and ("provider" = \'customers\')', $queries[2]['raw_query']);
95+
96+
$this->assertEquals([$userToken->token->id], $userTokens);
97+
$this->assertEquals([$adminToken->token->id], $adminTokens);
98+
$this->assertEquals([$customerToken->token->id], $customerTokens);
8399
}
84100
}
85101

86102
class AdminProviderStub extends Authenticatable
87103
{
88104
use HasApiTokens;
89105

90-
public function getAuthIdentifier()
91-
{
92-
return 'foo';
93-
}
106+
protected $attributes = ['id' => 1];
94107
}
95108

96109
class CustomerProviderStub extends Authenticatable
97110
{
98111
use HasApiTokens;
99112

100-
public function getAuthIdentifier()
101-
{
102-
return 3;
103-
}
113+
protected $attributes = ['id' => 3];
104114
}

0 commit comments

Comments
 (0)