Add application API keys
linter / quality (pull_request) Successful in 1m19s
tests / ci (8.4) (pull_request) Successful in 1m32s

This commit is contained in:
2026-04-20 19:58:24 +02:00
parent a6a4615ad5
commit bf0e50464a
31 changed files with 1124 additions and 46 deletions
@@ -0,0 +1,84 @@
<?php
namespace Tests\Feature\Api;
use App\Models\Project;
use App\Models\User;
use App\Models\UserApplication;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ApiApplicationKeyTest extends TestCase
{
use RefreshDatabase;
public function test_missing_bearer_token_returns_unauthorized(): void
{
$this->getJson(route('api.projects.index'))
->assertUnauthorized()
->assertJsonPath('message', 'Unauthenticated.');
}
public function test_invalid_bearer_token_returns_unauthorized(): void
{
$this->withHeader('Authorization', 'Bearer wrong-key')
->getJson(route('api.projects.index'))
->assertUnauthorized()
->assertJsonPath('message', 'Unauthenticated.');
}
public function test_valid_bearer_token_authenticates_as_owner(): void
{
$user = User::factory()->create();
$project = Project::factory()->create([
'name' => 'Visible project',
]);
$this->syncProjectPermissions($project, $user, ['view']);
$this->withApplicationKey($user)
->getJson(route('api.projects.index'))
->assertOk()
->assertJsonPath('data.0.name', 'Visible project')
->assertJsonCount(1, 'data');
}
public function test_application_key_owner_permissions_still_apply(): void
{
$user = User::factory()->create();
$visibleProject = Project::factory()->create([
'name' => 'Visible project',
]);
Project::factory()->create([
'name' => 'Hidden project',
]);
$this->syncProjectPermissions($visibleProject, $user, ['view']);
$this->withApplicationKey($user)
->getJson(route('api.projects.index'))
->assertOk()
->assertJsonPath('data.0.name', 'Visible project')
->assertJsonCount(1, 'data');
}
public function test_application_last_used_at_updates_after_use(): void
{
$user = User::factory()->create();
$project = Project::factory()->create();
$plainTextKey = UserApplication::generatePlainTextKey();
$application = UserApplication::query()->create([
'key_hash' => UserApplication::hashKey($plainTextKey),
'name' => 'Claude Desktop',
'user_id' => $user->id,
]);
$this->syncProjectPermissions($project, $user, ['view']);
$this->withHeader('Authorization', "Bearer {$plainTextKey}")
->getJson(route('api.projects.index'))
->assertOk();
$this->assertNotNull($application->fresh()->last_used_at);
}
}