clinet fix
This commit is contained in:
parent
4b1ed6ade3
commit
383e73c2cd
3 changed files with 53 additions and 293 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue