From 383e73c2cda5115affd43a21a08c59d642503361 Mon Sep 17 00:00:00 2001 From: Jethro Lin Date: Wed, 4 Dec 2024 13:34:46 +0800 Subject: [PATCH] clinet fix --- .../Api/Admin/ClientController.php | 306 ++---------------- app/Http/Controllers/Api/AuthController.php | 5 - app/Http/Middleware/ValidateAccessToken.php | 35 +- 3 files changed, 53 insertions(+), 293 deletions(-) diff --git a/app/Http/Controllers/Api/Admin/ClientController.php b/app/Http/Controllers/Api/Admin/ClientController.php index 516cfb2..98a2e44 100644 --- a/app/Http/Controllers/Api/Admin/ClientController.php +++ b/app/Http/Controllers/Api/Admin/ClientController.php @@ -6,271 +6,30 @@ use App\Constants\ErrorCode; use App\Http\Controllers\Controller; +use App\Models\Admin; use App\Models\Client; -use App\Services\LogService; use App\Services\Auth\TokenService; +use App\Services\LogService; use App\Traits\ApiResponse; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\ValidationException; use Illuminate\Support\Facades\Redis; +use Illuminate\Validation\ValidationException; class ClientController extends Controller { use ApiResponse; + private Admin $admin; + public function __construct( - private readonly LogService $logService, private readonly TokenService $tokenService, - ) {} - - /** - * 获取客户列表 - * - * @param Request $request - * @return JsonResponse - */ - public function index(Request $request): JsonResponse - { - try { - $perPage = $request->input('per_page', 15); - $perPage = min(max($perPage, 1), 100); - $search = $request->input('search'); - $status = $request->input('status'); - - $query = Client::with('llmProvider:id,name,service_name') - ->orderBy('created_at', 'desc'); - - if ($search) { - $query->where(function ($q) use ($search) { - $q->where('name', 'like', "%{$search}%") - ->orWhere('email', 'like', "%{$search}%"); - }); - } - - if ($status && in_array($status, ['active', 'inactive'])) { - $query->where('status', $status); - } - - $clients = $query->paginate($perPage); - - return $this->paginate( - $clients->items(), - [ - 'current_page' => $clients->currentPage(), - 'per_page' => $clients->perPage(), - 'total' => $clients->total(), - 'total_pages' => $clients->lastPage(), - ] - ); - - } catch (\Exception $e) { - Log::error('Error fetching clients', [ - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - 'search' => $search, - 'status' => $status, - ]); - - return $this->error( - ErrorCode::SERVER_ERROR, - ErrorCode::getMessage(ErrorCode::SERVER_ERROR) - ); - } - } - - /** - * 创建客户 - * - * @param Request $request - * @return JsonResponse - */ - public function store(Request $request): JsonResponse - { - try { - $validated = $request->validate([ - 'name' => [ - 'required', - 'string', - 'max:100', - 'regex:/^[\w\-\s]+$/u', - ], - 'email' => [ - 'required', - 'string', - 'email', - 'max:255', - 'unique:clients', - ], - 'llm_provider_id' => [ - 'required', - 'integer', - 'exists:llm_providers,id', - ], - 'rate_limit' => [ - 'required', - 'integer', - 'min:1', - 'max:1000', - ], - 'timeout' => [ - 'required', - 'integer', - 'min:1', - 'max:300', - ], - ], [ - 'name.regex' => '客户名称只能包含字母、数字、下划线、横线和空格。', - 'email.unique' => '该邮箱地址已被使用。', - 'llm_provider_id.exists' => '选择的 LLM 提供商不存在。', - 'rate_limit.min' => '速率限制不能小于 1。', - 'rate_limit.max' => '速率限制不能大于 1000。', - 'timeout.min' => '超时时间不能小于 1 秒。', - 'timeout.max' => '超时时间不能大于 300 秒。', - ]); - - $validated['status'] = 'active'; - $client = Client::create($validated); - - // 加载 LLM 提供商信息 - $client->load('llmProvider:id,name,service_name'); - - $this->logService->logOperation( - 'admin', - $request->admin->id, - "Created client: {$client->name}" - ); - - return $this->created($client); - - } catch (ValidationException $e) { - return $this->error( - ErrorCode::VALIDATION_ERROR, - ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR), - $e->errors() - ); - } catch (\Exception $e) { - Log::error('Error creating client', [ - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - 'request_data' => $request->except(['api_token']), - ]); - - return $this->error( - ErrorCode::SERVER_ERROR, - ErrorCode::getMessage(ErrorCode::SERVER_ERROR) - ); - } - } - - /** - * 更新客户 - * - * @param Request $request - * @param int $id - * @return JsonResponse - */ - public function update(Request $request, int $id): JsonResponse - { - try { - $client = Client::findOrFail($id); - - $validated = $request->validate([ - 'name' => [ - 'required', - 'string', - 'max:100', - 'regex:/^[\w\-\s]+$/u', - ], - 'email' => [ - 'required', - 'string', - 'email', - 'max:255', - "unique:clients,email,{$id}", - ], - 'llm_provider_id' => [ - 'required', - 'integer', - 'exists:llm_providers,id', - ], - 'rate_limit' => [ - 'required', - 'integer', - 'min:1', - 'max:1000', - ], - 'timeout' => [ - 'required', - 'integer', - 'min:1', - 'max:300', - ], - 'status' => [ - 'required', - 'string', - 'in:active,inactive', - ], - ], [ - 'name.regex' => '客户名称只能包含字母、数字、下划线、横线和空格。', - 'email.unique' => '该邮箱地址已被使用。', - 'llm_provider_id.exists' => '选择的 LLM 提供商不存在。', - 'rate_limit.min' => '速率限制不能小于 1。', - 'rate_limit.max' => '速率限制不能大于 1000。', - 'timeout.min' => '超时时间不能小于 1 秒。', - 'timeout.max' => '超时时间不能大于 300 秒。', - 'status.in' => '状态只能是 active 或 inactive。', - ]); - - // 如果状态改为 inactive,检查是否有活跃的认证令牌 - if ($validated['status'] === 'inactive' && $client->status === 'active') { - if ($client->authTokens()->where('status', 'active')->exists()) { - return $this->error( - ErrorCode::CLIENT_HAS_ACTIVE_TOKENS, - '该客户有活跃的认证令牌,请先停用所有令牌。' - ); - } - } - - $client->update($validated); - - // 加载 LLM 提供商信息 - $client->load('llmProvider:id,name,service_name'); - - $this->logService->logOperation( - 'admin', - $request->admin->id, - "Updated client: {$client->name}" - ); - - return $this->success($client); - - } catch (ValidationException $e) { - return $this->error( - ErrorCode::VALIDATION_ERROR, - ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR), - $e->errors() - ); - } catch (ModelNotFoundException $e) { - return $this->error( - ErrorCode::CLIENT_NOT_FOUND, - ErrorCode::getMessage(ErrorCode::CLIENT_NOT_FOUND) - ); - } catch (\Exception $e) { - Log::error('Error updating client', [ - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - 'client_id' => $id, - 'request_data' => $request->except(['api_token']), - ]); - - return $this->error( - ErrorCode::SERVER_ERROR, - ErrorCode::getMessage(ErrorCode::SERVER_ERROR) - ); - } + private readonly LogService $logService, + Request $request + ) { + $this->admin = $request->admin; } /** @@ -397,60 +156,45 @@ public function destroy(int $id): JsonResponse } /** - * 生成认证令牌 - * - * @param Request $request - * @param int $id - * @return JsonResponse + * 為客戶生成認證令牌 */ - public function generateAuthToken(Request $request, int $id): JsonResponse + public function generateAuthToken(int $id): JsonResponse { try { $client = Client::findOrFail($id); - if ($client->status !== 'active') { + if (!$this->admin->canManageClient($client->id)) { return $this->error( - ErrorCode::CLIENT_INACTIVE, - ErrorCode::getMessage(ErrorCode::CLIENT_INACTIVE) + ErrorCode::FORBIDDEN, + '您無權管理該客戶。' ); } - // 验证过期时间 - $validated = $request->validate([ - 'expires_in_days' => 'nullable|integer|min:1|max:365', - ], [ - 'expires_in_days.min' => '令牌有效期不能小于 1 天。', - 'expires_in_days.max' => '令牌有效期不能超过 365 天。', - ]); + if (!$client->isActive()) { + return $this->error( + ErrorCode::CLIENT_INACTIVE, + '客戶未啟用,無法生成令牌。' + ); + } - $token = $this->tokenService->generateAuthToken( - $client, - $validated['expires_in_days'] ?? 30 - ); + $token = $this->tokenService->generateAuthToken($client); $this->logService->logOperation( 'admin', - $request->admin->id, + $this->admin->id, "Generated auth token for client: {$client->name}" ); return $this->success([ - 'auth_token' => $token->token, - 'expires_at' => $token->expires_at, + 'auth_token' => $token['token'], + 'expires_at' => $token['expires_at'], 'client' => [ 'id' => $client->id, 'name' => $client->name, - 'email' => $client->email, 'status' => $client->status, ], ]); - } catch (ValidationException $e) { - return $this->error( - ErrorCode::VALIDATION_ERROR, - ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR), - $e->errors() - ); } catch (ModelNotFoundException $e) { return $this->error( ErrorCode::CLIENT_NOT_FOUND, @@ -460,8 +204,6 @@ public function generateAuthToken(Request $request, int $id): JsonResponse Log::error('Error generating auth token', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), - 'client_id' => $id, - 'request_data' => $request->except(['api_token']), ]); return $this->error( diff --git a/app/Http/Controllers/Api/AuthController.php b/app/Http/Controllers/Api/AuthController.php index effad93..8ec9387 100644 --- a/app/Http/Controllers/Api/AuthController.php +++ b/app/Http/Controllers/Api/AuthController.php @@ -61,11 +61,6 @@ public function getAccessToken(Request $request): JsonResponse ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR), $e->errors() ); - } catch (\InvalidArgumentException $e) { - return $this->error( - ErrorCode::TOKEN_EXPIRED, - $e->getMessage() - ); } catch (\Exception $e) { Log::error('Error generating access token', [ 'error' => $e->getMessage(), diff --git a/app/Http/Middleware/ValidateAccessToken.php b/app/Http/Middleware/ValidateAccessToken.php index bfe5a64..4173ed2 100644 --- a/app/Http/Middleware/ValidateAccessToken.php +++ b/app/Http/Middleware/ValidateAccessToken.php @@ -5,6 +5,7 @@ namespace App\Http\Middleware; use App\Constants\ErrorCode; +use App\Models\Client; use App\Services\Auth\TokenService; use Closure; use Illuminate\Http\Request; @@ -18,11 +19,12 @@ public function __construct( public function handle(Request $request, Closure $next): Response { - // 禁止访问管理员路由 + // 禁止訪問管理員路由 if (str_starts_with($request->path(), 'api/admin')) { return response()->json([ + 'success' => false, 'error' => ErrorCode::FORBIDDEN, - 'message' => '客户用户无权访问管理员资源。', + 'message' => '客戶用戶無權訪問管理員資源。', ], Response::HTTP_FORBIDDEN); } @@ -30,8 +32,9 @@ public function handle(Request $request, Closure $next): Response if (!$bearerToken) { return response()->json([ + 'success' => false, 'error' => ErrorCode::UNAUTHORIZED, - 'message' => '未授权,令牌无效或未提供。', + 'message' => '未授權,令牌無效或未提供。', ], Response::HTTP_UNAUTHORIZED); } @@ -39,13 +42,33 @@ public function handle(Request $request, Closure $next): Response if (!$tokenData) { return response()->json([ + 'success' => false, 'error' => ErrorCode::UNAUTHORIZED, - 'message' => '访问令牌无效或已过期。', + 'message' => '訪問令牌無效或已過期。', ], Response::HTTP_UNAUTHORIZED); } - // Add client information to the request for later use - $request->merge(['client_id' => $tokenData['client_id']]); + // 檢查客戶狀態 + $client = Client::find($tokenData['client_id']); + if (!$client || !$client->isActive()) { + return response()->json([ + 'success' => false, + 'error' => ErrorCode::CLIENT_INACTIVE, + 'message' => '客戶帳戶未啟用。', + ], Response::HTTP_FORBIDDEN); + } + + // 檢查 LLM 提供商狀態 + if (!$client->canSendLlmRequest()) { + return response()->json([ + 'success' => false, + 'error' => ErrorCode::PROVIDER_ERROR, + 'message' => 'LLM 提供商服務暫時不可用。', + ], Response::HTTP_SERVICE_UNAVAILABLE); + } + + // 將客戶信息添加到請求中 + $request->merge(['client' => $client]); return $next($request); }