diff --git a/src/Guard.php b/src/Guard.php index 0054805..b14d27f 100644 --- a/src/Guard.php +++ b/src/Guard.php @@ -30,18 +30,27 @@ class Guard */ protected $provider; + /** + * Whether to track the last used timestamp. + * + * @var bool + */ + protected $trackLastUsedAt; + /** * Create a new guard instance. * * @param \Illuminate\Contracts\Auth\Factory $auth * @param int $expiration * @param string $provider + * @param bool $trackLastUsedAt */ - public function __construct(AuthFactory $auth, $expiration = null, $provider = null) + public function __construct(AuthFactory $auth, $expiration = null, $provider = null, $trackLastUsedAt = true) { $this->auth = $auth; $this->expiration = $expiration; $this->provider = $provider; + $this->trackLastUsedAt = $trackLastUsedAt; } /** @@ -76,7 +85,9 @@ public function __invoke(Request $request) event(new TokenAuthenticated($accessToken)); - $this->updateLastUsedAt($accessToken); + if ($this->trackLastUsedAt) { + $this->updateLastUsedAt($accessToken); + } return $tokenable; } diff --git a/src/SanctumServiceProvider.php b/src/SanctumServiceProvider.php index 9aed959..a50c855 100644 --- a/src/SanctumServiceProvider.php +++ b/src/SanctumServiceProvider.php @@ -103,7 +103,12 @@ protected function configureGuard() protected function createGuard($auth, $config) { return new RequestGuard( - new Guard($auth, config('sanctum.expiration'), $config['provider']), + new Guard( + $auth, + config('sanctum.expiration'), + $config['provider'], + config('sanctum.last_used_at', true) + ), request(), $auth->createUserProvider($config['provider'] ?? null) ); diff --git a/tests/Feature/GuardTest.php b/tests/Feature/GuardTest.php index 29e9199..666aa1a 100644 --- a/tests/Feature/GuardTest.php +++ b/tests/Feature/GuardTest.php @@ -418,4 +418,65 @@ public static function invalidTokenDataProvider(): array ['Bearer 1ABC|'], ]; } + + public function test_last_used_at_is_not_tracked_when_disabled() + { + $factory = Mockery::mock(AuthFactory::class); + + $guard = new Guard($factory, null, 'users', false); + + $webGuard = Mockery::mock(stdClass::class); + + $factory->shouldReceive('guard') + ->with('web') + ->andReturn($webGuard); + + $webGuard->shouldReceive('user')->once()->andReturn(null); + + $request = Request::create('/', 'GET'); + $request->headers->set('Authorization', 'Bearer test'); + + $token = PersonalAccessTokenFactory::new()->for( + $user = UserFactory::new()->create(), 'tokenable' + )->create([ + 'name' => 'Test', + 'last_used_at' => null, + ]); + + $returnedUser = $guard->__invoke($request); + + $this->assertEquals($user->id, $returnedUser->id); + $this->assertEquals($token->id, $returnedUser->currentAccessToken()->id); + $this->assertNull($returnedUser->currentAccessToken()->last_used_at); + } + + public function test_last_used_at_is_tracked_when_enabled() + { + $factory = Mockery::mock(AuthFactory::class); + + $guard = new Guard($factory, null, 'users', true); + + $webGuard = Mockery::mock(stdClass::class); + + $factory->shouldReceive('guard') + ->with('web') + ->andReturn($webGuard); + + $webGuard->shouldReceive('user')->once()->andReturn(null); + + $request = Request::create('/', 'GET'); + $request->headers->set('Authorization', 'Bearer test'); + + $token = PersonalAccessTokenFactory::new()->for( + $user = UserFactory::new()->create(), 'tokenable' + )->create([ + 'name' => 'Test', + ]); + + $returnedUser = $guard->__invoke($request); + + $this->assertEquals($user->id, $returnedUser->id); + $this->assertEquals($token->id, $returnedUser->currentAccessToken()->id); + $this->assertInstanceOf(DateTimeInterface::class, $returnedUser->currentAccessToken()->last_used_at); + } }