\Utils\ErrorCodes::ENRICHMENT_API_KEY_DOES_NOT_EXIST]; } set_error_handler([\Utils\ErrorHandler::class, 'exceptionErrorHandler']); $search = $search !== null ? ['value' => $search] : null; $result = $this->enrichEntityProcess($type, $search, $entityId, $apiKey, $enrichmentKey); restore_error_handler(); return $result; } private function enrichEntityProcess(string $type, ?array $search, ?int $entityId, int $apiKey, ?string $enrichmentKey): array { $processErrorMessage = ['ERROR_CODE' => \Utils\ErrorCodes::ENRICHMENT_API_UNKNOWN_ERROR]; if ($type === 'device') { if ($entityId !== null) { $model = new \Models\Device(); $device = $model->getFullDeviceInfoById($entityId, $apiKey); if ($device !== []) { $entityId = $device['ua_id']; $type = 'ua'; } else { return $processErrorMessage; } } else { return $processErrorMessage; } } $model = new \Models\ApiKeys(); $attributes = $model->enrichableAttributes($apiKey); if (!array_key_exists($type, $attributes)) { return ['ERROR_CODE' => \Utils\ErrorCodes::ENRICHMENT_API_ATTRIBUTE_IS_UNAVAILABLE]; } $modelDb = null; $modelResult = null; $extraModel = null; switch ($type) { case 'ip': $modelDb = new \Models\Ip(); $modelResult = new \Models\Enrichment\Ip(); $extraModel = new \Models\Enrichment\LocalhostIp(); break; case 'email': $modelDb = new \Models\Email(); $modelResult = new \Models\Enrichment\Email(); break; case 'domain': $modelDb = new \Models\Domain(); $modelResult = new \Models\Enrichment\DomainFound(); $extraModel = new \Models\Enrichment\DomainNotFound(); break; case 'phone': $modelDb = new \Models\Phone(); $modelResult = new \Models\Enrichment\PhoneValid(); $extraModel = new \Models\Enrichment\PhoneInvalid(); break; case 'ua': $modelDb = new \Models\Device(); $modelResult = new \Models\Enrichment\Device(); break; } if ($modelDb === null) { return $processErrorMessage; } $value = $entityId !== null ? $modelDb->extractById($entityId, $apiKey) : $search; if ($value === null || $value === []) { return $processErrorMessage; } $apiError = null; try { [$statusCode, $response,] = $this->enrichEntityByValue($type, $value, $enrichmentKey); $error = \Utils\ApiResponseFormats::getErrorResponseFormat(); $apiError = \Utils\ApiResponseFormats::matchResponse($response[$type] ?? [], $error) ? $response[$type]['error'] : null; } catch (\ErrorException $e) { return $processErrorMessage; } if ($statusCode === 403) { return ['ERROR_CODE' => \Utils\ErrorCodes::ENRICHMENT_API_KEY_OVERUSE]; } if ($type === 'ip') { // do not raise on bogon ip if ($apiError === \Utils\Constants::get('ENRICHMENT_IP_IS_NOT_FOUND')) { return ['ERROR_CODE' => \Utils\ErrorCodes::ENRICHMENT_API_IP_NOT_FOUND]; } elseif ($apiError !== null && $apiError !== \Utils\Constants::get('ENRICHMENT_IP_IS_BOGON') || $statusCode !== 200 || $response[$type] === null) { return $processErrorMessage; } } elseif ($apiError !== null || $statusCode !== 200 || $response[$type] === null) { return $processErrorMessage; } try { $modelResult->init($response[$type]); } catch (\ErrorException $e) { if ($extraModel === null) { return $processErrorMessage; } try { $extraModel->init($response[$type]); $modelResult = $extraModel; } catch (\ErrorException $e) { return $processErrorMessage; } } // change value in db only if $entityId was passed if ($entityId !== null) { try { $modelResult->updateEntityInDb($entityId, $apiKey); } catch (\ErrorException $e) { return $processErrorMessage; } } return [ $type => $response[$type], 'SUCCESS_MESSAGE' => $this->f3->get('AdminEnrichment_success_message'), ]; } private function validateResponse(string $requestType, int $statusCode, ?array $result, string $errorMessage): bool|string|int { if (!is_array($result)) { return \Utils\ErrorCodes::ENRICHMENT_API_UNKNOWN_ERROR; } if ($statusCode === 200 && is_array($result) && is_array($result[$requestType])) { return false; } $details = $result['detail'] ?? null; if ($details) { if (is_array($details)) { $messages = array_map(function ($detail) { if (isset($detail['msg']) && $detail['msg'] !== null && $detail['msg'] !== '') { return $detail['msg']; } }, $details); $messages = implode('; ', $messages); } else { $messages = $details; } } if (strlen($errorMessage) > 0) { \Utils\Logger::log('Enrichment API web error', $errorMessage); } if (!isset($messages) || strlen($messages) < 1) { return \Utils\ErrorCodes::ENRICHMENT_API_UNKNOWN_ERROR; } return $messages; } private function enrichEntityByValue(string $type, array $value, string $enrichmentKey): array { $apiUrl = \Utils\Variables::getEnrichtmentApi(); $postFields = [ $type => $value['value'], ]; $options = [ 'method' => 'POST', 'header' => [ 'Content-Type: application/json', 'Authorization: Bearer ' . $enrichmentKey, 'User-Agent: ' . $this->f3->get('USER_AGENT'), ], 'content' => \json_encode($postFields), ]; /** @var array{request: array, body: string, headers: array, engine: string, cached: bool, error: string} $result */ $result = \Web::instance()->request( url: sprintf('%s/query', $apiUrl), options: $options, ); $matches = []; preg_match('/^HTTP\/(\d+)(?:\.\d)? (\d{3})/', $result['headers'][0], $matches); $jsonResponse = json_decode($result['body'], true); $statusCode = (int) ($matches[2] ?? 0); $errorMessages = $this->validateResponse($type, $statusCode, $jsonResponse, $result['error']); return [$statusCode, $jsonResponse, $errorMessages]; } public function getNotCheckedEntitiesCount(int $apiKey): array { $model = new \Models\ApiKeys(); $models = $model->enrichableAttributes($apiKey); $result = []; foreach ($models as $type => $model) { $result[$type] = (new $model())->countNotChecked($apiKey); } return $result; } public function getNotCheckedExists(int $apiKey): bool { $model = new \Models\ApiKeys(); $models = $model->enrichableAttributes($apiKey); foreach ($models as $model) { if ((new $model())->notCheckedExists($apiKey)) { return true; } } return false; } public function getNotCheckedEntitiesByUserId(int $userId, int $apiKey): array { $model = new \Models\ApiKeys(); $models = $model->enrichableAttributes($apiKey); $result = []; foreach ($models as $type => $model) { $result[$type] = (new $model())->notCheckedForUserId($userId, $apiKey); } return $result; } }