[]]], tags: ['ApiKeys'], requestBody: new OA\RequestBody( required: true, content: new OA\JsonContent( required: ['name'], properties: [ new OA\Property(property: 'name', type: 'string', maxLength: 100, example: 'Production Key'), new OA\Property(property: 'expires_at', type: 'string', format: 'date-time', nullable: true, 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: 'plain_key', type: 'string', description: '明文 Key,仅此次可见'), new OA\Property(property: 'api_key', 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: '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'), ], type: 'object'), ], type: 'object'), ]) ), new OA\Response(response: 400, description: '参数校验失败', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), new OA\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), new OA\Response(response: 403, description: '未启用 API Key 功能', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), ] )] #[RequestMapping(path: "", methods: "POST")] #[Middleware(AuthMiddleware::class)] public function store(AuthManager $auth): \Psr\Http\Message\ResponseInterface|array { $user = $auth->guard('jwt')->user(); if (!$user instanceof User) { return $this->response->json([ 'code' => 401, 'message' => '未授权', ])->withStatus(401); } if (!$user->api_key_enabled) { return $this->response->json([ 'code' => 403, 'message' => '未启用 API Key 功能,请联系管理员开启', ])->withStatus(403); } $name = $this->request->input('name'); $expires_at = $this->request->input('expires_at'); if (!is_string($name) || trim($name) === '') { return $this->response->json([ 'code' => 400, 'message' => 'API Key 名称不能为空', ])->withStatus(400); } $name = trim($name); if (strlen($name) > 100) { return $this->response->json([ 'code' => 400, 'message' => 'API Key 名称不能超过 100 个字符', ])->withStatus(400); } // 校验过期时间格式 if ($expires_at !== null && $expires_at !== '') { try { $expires_at = \Carbon\Carbon::parse($expires_at)->toDateTimeString(); } catch (\Throwable $e) { return $this->response->json([ 'code' => 400, 'message' => '过期时间格式不正确', ])->withStatus(400); } } else { $expires_at = null; } $result = ApiKey::generate($user->id, $name, $expires_at); return [ 'code' => 0, 'message' => '生成成功', 'data' => [ 'plain_key' => $result['plain_key'], 'api_key' => $result['api_key'], ], ]; } /** * API Key 列表 * * 列出当前用户的所有 API Keys(不含哈希) */ #[OA\Get( path: '/me/api-keys', summary: 'API Key 列表', description: '列出当前用户的所有 API Keys', security: [['bearerAuth' => []]], tags: ['ApiKeys'], 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', type: 'array', items: new OA\Items(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: '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\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), ] )] #[RequestMapping(path: "", methods: "GET")] #[Middleware(AuthMiddleware::class)] public function index(AuthManager $auth): \Psr\Http\Message\ResponseInterface|array { $user = $auth->guard('jwt')->user(); if (!$user instanceof User) { return $this->response->json([ 'code' => 401, 'message' => '未授权', ])->withStatus(401); } $keys = ApiKey::query() ->where('user_id', $user->id) ->orderBy('created_at', 'desc') ->get(); return [ 'code' => 0, 'message' => '获取成功', 'data' => $keys, ]; } /** * 删除 API Key */ #[OA\Delete( path: '/me/api-keys/{id}', summary: '删除 API Key', security: [['bearerAuth' => []]], tags: ['ApiKeys'], 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: 404, description: 'API Key 不存在', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')), ] )] #[RequestMapping(path: "{id}", methods: "DELETE")] #[Middleware(AuthMiddleware::class)] public function destroy(int $id, AuthManager $auth): \Psr\Http\Message\ResponseInterface|array { $user = $auth->guard('jwt')->user(); if (!$user instanceof User) { return $this->response->json([ 'code' => 401, 'message' => '未授权', ])->withStatus(401); } $api_key = ApiKey::query() ->where('id', $id) ->where('user_id', $user->id) ->first(); if (!$api_key) { return $this->response->json([ 'code' => 404, 'message' => 'API Key 不存在', ])->withStatus(404); } $api_key->delete(); return [ 'code' => 0, 'message' => '删除成功', ]; } }