137 lines
4.5 KiB
PHP
137 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Admin;
|
|
|
|
use App\Models\User;
|
|
use Database\Seeders\RolesAndPermissionsSeeder;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Str;
|
|
use Laravel\Passport\Client;
|
|
use Laravel\Passport\Token;
|
|
use Tests\TestCase;
|
|
|
|
class UserSessionTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private User $admin;
|
|
private User $target;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->seed(RolesAndPermissionsSeeder::class);
|
|
|
|
$this->admin = User::factory()->approved()->create();
|
|
$this->admin->assignRole('admin');
|
|
|
|
$this->target = User::factory()->approved()->create();
|
|
}
|
|
|
|
public function test_admin_can_list_a_users_active_sessions(): void
|
|
{
|
|
$token = $this->createActiveToken($this->target, 'Demo App');
|
|
|
|
$response = $this->actingAs($this->admin)->getJson("/web-api/admin/users/{$this->target->id}/sessions");
|
|
|
|
$response->assertOk();
|
|
$response->assertJsonFragment(['id' => $token->id, 'client_name' => 'Demo App']);
|
|
}
|
|
|
|
public function test_revoked_and_expired_tokens_are_not_listed(): void
|
|
{
|
|
$this->createActiveToken($this->target, 'Revoked App', ['revoked' => true]);
|
|
$this->createActiveToken($this->target, 'Expired App', ['expires_at' => now()->subDay()]);
|
|
$active = $this->createActiveToken($this->target, 'Active App');
|
|
|
|
$response = $this->actingAs($this->admin)->getJson("/web-api/admin/users/{$this->target->id}/sessions");
|
|
|
|
$response->assertOk()->assertJsonCount(1);
|
|
$response->assertJsonFragment(['id' => $active->id]);
|
|
}
|
|
|
|
public function test_non_admin_cannot_list_sessions(): void
|
|
{
|
|
$user = User::factory()->approved()->create();
|
|
|
|
$this->actingAs($user)
|
|
->getJson("/web-api/admin/users/{$this->target->id}/sessions")
|
|
->assertForbidden();
|
|
}
|
|
|
|
public function test_admin_can_revoke_a_single_session(): void
|
|
{
|
|
$token = $this->createActiveToken($this->target);
|
|
|
|
$response = $this->actingAs($this->admin)
|
|
->deleteJson("/web-api/admin/users/{$this->target->id}/sessions/{$token->id}");
|
|
|
|
$response->assertNoContent();
|
|
$this->assertTrue($token->fresh()->revoked);
|
|
$this->assertDatabaseHas('audit_logs', [
|
|
'action' => 'user.session_revoked',
|
|
'subject_id' => (string) $this->target->id,
|
|
]);
|
|
}
|
|
|
|
public function test_revoking_nonexistent_session_returns_404(): void
|
|
{
|
|
$this->actingAs($this->admin)
|
|
->deleteJson('/web-api/admin/users/'.$this->target->id.'/sessions/'.Str::random(80))
|
|
->assertNotFound();
|
|
}
|
|
|
|
public function test_admin_can_revoke_all_sessions(): void
|
|
{
|
|
$this->createActiveToken($this->target, 'App One');
|
|
$this->createActiveToken($this->target, 'App Two');
|
|
|
|
$response = $this->actingAs($this->admin)
|
|
->deleteJson("/web-api/admin/users/{$this->target->id}/sessions");
|
|
|
|
$response->assertNoContent();
|
|
$this->assertSame(0, Token::where('user_id', $this->target->id)->where('revoked', false)->count());
|
|
$this->assertDatabaseHas('audit_logs', [
|
|
'action' => 'user.sessions_revoked_all',
|
|
'subject_id' => (string) $this->target->id,
|
|
]);
|
|
}
|
|
|
|
public function test_non_admin_cannot_revoke_sessions(): void
|
|
{
|
|
$user = User::factory()->approved()->create();
|
|
$token = $this->createActiveToken($this->target);
|
|
|
|
$this->actingAs($user)
|
|
->deleteJson("/web-api/admin/users/{$this->target->id}/sessions/{$token->id}")
|
|
->assertForbidden();
|
|
|
|
$this->assertFalse($token->fresh()->revoked);
|
|
}
|
|
|
|
private function createActiveToken(User $user, string $clientName = 'Test Client', array $overrides = []): Token
|
|
{
|
|
$client = Client::create([
|
|
'name' => $clientName,
|
|
'secret' => null,
|
|
'provider' => null,
|
|
'redirect_uris' => [],
|
|
'grant_types' => ['authorization_code', 'refresh_token'],
|
|
'revoked' => false,
|
|
]);
|
|
|
|
return Token::create(array_merge([
|
|
'id' => Str::random(80),
|
|
'user_id' => $user->id,
|
|
'client_id' => $client->id,
|
|
'name' => null,
|
|
'scopes' => ['users:read'],
|
|
'revoked' => false,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
'expires_at' => now()->addDays(15),
|
|
], $overrides));
|
|
}
|
|
}
|