errors = []; // 验证必填字段 $this->validateRequired($data, [ 'service_id' => '服务ID', 'name' => '凭证名称', 'type' => '认证类型', 'credentials' => '凭证信息', ]); // 验证字段格式 $this->validateCredentialData($data); // 验证服务和认证类型匹配 if (isset($data['service_id']) && isset($data['type'])) { $this->validateServiceAuthType($data['service_id'], $data['type']); } // 验证环境下的唯一性 if (isset($data['service_id']) && isset($data['environment']) && ($data['is_active'] ?? true)) { $this->validateEnvironmentUnique($data['service_id'], $data['environment']); } return empty($this->errors); } /** * 验证更新凭证数据 * * @param array $data * @param int $credentialId * @return bool */ public function validateUpdate(array $data, int $credentialId): bool { $this->errors = []; // 验证字段格式 $this->validateCredentialData($data); $credential = ThirdPartyCredential::find($credentialId); if (!$credential) { $this->addError('credential', '凭证不存在'); return false; } // 验证服务和认证类型匹配 if (isset($data['type'])) { $this->validateServiceAuthType($credential->service_id, $data['type']); } // 验证环境下的唯一性 if (isset($data['is_active']) && $data['is_active']) { $environment = $data['environment'] ?? $credential->environment; $this->validateEnvironmentUnique($credential->service_id, $environment, $credentialId); } return empty($this->errors); } /** * 验证删除凭证 * * @param int $credentialId * @return bool */ public function validateDelete(int $credentialId): bool { $this->errors = []; $credential = ThirdPartyCredential::find($credentialId); if (!$credential) { $this->addError('credential', '凭证不存在'); return false; } // 检查凭证状态 if ($credential->is_active) { $this->addError('status', '激活状态的凭证无法删除,请先停用凭证'); } // 检查最近使用记录 if ($credential->last_used_at && $credential->last_used_at->gt(now()->subHours(1))) { $this->addError('usage', '凭证在1小时内有使用记录,无法删除'); } return empty($this->errors); } /** * 验证凭证激活 * * @param int $credentialId * @return bool */ public function validateActivation(int $credentialId): bool { $this->errors = []; $credential = ThirdPartyCredential::find($credentialId); if (!$credential) { $this->addError('credential', '凭证不存在'); return false; } // 检查凭证是否过期 if ($credential->isExpired()) { $this->addError('expired', '凭证已过期,无法激活'); } // 检查同环境下是否已有其他激活的凭证 $existingActive = ThirdPartyCredential::where('service_id', $credential->service_id) ->where('environment', $credential->environment) ->where('is_active', true) ->where('id', '!=', $credentialId) ->exists(); if ($existingActive) { $this->addError('environment', "环境 {$credential->environment} 下已有其他激活的凭证,请先停用其他凭证"); } return empty($this->errors); } /** * 验证凭证数据 * * @param array $data * @return void */ protected function validateCredentialData(array $data): void { // 验证认证类型 if (isset($data['type']) && !AUTH_TYPE::tryFrom($data['type'])) { $this->addError('type', '不支持的认证类型'); } // 验证名称长度 if (isset($data['name'])) { if (strlen($data['name']) < 2) { $this->addError('name', '凭证名称至少需要2个字符'); } if (strlen($data['name']) > 100) { $this->addError('name', '凭证名称不能超过100个字符'); } } // 验证环境 if (isset($data['environment'])) { $validEnvironments = ['production', 'staging', 'development', 'testing']; if (!in_array($data['environment'], $validEnvironments)) { $this->addError('environment', '无效的环境类型'); } } // 验证过期时间 if (isset($data['expires_at']) && !empty($data['expires_at'])) { try { $expiresAt = new \DateTime($data['expires_at']); if ($expiresAt <= now()) { $this->addError('expires_at', '过期时间必须在未来'); } } catch (\Exception $e) { $this->addError('expires_at', '过期时间格式无效'); } } // 验证凭证信息 if (isset($data['credentials']) && isset($data['type'])) { $this->validateCredentialsData($data['type'], $data['credentials']); } } /** * 验证凭证信息数据 * * @param string $authType * @param array $credentials * @return void */ protected function validateCredentialsData(string $authType, array $credentials): void { $authTypeEnum = AUTH_TYPE::tryFrom($authType); if (!$authTypeEnum) { return; } $requiredFields = $authTypeEnum->getRequiredFields(); $missingFields = []; foreach ($requiredFields as $field) { if (empty($credentials[$field])) { $missingFields[] = $field; } } if (!empty($missingFields)) { $this->addError('credentials', '凭证配置不完整,缺少字段: ' . implode(', ', $missingFields)); } // 验证特定字段格式 $this->validateSpecificCredentialFields($authTypeEnum, $credentials); } /** * 验证特定凭证字段格式 * * @param AUTH_TYPE $authType * @param array $credentials * @return void */ protected function validateSpecificCredentialFields(AUTH_TYPE $authType, array $credentials): void { switch ($authType) { case AUTH_TYPE::API_KEY: if (isset($credentials['api_key']) && strlen($credentials['api_key']) < 10) { $this->addError('credentials', 'API Key长度至少需要10个字符'); } break; case AUTH_TYPE::OAUTH2: if (isset($credentials['client_id']) && strlen($credentials['client_id']) < 5) { $this->addError('credentials', 'Client ID长度至少需要5个字符'); } if (isset($credentials['client_secret']) && strlen($credentials['client_secret']) < 10) { $this->addError('credentials', 'Client Secret长度至少需要10个字符'); } break; case AUTH_TYPE::JWT: if (isset($credentials['jwt_token'])) { $parts = explode('.', $credentials['jwt_token']); if (count($parts) !== 3) { $this->addError('credentials', 'JWT Token格式无效'); } } break; case AUTH_TYPE::BASIC: if (isset($credentials['username']) && strlen($credentials['username']) < 2) { $this->addError('credentials', '用户名长度至少需要2个字符'); } if (isset($credentials['password']) && strlen($credentials['password']) < 6) { $this->addError('credentials', '密码长度至少需要6个字符'); } break; } } /** * 验证服务和认证类型匹配 * * @param int $serviceId * @param string $authType * @return void */ protected function validateServiceAuthType(int $serviceId, string $authType): void { $service = ThirdPartyService::find($serviceId); if (!$service) { $this->addError('service_id', '服务不存在'); return; } if ($authType !== $service->auth_type) { $this->addError('type', "认证类型 {$authType} 与服务要求的 {$service->auth_type} 不匹配"); } } /** * 验证环境下的唯一性 * * @param int $serviceId * @param string $environment * @param int|null $excludeId * @return void */ protected function validateEnvironmentUnique(int $serviceId, string $environment, ?int $excludeId = null): void { $query = ThirdPartyCredential::where('service_id', $serviceId) ->where('environment', $environment) ->where('is_active', true); if ($excludeId) { $query->where('id', '!=', $excludeId); } if ($query->exists()) { $this->addError('environment', "环境 {$environment} 下已有激活的凭证,请先停用现有凭证"); } } /** * 验证必填字段 * * @param array $data * @param array $required * @return void */ protected function validateRequired(array $data, array $required): void { foreach ($required as $field => $label) { if (!isset($data[$field]) || empty($data[$field])) { $this->addError($field, "{$label}不能为空"); } } } /** * 添加错误信息 * * @param string $field * @param string $message * @return void */ protected function addError(string $field, string $message): void { if (!isset($this->errors[$field])) { $this->errors[$field] = []; } $this->errors[$field][] = $message; } /** * 获取错误信息 * * @return array */ public function getErrors(): array { return $this->errors; } /** * 获取第一个错误信息 * * @return string|null */ public function getFirstError(): ?string { if (empty($this->errors)) { return null; } $firstField = array_key_first($this->errors); return $this->errors[$firstField][0] ?? null; } /** * 检查是否有错误 * * @return bool */ public function hasErrors(): bool { return !empty($this->errors); } }