Added API endpoints for user API tokens

This commit is contained in:
Constantin Graf
2025-02-10 20:44:16 -05:00
parent d924fa74ec
commit a9d9c13846
25 changed files with 707 additions and 47 deletions

View File

@@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api\V1;
use App\Http\Requests\V1\ApiToken\ApiTokenStoreRequest;
use App\Http\Resources\V1\ApiToken\ApiTokenCollection;
use App\Http\Resources\V1\ApiToken\ApiTokenWithAccessTokenResource;
use App\Models\Passport\Token;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\JsonResponse;
class ApiTokenController extends Controller
{
/**
* List all api token of the currently authenticated user
*
* This endpoint is independent of organization.
*
* @operationId getApiTokens
*
* @throws AuthorizationException
*/
public function index(): ApiTokenCollection
{
$user = $this->user();
$tokens = $user->tokens()->get();
return new ApiTokenCollection($tokens);
}
/**
* Create a new api token for the currently authenticated user
*
* The response will contain the access token that can be used to send authenticated API requests.
* Please note that the access token is only shown in this response and cannot be retrieved later.
*
* @throws AuthorizationException
*/
public function store(ApiTokenStoreRequest $request): ApiTokenWithAccessTokenResource
{
$user = $this->user();
$token = $user->createToken($request->getName(), ['*']);
/** @var Token $tokenModel */
$tokenModel = $token->token;
return new ApiTokenWithAccessTokenResource($tokenModel, $token->accessToken);
}
/**
* Revoke an api token
*
* @throws AuthorizationException
*/
public function revoke(string $apiTokenId): JsonResponse
{
$user = $this->user();
$apiToken = $user->tokens()->where('id', $apiTokenId)->firstOrFail();
$apiToken->revoke();
return response()->json(null, 204);
}
/**
* Delete an api token
*
* @throws AuthorizationException
*/
public function destroy(string $apiTokenId): JsonResponse
{
$user = $this->user();
$apiToken = $user->tokens()->where('id', $apiTokenId)->firstOrFail();
$apiToken->delete();
return response()->json(null, 204);
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace App\Http\Requests\V1\ApiToken;
use Illuminate\Foundation\Http\FormRequest;
class ApiTokenStoreRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, array<string>>
*/
public function rules(): array
{
return [
'name' => [
'required',
'string',
'min:1',
'max:255',
],
];
}
public function getName(): string
{
return $this->input('name');
}
}

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace App\Http\Resources\V1\ApiToken;
use Illuminate\Http\Resources\Json\ResourceCollection;
class ApiTokenCollection extends ResourceCollection
{
/**
* The resource that this resource collects.
*
* @var string
*/
public $collects = ApiTokenResource::class;
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace App\Http\Resources\V1\ApiToken;
use App\Http\Resources\V1\BaseResource;
use App\Models\Passport\Token;
use Illuminate\Http\Request;
/**
* @property-read Token $resource
*/
class ApiTokenResource extends BaseResource
{
/**
* Transform the resource into an array.
*
* @return array<string, string|bool|int|null|array<string>>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->resource->id,
'name' => $this->resource->name,
'revoked' => $this->resource->revoked,
'scopes' => $this->resource->scopes,
'created_at' => $this->formatDateTime($this->resource->created_at),
'expires_at' => $this->formatDateTime($this->resource->expires_at),
];
}
}

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace App\Http\Resources\V1\ApiToken;
use App\Models\Passport\Token;
use Illuminate\Http\Request;
/**
* @property-read Token $resource
*/
class ApiTokenWithAccessTokenResource extends ApiTokenResource
{
private string $accessToken;
public function __construct(Token $resource, string $accessToken)
{
$this->accessToken = $accessToken;
parent::__construct($resource);
}
/**
* Transform the resource into an array.
*
* @return array<string, string|bool|int|null|array<string>>
*/
public function toArray(Request $request): array
{
$parent = parent::toArray($request);
return $parent + [
'access_token' => $this->accessToken,
];
}
}