Files
datahub/backend/app/Controller/Api/V1/AdminApiKeyController.php
T

233 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace App\Controller\Api\V1;
use App\Controller\AbstractController;
use App\Middleware\AuthMiddleware;
use App\Middleware\PermissionMiddleware;
use App\Model\ApiKey;
use Hyperf\HttpServer\Annotation\Controller;
use Psr\Http\Message\ResponseInterface;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\RequestMapping;
use OpenApi\Attributes as OA;
#[OA\Tag(name: 'Admin API Keys', description: '管理员 API Key 管理')]
#[Controller(prefix: "/api/v1/admin/api-keys")]
class AdminApiKeyController extends AbstractController
{
/**
* 管理员列出所有 API Keys
*
* 支持按 user_id、enabled 筛选,关联用户信息
*/
#[OA\Get(
path: '/admin/api-keys',
summary: '管理员列出所有 API Keys',
description: '分页列出所有用户的 API Keys,支持按 user_id、enabled 筛选,关联用户基本信息',
security: [['bearerAuth' => []]],
tags: ['Admin API Keys'],
parameters: [
new OA\Parameter(name: 'page', in: 'query', required: false, description: '页码,默认 1', schema: new OA\Schema(type: 'integer', default: 1)),
new OA\Parameter(name: 'per_page', in: 'query', required: false, description: '每页条数,默认 15,最大 100', schema: new OA\Schema(type: 'integer', default: 15)),
new OA\Parameter(name: 'user_id', in: 'query', required: false, description: '按用户 ID 筛选', schema: new OA\Schema(type: 'integer')),
new OA\Parameter(name: 'enabled', in: 'query', required: false, description: '按启用状态筛选(0/1', schema: new OA\Schema(type: 'integer', enum: [0, 1])),
],
responses: [
new OA\Response(
response: 200,
description: '获取成功',
content: new OA\JsonContent(properties: [
new OA\Property(property: 'code', type: 'integer', example: 0),
new OA\Property(property: 'message', type: 'string', example: '获取成功'),
new OA\Property(property: 'data', properties: [
new OA\Property(property: 'items', type: 'array', items: new OA\Items(properties: [
new OA\Property(property: 'id', type: 'integer'),
new OA\Property(property: 'user_id', type: 'integer'),
new OA\Property(property: 'name', type: 'string'),
new OA\Property(property: 'key_prefix', type: 'string'),
new OA\Property(property: 'last_used_at', type: 'string', format: 'date-time', nullable: true),
new OA\Property(property: 'expires_at', type: 'string', format: 'date-time', nullable: true),
new OA\Property(property: 'enabled', type: 'boolean'),
new OA\Property(property: 'created_at', type: 'string', format: 'date-time'),
new OA\Property(property: 'user', properties: [
new OA\Property(property: 'id', type: 'integer'),
new OA\Property(property: 'username', type: 'string'),
new OA\Property(property: 'api_key_enabled', type: 'boolean'),
], type: 'object'),
])),
new OA\Property(property: 'total', type: 'integer'),
new OA\Property(property: 'page', type: 'integer'),
new OA\Property(property: 'per_page', type: 'integer'),
], type: 'object'),
])
),
new OA\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
new OA\Response(response: 403, description: '无权限', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
]
)]
#[RequestMapping(path: "", methods: "GET")]
#[Middleware(AuthMiddleware::class)]
#[Middleware(PermissionMiddleware::class)]
public function index(): array
{
$page = (int) $this->request->input('page', 1);
$per_page = min((int) $this->request->input('per_page', 15), 100);
$query = ApiKey::query()->with('user:id,username,api_key_enabled');
// 按用户 ID 筛选
$user_id = $this->request->input('user_id');
if ($user_id !== null && $user_id !== '') {
$query->where('user_id', (int) $user_id);
}
// 按启用状态筛选
$enabled = $this->request->input('enabled');
if ($enabled !== null && $enabled !== '') {
$query->where('enabled', (bool) (int) $enabled);
}
$total = $query->count();
$items = $query->orderBy('created_at', 'desc')
->offset(($page - 1) * $per_page)
->limit($per_page)
->get();
return [
'code' => 0,
'message' => '获取成功',
'data' => [
'items' => $items,
'total' => $total,
'page' => $page,
'per_page' => $per_page,
],
];
}
/**
* 管理员启用/禁用指定 API Key
*/
#[OA\Patch(
path: '/admin/api-keys/{id}/toggle',
summary: '启用/禁用指定 API Key',
description: '管理员切换任意 API Key 的启用状态',
security: [['bearerAuth' => []]],
tags: ['Admin API Keys'],
parameters: [
new OA\Parameter(name: 'id', in: 'path', required: true, description: 'API Key ID', schema: new OA\Schema(type: 'integer')),
],
requestBody: new OA\RequestBody(
required: true,
content: new OA\JsonContent(
required: ['enabled'],
properties: [
new OA\Property(property: 'enabled', type: 'boolean', description: '是否启用'),
]
)
),
responses: [
new OA\Response(
response: 200,
description: '状态更新成功',
content: new OA\JsonContent(properties: [
new OA\Property(property: 'code', type: 'integer', example: 0),
new OA\Property(property: 'message', type: 'string', example: '状态更新成功'),
new OA\Property(property: 'data', properties: [
new OA\Property(property: 'id', type: 'integer'),
new OA\Property(property: 'name', type: 'string'),
new OA\Property(property: 'key_prefix', type: 'string'),
new OA\Property(property: 'enabled', type: 'boolean'),
new OA\Property(property: 'user_id', type: 'integer'),
], type: 'object'),
])
),
new OA\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
new OA\Response(response: 403, description: '无权限', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
new OA\Response(response: 404, description: 'API Key 不存在', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
]
)]
#[RequestMapping(path: "{id}/toggle", methods: "PATCH")]
#[Middleware(AuthMiddleware::class)]
#[Middleware(PermissionMiddleware::class)]
public function toggle(int $id): ResponseInterface|array
{
$api_key = ApiKey::query()->find($id);
if (!$api_key) {
return $this->response->json([
'code' => 404,
'message' => 'API Key 不存在',
])->withStatus(404);
}
$enabled = filter_var($this->request->input('enabled'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if ($enabled === null) {
return $this->response->json([
'code' => 400,
'message' => 'enabled 参数不能为空或格式不正确',
])->withStatus(400);
}
$api_key->enabled = $enabled;
$api_key->save();
return [
'code' => 0,
'message' => '状态更新成功',
'data' => $api_key,
];
}
/**
* 管理员删除指定 API Key
*/
#[OA\Delete(
path: '/admin/api-keys/{id}',
summary: '删除指定 API Key',
description: '管理员删除任意 API Key(硬删除,不可恢复)',
security: [['bearerAuth' => []]],
tags: ['Admin API Keys'],
parameters: [
new OA\Parameter(name: 'id', in: 'path', required: true, description: 'API Key ID', schema: new OA\Schema(type: 'integer')),
],
responses: [
new OA\Response(
response: 200,
description: '删除成功',
content: new OA\JsonContent(properties: [
new OA\Property(property: 'code', type: 'integer', example: 0),
new OA\Property(property: 'message', type: 'string', example: '删除成功'),
])
),
new OA\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
new OA\Response(response: 403, description: '无权限', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
new OA\Response(response: 404, description: 'API Key 不存在', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
]
)]
#[RequestMapping(path: "{id}", methods: "DELETE")]
#[Middleware(AuthMiddleware::class)]
#[Middleware(PermissionMiddleware::class)]
public function destroy(int $id): ResponseInterface|array
{
$api_key = ApiKey::query()->find($id);
if (!$api_key) {
return $this->response->json([
'code' => 404,
'message' => 'API Key 不存在',
])->withStatus(404);
}
$api_key->delete();
return [
'code' => 0,
'message' => '删除成功',
];
}
}