Add filament resource for tokens; Ignore non-personal tokens in API token endpoints

This commit is contained in:
Constantin Graf
2025-02-11 15:58:25 -05:00
committed by Constantin Graf
parent 69a8c8bb2b
commit ae76135373
10 changed files with 461 additions and 9 deletions

View File

@@ -19,10 +19,14 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
{
// Arrange
$data = $this->createUserWithPermission([]);
$client = $this->createPersonalAccessClient();
$token = Token::factory()->forUser($data->user)->forClient($client)->create();
$personalAccessClient = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $personalAccessClient->id);
Config::set('passport.personal_access_client.secret', $personalAccessClient->secret);
$client = $this->createClient();
$token = Token::factory()->forUser($data->user)->forClient($personalAccessClient)->create();
$otherTokenType = Token::factory()->forUser($data->user)->forClient($client)->create();
$otherData = $this->createUserWithPermission([]);
$otherToken = Token::factory()->forUser($otherData->user)->forClient($client)->create();
$otherToken = Token::factory()->forUser($otherData->user)->forClient($personalAccessClient)->create();
Passport::actingAs($data->user);
// Act
@@ -48,9 +52,9 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
{
// Arrange
$data = $this->createUserWithPermission([]);
$client = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $client->id);
Config::set('passport.personal_access_client.secret', $client->secret);
$personalAccessClient = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $personalAccessClient->id);
Config::set('passport.personal_access_client.secret', $personalAccessClient->secret);
Passport::actingAs($data->user);
// Act
@@ -73,11 +77,33 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
]);
}
public function test_store_fails_if_personal_access_client_is_not_configured(): void
{
// Arrange
$data = $this->createUserWithPermission([]);
Passport::actingAs($data->user);
// Act
$response = $this->postJson(route('api.v1.api-tokens.store'), [
'name' => 'Test Token',
]);
// Assert
$this->assertResponseCode($response, 400);
$response->assertExactJson([
'error' => true,
'key' => 'personal_access_client_is_not_configured',
'message' => 'Personal access client is not configured',
]);
}
public function test_revoke_endpoint_revokes_api_token(): void
{
// Arrange
$data = $this->createUserWithPermission([]);
$client = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $client->id);
Config::set('passport.personal_access_client.secret', $client->secret);
$token = Token::factory()->forUser($data->user)->forClient($client)->create();
Passport::actingAs($data->user);
@@ -92,6 +118,28 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
]);
}
public function test_revoke_fails_if_token_is_not_personal_access_token(): void
{
// Arrange
$data = $this->createUserWithPermission([]);
$personalAccessClient = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $personalAccessClient->id);
Config::set('passport.personal_access_client.secret', $personalAccessClient->secret);
$client = $this->createClient();
$token = Token::factory()->forUser($data->user)->forClient($client)->create();
Passport::actingAs($data->user);
// Act
$response = $this->postJson(route('api.v1.api-tokens.revoke', $token->id));
// Assert
$this->assertResponseCode($response, 403);
$this->assertDatabaseHas(Token::class, [
'id' => $token->id,
'revoked' => false,
]);
}
public function test_revoke_fails_if_token_with_id_does_not_exist(): void
{
// Arrange
@@ -105,12 +153,34 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
$this->assertResponseCode($response, 404);
}
public function test_revoke_fails_if_personal_access_client_is_not_configured(): void
{
// Arrange
$data = $this->createUserWithPermission([]);
$client = $this->createPersonalAccessClient();
$token = Token::factory()->forUser($data->user)->forClient($client)->create();
Passport::actingAs($data->user);
// Act
$response = $this->postJson(route('api.v1.api-tokens.revoke', $token->id));
// Assert
$this->assertResponseCode($response, 400);
$response->assertExactJson([
'error' => true,
'key' => 'personal_access_client_is_not_configured',
'message' => 'Personal access client is not configured',
]);
}
public function test_revoke_fails_if_the_token_does_not_belong_to_the_user(): void
{
// Arrange
$data = $this->createUserWithPermission([]);
$otherData = $this->createUserWithPermission([]);
$client = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $client->id);
Config::set('passport.personal_access_client.secret', $client->secret);
$token = Token::factory()->forUser($otherData->user)->forClient($client)->create();
Passport::actingAs($data->user);
@@ -130,6 +200,8 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
// Arrange
$data = $this->createUserWithPermission([]);
$client = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $client->id);
Config::set('passport.personal_access_client.secret', $client->secret);
$token = Token::factory()->forUser($data->user)->forClient($client)->create();
Passport::actingAs($data->user);
@@ -141,6 +213,47 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
$this->assertDatabaseMissing(Token::class, ['id' => $token->id]);
}
public function test_destroy_fails_if_personal_access_client_is_not_configured(): void
{
// Arrange
$data = $this->createUserWithPermission([]);
$client = $this->createPersonalAccessClient();
$token = Token::factory()->forUser($data->user)->forClient($client)->create();
Passport::actingAs($data->user);
// Act
$response = $this->deleteJson(route('api.v1.api-tokens.destroy', $token->id));
// Assert
$this->assertResponseCode($response, 400);
$response->assertExactJson([
'error' => true,
'key' => 'personal_access_client_is_not_configured',
'message' => 'Personal access client is not configured',
]);
}
public function test_destroy_fails_if_token_is_not_personal_access_token(): void
{
// Arrange
$data = $this->createUserWithPermission([]);
$personalAccessClient = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $personalAccessClient->id);
Config::set('passport.personal_access_client.secret', $personalAccessClient->secret);
$client = $this->createClient();
$token = Token::factory()->forUser($data->user)->forClient($client)->create();
Passport::actingAs($data->user);
// Act
$response = $this->deleteJson(route('api.v1.api-tokens.destroy', $token->id));
// Assert
$this->assertResponseCode($response, 403);
$this->assertDatabaseHas(Token::class, [
'id' => $token->id,
]);
}
public function test_destroy_fails_if_token_with_id_does_not_exist(): void
{
// Arrange
@@ -160,6 +273,8 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
$data = $this->createUserWithPermission([]);
$otherData = $this->createUserWithPermission([]);
$client = $this->createPersonalAccessClient();
Config::set('passport.personal_access_client.id', $client->id);
Config::set('passport.personal_access_client.secret', $client->secret);
$token = Token::factory()->forUser($otherData->user)->forClient($client)->create();
Passport::actingAs($data->user);
@@ -183,4 +298,15 @@ class ApiTokenEndpointTest extends ApiEndpointTestAbstract
return $client;
}
private function createClient(): Client
{
$clientRepository = new ClientRepository;
/** @var Client $client */
$client = $clientRepository->create(
null, 'Desktop App', 'http://localhost', null
);
return $client;
}
}