Skip to content

Commit

Permalink
refactor test cases | use phpstan
Browse files Browse the repository at this point in the history
  • Loading branch information
mgaber2024 committed Sep 10, 2023
1 parent 65a1323 commit f0c93d2
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 90 deletions.
9 changes: 9 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
parameters:

paths:
- src/

level: 9

excludePaths:

38 changes: 17 additions & 21 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">./app</directory>
<directory suffix=".php">./src</directory>
</include>
</coverage>

<php>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
</php>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<coverage/>
<php>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
</php>
<source>
<include>
<directory suffix=".php">./app</directory>
<directory suffix=".php">./src</directory>
</include>
</source>
</phpunit>
11 changes: 7 additions & 4 deletions src/SanctumRefreshTokenServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use Laravel\Sanctum\PersonalAccessToken;
use Laravel\Sanctum\Sanctum;

class SanctumRefreshTokenServiceProvider extends ServiceProvider
Expand All @@ -18,7 +19,7 @@ class SanctumRefreshTokenServiceProvider extends ServiceProvider
public function register()
{

if (! app()->configurationIsCached()) {
if (! app()->configurationIsCached()) { // @phpstan-ignore-line
$this->mergeConfigFrom(__DIR__ . '/../config/sanctum-refresh-token.php', 'sanctum-refresh-token');
}
}
Expand All @@ -42,24 +43,26 @@ public function boot()
Sanctum::authenticateAccessTokensUsing(fn ($token, $isValid) => $isValid && $this->isTokenAbilityValid($token));
}

private function isTokenAbilityValid($token)
private function isTokenAbilityValid(PersonalAccessToken $token): bool
{
/** @var array<string>|string $routeNames */
$routeNames = config('sanctum-refresh-token.refresh_route_names');
if (is_string($routeNames)) {
$routeNames = [$routeNames];
}

// @phpstan-ignore-next-line
return collect($routeNames)->contains(Route::currentRouteName()) ?
$this->isRefreshTokenValid($token) :
$this->isAuthTokenValid($token);
}

private function isAuthTokenValid($token)
private function isAuthTokenValid(PersonalAccessToken $token): bool
{
return $token->can('auth') && $token->cant('refresh');
}

private function isRefreshTokenValid($token)
private function isRefreshTokenValid(PersonalAccessToken $token): bool
{
return $token->can('refresh') && $token->cant('auth');
}
Expand Down
27 changes: 6 additions & 21 deletions tests/Feature/AuthTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,23 @@

it('auth token can be generated with expires time from config', function () {
$this->freezeTime();
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$authToken = $user->createAuthToken('auth');
$authToken = $this->user->createAuthToken('auth');
$this->assertDatabaseCount('personal_access_tokens', 1);
expect($authToken->accessToken['expires_at']->timestamp)
->toBe(now()->addMinutes(config('sanctum-refresh-token.auth_token_expiration'))->timestamp);
});

it('auth token can be generated with custom expires time', function () {
$this->freezeTime();
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$tokenExpiresMinutes = fake()->numberBetween(1, 50);
$authToken = $user->createAuthToken('auth', now()->addMinutes($tokenExpiresMinutes));
$authToken = $this->user->createAuthToken('auth', now()->addMinutes($tokenExpiresMinutes));
$this->assertDatabaseCount('personal_access_tokens', 1);
expect($authToken->accessToken['expires_at']->timestamp)
->toBe(now()->addMinutes($tokenExpiresMinutes)->timestamp);
});

it('auth token can be generated with abilities', function () {
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$authToken = $user->createAuthToken(name: 'auth', abilities: ['create-user', 'update-user']);
$authToken = $this->user->createAuthToken(name: 'auth', abilities: ['create-user', 'update-user']);
$this->assertDatabaseCount('personal_access_tokens', 1);
expect($authToken->accessToken->abilities)->toHaveCount(3);
expect($authToken->accessToken->can('auth'))
Expand All @@ -40,22 +34,15 @@
});

it('auth token can\'t access refresh route', function () {
Route::post('api/refresh-token', fn () => response(['message' => 'success']))->name('api.token.refresh')->middleware('auth:sanctum');
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$authToken = $user->createAuthToken(name: 'auth');
$authToken = $this->user->createAuthToken(name: 'auth');
$this->assertDatabaseCount('personal_access_tokens', 1);
$this->withToken($authToken->plainTextToken);
$response = $this->postJson(route('api.token.refresh'));
$response->assertStatus(401);
});

it('auth token can access any other route except refresh route', function () {
Route::post('api/refresh-token', fn () => response(['message' => 'success']))->name('api.token.refresh')->middleware('auth:sanctum');
Route::post('api/other-route', fn () => response(['message' => 'success']))->name('api.other-route')->middleware('auth:sanctum');
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$authToken = $user->createAuthToken(name: 'auth');
$authToken = $this->user->createAuthToken(name: 'auth');
$this->assertDatabaseCount('personal_access_tokens', 1);
$this->withToken($authToken->plainTextToken);
$this->postJson(route('api.token.refresh'))->assertStatus(401);
Expand All @@ -64,9 +51,7 @@

it('auth token never expire can be generated ', function () {
config(['sanctum-refresh-token.auth_token_expiration' => null]);
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$authToken = $user->createAuthToken('auth');
$authToken = $this->user->createAuthToken('auth');
$this->assertDatabaseCount('personal_access_tokens', 1);
expect($authToken->accessToken['expires_at'])->toBe(null);
});
46 changes: 9 additions & 37 deletions tests/Feature/RefreshTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,110 +6,82 @@

it('refresh token can be generated with expires time from config', function () {
$this->freezeTime();
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$refreshToken = $user->createRefreshToken('refresh');
$refreshToken = $this->user->createRefreshToken('refresh');
$this->assertDatabaseCount('personal_access_tokens', 1);
expect($refreshToken->accessToken['expires_at']->timestamp)
->toBe(now()->addMinutes(config('sanctum-refresh-token.refresh_token_expiration'))->timestamp);
});

it('refresh token can be generated with custom expires time', function () {
$this->freezeTime();
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$tokenExpiresMinutes = fake()->numberBetween(1, 50);
$refreshToken = $user->createRefreshToken('refresh', now()->addMinutes($tokenExpiresMinutes));
$refreshToken = $this->user->createRefreshToken('refresh', now()->addMinutes($tokenExpiresMinutes));
$this->assertDatabaseCount('personal_access_tokens', 1);
expect($refreshToken->accessToken['expires_at']->timestamp)
->toBe(now()->addMinutes($tokenExpiresMinutes)->timestamp);
});

it('refresh token can access refresh route', function () {
Route::post('api/refresh-token', fn () => response(['message' => 'success']))->name('api.token.refresh')->middleware('auth:sanctum');
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$refreshToken = $user->createRefreshToken('refresh');
$refreshToken = $this->user->createRefreshToken('refresh');
$this->assertDatabaseCount('personal_access_tokens', 1);
$this->withToken($refreshToken->plainTextToken);
$response = $this->postJson(route('api.token.refresh'));
$response->assertStatus(200);
});

it("auth token can't access any other route ", function () {
Route::post('api/refresh-token', fn () => response(['message' => 'success']))->name('api.token.refresh')->middleware('auth:sanctum');
Route::post('api/other-route', fn () => response(['message' => 'success']))->name('api.other-route')->middleware('auth:sanctum');
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$refreshToken = $user->createRefreshToken('refresh');
$refreshToken = $this->user->createRefreshToken('refresh');
$this->assertDatabaseCount('personal_access_tokens', 1);
$this->withToken($refreshToken->plainTextToken);
$response = $this->postJson(route('api.other-route'));
$response->assertStatus(401);
});

it('refresh token can access multiple refresh routes 1', function () {
Route::post('api/refresh-token1', fn () => response(['message' => 'success']))->name('api.token.refresh1')->middleware('auth:sanctum');
Route::post('api/refresh-token2', fn () => response(['message' => 'success']))->name('api.token.refresh2')->middleware('auth:sanctum');
config(['sanctum-refresh-token.refresh_route_names' => [
'api.token.refresh1',
'api.token.refresh2',
]]);
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$refreshToken = $user->createRefreshToken('refresh');
$refreshToken = $this->user->createRefreshToken('refresh');
$this->assertDatabaseCount('personal_access_tokens', 1);
$this->withToken($refreshToken->plainTextToken);
$this->postJson(route('api.token.refresh1'))->assertStatus(200);
});

it('refresh token can access multiple refresh routes 2', function () {
Route::post('api/refresh-token1', fn () => response(['message' => 'success']))->name('api.token.refresh1')->middleware('auth:sanctum');
Route::post('api/refresh-token2', fn () => response(['message' => 'success']))->name('api.token.refresh2')->middleware('auth:sanctum');
config(['sanctum-refresh-token.refresh_route_names' => [
'api.token.refresh1',
'api.token.refresh2',
]]);
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$refreshToken = $user->createRefreshToken('refresh');
$refreshToken = $this->user->createRefreshToken('refresh');
$this->assertDatabaseCount('personal_access_tokens', 1);
$this->withToken($refreshToken->plainTextToken);
$this->postJson(route('api.token.refresh2'))->assertStatus(200);
});

it('refresh token can access refresh route when refresh route names is array in config', function () {
Route::post('api/refresh-token1', fn () => response(['message' => 'success']))->name('api.token.refresh1')->middleware('auth:sanctum');
config(['sanctum-refresh-token.refresh_route_names' => [
'api.token.refresh1',
]]);
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$refreshToken = $user->createRefreshToken('refresh');
$refreshToken = $this->user->createRefreshToken('refresh');
$this->assertDatabaseCount('personal_access_tokens', 1);
$this->withToken($refreshToken->plainTextToken);
$this->postJson(route('api.token.refresh1'))->assertStatus(200);
});

it('refresh token can\'t access other routes when refresh route names is array in config', function () {
Route::post('api/refresh-token1', fn () => response(['message' => 'success']))->name('api.token.refresh1')->middleware('auth:sanctum');
Route::post('api/other-route', fn () => response(['message' => 'success']))->name('api.other-route')->middleware('auth:sanctum');
config(['sanctum-refresh-token.refresh_route_names' => [
'api.token.refresh1',
]]);
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$refreshToken = $user->createRefreshToken('refresh');
$refreshToken = $this->user->createRefreshToken('refresh');
$this->assertDatabaseCount('personal_access_tokens', 1);
$this->withToken($refreshToken->plainTextToken);
$this->postJson(route('api.other-route'))->assertStatus(401);
});

it('refresh token never expire can be generated ', function () {
config(['sanctum-refresh-token.refresh_token_expiration' => null]);
$user = User::factory()->create();
$this->assertDatabaseCount('users', 1);
$authToken = $user->createRefreshToken('refresh');
$authToken = $this->user->createRefreshToken('refresh');
$this->assertDatabaseCount('personal_access_tokens', 1);
expect($authToken->accessToken['expires_at'])->toBe(null);
});
14 changes: 12 additions & 2 deletions tests/Pest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,20 @@
|
*/

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\Datasets\User;

uses(
Tests\TestCase::class,
\Illuminate\Foundation\Testing\RefreshDatabase::class
)->in('Feature');
RefreshDatabase::class
)->beforeEach(function (){
Route::post('api/refresh-token', fn () => response(['message' => 'success']))->name('api.token.refresh')->middleware('auth:sanctum');
Route::post('api/other-route', fn () => response(['message' => 'success']))->name('api.other-route')->middleware('auth:sanctum');
Route::post('api/refresh-token1', fn () => response(['message' => 'success']))->name('api.token.refresh1')->middleware('auth:sanctum');
Route::post('api/refresh-token2', fn () => response(['message' => 'success']))->name('api.token.refresh2')->middleware('auth:sanctum');
$this->user = User::factory()->create();
})->in('Feature');


/*
|--------------------------------------------------------------------------
Expand Down
5 changes: 0 additions & 5 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ protected function setUp(): void
$table->boolean('active')->default(false);
$table->timestamps();
});
/**
* @var $router Router
* */
$router = $this->app->get('router');
$router->post('api/refresh-token', fn () => true)->name('api.refresh-token');
}

protected function getPackageProviders($app)
Expand Down

0 comments on commit f0c93d2

Please sign in to comment.