Skip to content

Commit

Permalink
[12.x] Fix purge command (#1772)
Browse files Browse the repository at this point in the history
* fix purge command

* add tests

* formatting

* formatting

* formatting

* formatting

* formatting

* formatting

* formatting

* formatting

---------

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
hafezdivandari and taylorotwell authored Jul 10, 2024
1 parent 8ea1dd4 commit 795bbb4
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 25 deletions.
41 changes: 16 additions & 25 deletions src/Console/PurgeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Laravel\Passport\Console;

use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Laravel\Passport\Passport;
use Symfony\Component\Console\Attribute\AsCommand;
Expand All @@ -18,7 +19,7 @@ class PurgeCommand extends Command
protected $signature = 'passport:purge
{--revoked : Only purge revoked tokens and authentication codes}
{--expired : Only purge expired tokens and authentication codes}
{--hours= : The number of hours to retain expired tokens}';
{--hours=168 : The number of hours to retain expired tokens}';

/**
* The console command description.
Expand All @@ -32,33 +33,23 @@ class PurgeCommand extends Command
*/
public function handle()
{
$expired = $this->option('hours')
? Carbon::now()->subHours($this->option('hours'))
: Carbon::now()->subDays(7);
$revoked = $this->option('revoked') || ! $this->option('expired');

if (($this->option('revoked') && $this->option('expired')) ||
(! $this->option('revoked') && ! $this->option('expired'))) {
Passport::token()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete();
Passport::authCode()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete();
Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete();
$expired = $this->option('expired') || ! $this->option('revoked')
? Carbon::now()->subHours($this->option('hours'))
: false;

$this->option('hours')
? $this->components->info('Purged revoked items and items expired for more than '.$this->option('hours').' hours.')
: $this->components->info('Purged revoked items and items expired for more than seven days.');
} elseif ($this->option('revoked')) {
Passport::token()->where('revoked', 1)->delete();
Passport::authCode()->where('revoked', 1)->delete();
Passport::refreshToken()->where('revoked', 1)->delete();
$constraint = fn (Builder $query) => $query
->when($revoked, fn () => $query->orWhere('revoked', true))
->when($expired, fn () => $query->orWhere('expires_at', '<', $expired));

$this->components->info('Purged revoked items.');
} elseif ($this->option('expired')) {
Passport::token()->whereDate('expires_at', '<', $expired)->delete();
Passport::authCode()->whereDate('expires_at', '<', $expired)->delete();
Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete();
Passport::token()->where($constraint)->delete();
Passport::authCode()->where($constraint)->delete();
Passport::refreshToken()->where($constraint)->delete();

$this->option('hours')
? $this->components->info('Purged items expired for more than '.$this->option('hours').' hours.')
: $this->components->info('Purged items expired for more than seven days.');
}
$this->components->info(sprintf('Purged %s.', implode(' and ', array_filter([
$revoked ? 'revoked items' : null,
$expired ? "items expired for more than {$expired->longAbsoluteDiffForHumans()}" : null,
]))));
}
}
91 changes: 91 additions & 0 deletions tests/Feature/Console/PurgeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace Console;

use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Orchestra\Testbench\Concerns\WithWorkbench;
use Orchestra\Testbench\TestCase;

class PurgeCommand extends TestCase
{
use WithWorkbench;

public function test_it_can_purge_tokens()
{
$this->travelTo(Carbon::create(2000, 1, 8));

$query = DB::pretend(function () {
$this->artisan('passport:purge')
->expectsOutputToContain('Purged revoked items and items expired for more than 1 week.');
});

$this->assertSame([
'delete from "oauth_access_tokens" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
'delete from "oauth_auth_codes" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
'delete from "oauth_refresh_tokens" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
], array_column($query, 'query'));
}

public function test_it_can_purge_revoked_tokens()
{
$query = DB::pretend(function () {
$this->artisan('passport:purge', ['--revoked' => true])
->expectsOutputToContain('Purged revoked items.');
});

$this->assertSame([
'delete from "oauth_access_tokens" where ("revoked" = 1)',
'delete from "oauth_auth_codes" where ("revoked" = 1)',
'delete from "oauth_refresh_tokens" where ("revoked" = 1)',
], array_column($query, 'query'));
}

public function test_it_can_purge_expired_tokens()
{
$this->travelTo(Carbon::create(2000, 1, 8));

$query = DB::pretend(function () {
$this->artisan('passport:purge', ['--expired' => true])
->expectsOutputToContain('Purged items expired for more than 1 week.');
});

$this->assertSame([
'delete from "oauth_access_tokens" where ("expires_at" < \'2000-01-01 00:00:00\')',
'delete from "oauth_auth_codes" where ("expires_at" < \'2000-01-01 00:00:00\')',
'delete from "oauth_refresh_tokens" where ("expires_at" < \'2000-01-01 00:00:00\')',
], array_column($query, 'query'));
}

public function test_it_can_purge_revoked_and_expired_tokens()
{
$this->travelTo(Carbon::create(2000, 1, 8));

$query = DB::pretend(function () {
$this->artisan('passport:purge', ['--revoked' => true, '--expired' => true])
->expectsOutputToContain('Purged revoked items and items expired for more than 1 week.');
});

$this->assertSame([
'delete from "oauth_access_tokens" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
'delete from "oauth_auth_codes" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
'delete from "oauth_refresh_tokens" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
], array_column($query, 'query'));
}

public function test_it_can_purge_tokens_by_hours()
{
$this->travelTo(Carbon::create(2000, 1, 1, 2));

$query = DB::pretend(function () {
$this->artisan('passport:purge', ['--hours' => 2])
->expectsOutputToContain('Purged revoked items and items expired for more than 2 hours.');
});

$this->assertSame([
'delete from "oauth_access_tokens" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
'delete from "oauth_auth_codes" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
'delete from "oauth_refresh_tokens" where ("revoked" = 1 or "expires_at" < \'2000-01-01 00:00:00\')',
], array_column($query, 'query'));
}
}

0 comments on commit 795bbb4

Please sign in to comment.