feat(cloudron): add tirreno package artifacts
- Add CloudronStack/output/CloudronPackages-Artifacts/tirreno/ directory and its contents - Includes package manifest, Dockerfile, source code, documentation, and build artifacts - Add tirreno-1761840148.tar.gz as a build artifact - Add tirreno-cloudron-package-1761841304.tar.gz as the Cloudron package - Include all necessary files for the tirreno Cloudron package This adds the complete tirreno Cloudron package artifacts to the repository.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Sensor\Model\Http\RegularResponse;
|
||||
use Sensor\Model\Http\Request;
|
||||
use Sensor\Service\DI;
|
||||
|
||||
ini_set('display_errors', '0');
|
||||
|
||||
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
} else {
|
||||
require __DIR__ . '/../libs/mustangostang/spyc/Spyc.php';
|
||||
require __DIR__ . '/../libs/matomo/device-detector/autoload.php';
|
||||
}
|
||||
|
||||
// Register autoloader
|
||||
spl_autoload_register(fn (string $c) => @include_once __DIR__ . '/src/' . str_replace(['Sensor\\', '\\'], ['', '/'], $c) . '.php');
|
||||
|
||||
$requestStartTime = new \DateTime('now');
|
||||
|
||||
$di = new DI();
|
||||
$profiler = $di->getProfiler();
|
||||
$logger = $di->getLogger();
|
||||
$logbookManager = $di->getLogbookManager();
|
||||
$profiler->start('total');
|
||||
|
||||
$request = null;
|
||||
try {
|
||||
$apiKeyString = $_SERVER['HTTP_API_KEY'] ?? null;
|
||||
$apiKeyDto = $logbookManager->getApiKeyDto($apiKeyString); // GetApiKeyDto or null
|
||||
$logbookManager->setApiKeyDto($apiKeyDto);
|
||||
|
||||
$request = new Request($_POST, $apiKeyString, $_SERVER['HTTP_X_REQUEST_ID'] ?? null);
|
||||
|
||||
$controller = $di->getController();
|
||||
$response = $controller->index($request, $apiKeyDto);
|
||||
} catch (Throwable $e) {
|
||||
if ($e instanceof PDOException && str_contains($e->getMessage(), 'connect')) {
|
||||
$logger->logError($e, 'Unable to connect to database: ' . $e->getMessage());
|
||||
} else {
|
||||
$logger->logError($e);
|
||||
}
|
||||
// get apikey
|
||||
$logbookManager->logException(
|
||||
$requestStartTime,
|
||||
$e->getMessage(),
|
||||
);
|
||||
$logbookManager->logIncorrectRequest(
|
||||
$request?->body ?? [],
|
||||
$e::class . ': ' . $e->getMessage(),
|
||||
$request?->traceId ?? null,
|
||||
);
|
||||
|
||||
// Log profiler data and queries before exit
|
||||
$profiler->finish('total');
|
||||
$logger->logProfilerData($profiler->getData());
|
||||
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$profiler->finish('total');
|
||||
$logger->logProfilerData($profiler->getData());
|
||||
// getapikey
|
||||
$logbookManager->logRequest($requestStartTime, $response);
|
||||
|
||||
// response without errors
|
||||
if ($response instanceof RegularResponse) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Response is set only in case of error, so let's log it
|
||||
$logger->logUserError($response->httpCode, (string) $response);
|
||||
// getapikey
|
||||
$logbookManager->logIncorrectRequest(
|
||||
$request?->body ?? [],
|
||||
(string) $response,
|
||||
$request?->traceId ?? null,
|
||||
);
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Controller;
|
||||
|
||||
use Sensor\Dto\GetApiKeyDto;
|
||||
use Sensor\Dto\InsertAccountDto;
|
||||
use Sensor\Dto\InsertEventDto;
|
||||
use Sensor\Entity\AccountEntity;
|
||||
use Sensor\Exception\ValidationException;
|
||||
use Sensor\Factory\EventFactory;
|
||||
use Sensor\Factory\RequestFactory;
|
||||
use Sensor\Model\CreateEventDto;
|
||||
use Sensor\Model\Http\RegularResponse;
|
||||
use Sensor\Model\Http\ErrorResponse;
|
||||
use Sensor\Model\Http\Request;
|
||||
use Sensor\Model\Http\ValidationFailedResponse;
|
||||
use Sensor\Repository\AccountRepository;
|
||||
use Sensor\Repository\ApiKeyRepository;
|
||||
use Sensor\Repository\EventRepository;
|
||||
use Sensor\Service\ConnectionService;
|
||||
use Sensor\Service\Enrichment\DataEnrichmentService;
|
||||
use Sensor\Service\DeviceDetectorService;
|
||||
use Sensor\Service\FraudDetectionService;
|
||||
use Sensor\Service\Logger;
|
||||
use Sensor\Service\Profiler;
|
||||
use Sensor\Service\QueryParser;
|
||||
|
||||
class CreateEventController {
|
||||
public function __construct(
|
||||
private RequestFactory $requestFactory,
|
||||
private EventFactory $eventFactory,
|
||||
private ConnectionService $connectionService,
|
||||
private QueryParser $queryParser,
|
||||
private ?DataEnrichmentService $dataEnrichmentService,
|
||||
private DeviceDetectorService $deviceDetectorService,
|
||||
private FraudDetectionService $fraudDetectionService,
|
||||
private ApiKeyRepository $apiKeyRepository,
|
||||
private EventRepository $eventRepository,
|
||||
private AccountRepository $accountRepository,
|
||||
private \PDO $pdo,
|
||||
private Profiler $profiler,
|
||||
private Logger $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
public function index(Request $request, ?GetApiKeyDto $apiKeyDto): RegularResponse|ErrorResponse {
|
||||
$this->logger->logDebug('Request: ' . json_encode($request->body));
|
||||
|
||||
$this->profiler->start('user');
|
||||
|
||||
try {
|
||||
$dto = $this->requestFactory->createFromArray($request->body, $request->traceId, $this->eventRepository);
|
||||
} catch (ValidationException $e) {
|
||||
return new ValidationFailedResponse($e);
|
||||
}
|
||||
|
||||
if ($request->apiKey === null) {
|
||||
return new ErrorResponse('Api-Key header is not set', 401);
|
||||
}
|
||||
|
||||
if ($apiKeyDto === null) {
|
||||
return new ErrorResponse('API key from the "Api-Key" header is not found', 401);
|
||||
}
|
||||
|
||||
$this->connectionService->finishRequestForUser();
|
||||
$this->profiler->finish('user');
|
||||
|
||||
// Get account ID
|
||||
$account = new AccountEntity(
|
||||
$apiKeyDto->id,
|
||||
$dto->userName,
|
||||
$dto->ipAddress->value,
|
||||
$dto->fullName,
|
||||
$dto->firstName,
|
||||
$dto->lastName,
|
||||
$dto->eventTime,
|
||||
$dto->userCreated,
|
||||
);
|
||||
|
||||
$accountDto = $this->accountRepository->checkExistence($account);
|
||||
|
||||
if ($this->dataEnrichmentService === null) {
|
||||
$this->logger->logDebug('Skipping calling enrichment API, because it\'s not configured');
|
||||
}
|
||||
$enrichedData = $this->dataEnrichmentService?->getEnrichmentData(
|
||||
$apiKeyDto,
|
||||
$accountDto?->accountId,
|
||||
$dto->ipAddress, // check localhost inside of getEnrichmentData()
|
||||
$dto->emailAddress,
|
||||
$dto->emailDomain,
|
||||
$dto->phoneNumber,
|
||||
);
|
||||
|
||||
// Check if ip/email/phone is blacklisted
|
||||
$fraudDetected = $this->fraudDetectionService->getEarlierDetectedFraud(
|
||||
$apiKeyDto->id,
|
||||
$dto->emailAddress?->value,
|
||||
$dto->ipAddress->value,
|
||||
$dto->phoneNumber?->value,
|
||||
);
|
||||
|
||||
$deviceDetected = $this->deviceDetectorService->parse($apiKeyDto, $dto->userAgent);
|
||||
|
||||
$query = $this->queryParser->getQueryFromUrl($dto->url);
|
||||
|
||||
// Insert account and event into single transaction
|
||||
$this->pdo->beginTransaction();
|
||||
try {
|
||||
$this->apiKeyRepository->updateApiCallReached($enrichedData?->reached, $apiKeyDto);
|
||||
|
||||
$accountDto = $this->accountRepository->insert($account);
|
||||
|
||||
$event = $this->eventFactory->createFromDto(
|
||||
$accountDto->accountId,
|
||||
$accountDto->sessionId,
|
||||
$apiKeyDto->id,
|
||||
$dto,
|
||||
$enrichedData,
|
||||
$fraudDetected,
|
||||
$deviceDetected,
|
||||
$query,
|
||||
);
|
||||
|
||||
$this->profiler->start('db_insert');
|
||||
$insertDto = $this->eventRepository->insert(
|
||||
$event,
|
||||
$accountDto->lastEmailId,
|
||||
$accountDto->lastPhoneId,
|
||||
);
|
||||
$this->profiler->finish('db_insert');
|
||||
|
||||
$this->pdo->commit();
|
||||
} catch (\Throwable $e) {
|
||||
$this->pdo->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return new RegularResponse($insertDto->eventId, $dto->changedParams);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Dto;
|
||||
|
||||
class GetApiKeyDto {
|
||||
public function __construct(
|
||||
public int $id,
|
||||
public string $key,
|
||||
public ?string $token,
|
||||
public bool $hashExchange,
|
||||
public bool $skipEnrichingDomains,
|
||||
public bool $skipEnrichingEmails,
|
||||
public bool $skipEnrichingIps,
|
||||
public bool $skipEnrichingUserAgents,
|
||||
public bool $skipEnrichingPhones,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Dto;
|
||||
|
||||
class InsertAccountDto {
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public ?int $lastEmailId,
|
||||
public ?int $lastPhoneId,
|
||||
public int $sessionId
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Dto;
|
||||
|
||||
class InsertCountryDto {
|
||||
public function __construct(
|
||||
public int $eventCountryId,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Dto;
|
||||
|
||||
class InsertEmailDto {
|
||||
public function __construct(
|
||||
public int $emailId,
|
||||
public int $domainId,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Dto;
|
||||
|
||||
class InsertEventDto {
|
||||
public function __construct(
|
||||
public int $eventId,
|
||||
public int $ipAddressId,
|
||||
public int $urlId,
|
||||
public int $deviceId,
|
||||
public int $countryId,
|
||||
public ?int $domainId,
|
||||
public ?int $ispId,
|
||||
public ?int $payloadId,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Dto;
|
||||
|
||||
class InsertIpAddressDto {
|
||||
public function __construct(
|
||||
public int $ipAddressId,
|
||||
public int $countryId,
|
||||
public ?int $ispId,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Dto;
|
||||
|
||||
class InsertUrlDto {
|
||||
public function __construct(
|
||||
public int $urlId,
|
||||
public ?int $queryId,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Dto;
|
||||
|
||||
class InsertUserAgentDto {
|
||||
public function __construct(
|
||||
public int $userAgentId,
|
||||
public ?string $osName,
|
||||
public ?string $osVersion,
|
||||
public ?string $browserName,
|
||||
public ?string $browserVersion,
|
||||
public ?string $device,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class AccountEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $userName,
|
||||
public string $lastIp,
|
||||
public ?string $fullName,
|
||||
public ?string $firstName,
|
||||
public ?string $lastName,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
public ?\DateTimeImmutable $userCreated,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class CountryEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public int $countryId,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class DeviceEntity {
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public int $apiKeyId,
|
||||
public UserAgentEntity|UserAgentEnrichedEntity|null $userAgent,
|
||||
public ?string $lang,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class DomainEnrichedEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $domain,
|
||||
public bool $blockdomains,
|
||||
public bool $disposableDomains,
|
||||
public bool $freeEmailProvider,
|
||||
public ?string $ip,
|
||||
public ?string $geoIp,
|
||||
public ?string $geoHtml,
|
||||
public ?string $webServer,
|
||||
public ?string $hostname,
|
||||
public ?string $emails,
|
||||
public ?string $phone,
|
||||
public string $discoveryDate,
|
||||
public ?int $trancoRank,
|
||||
public ?string $creationDate,
|
||||
public ?string $expirationDate,
|
||||
public ?int $returnCode,
|
||||
public bool $disabled,
|
||||
public ?string $closestSnapshot,
|
||||
public bool $mxRecord,
|
||||
public bool $checked,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class DomainEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $domain,
|
||||
public ?bool $checked, // null if was not sent to enrichment
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class DomainNotFoundEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $domain,
|
||||
public bool $blockdomains,
|
||||
public bool $disposableDomains,
|
||||
public bool $freeEmailProvider,
|
||||
public ?string $creationDate,
|
||||
public ?string $expirationDate,
|
||||
public ?int $returnCode,
|
||||
public bool $disabled,
|
||||
public ?string $closestSnapshot,
|
||||
public bool $mxRecord,
|
||||
public bool $checked,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class EmailEnrichedEntity {
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public int $apiKeyId,
|
||||
public string $email,
|
||||
public ?string $hash,
|
||||
public DomainEntity|DomainEnrichedEntity|DomainNotFoundEntity $domain,
|
||||
public bool $blockEmails,
|
||||
public bool $dataBreach,
|
||||
public int $dataBreaches,
|
||||
public ?\DateTimeImmutable $earliestBreach,
|
||||
public int $profiles,
|
||||
public bool $domainContactEmail,
|
||||
public ?bool $alertList,
|
||||
public bool $fraudDetected,
|
||||
public bool $checked,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class EmailEntity {
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public int $apiKeyId,
|
||||
public string $email,
|
||||
public ?string $hash,
|
||||
public DomainEntity|DomainEnrichedEntity|DomainNotFoundEntity $domain,
|
||||
public bool $fraudDetected,
|
||||
public ?bool $checked, // null if was not sent to enrichment
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class EventEntity {
|
||||
/**
|
||||
* @param array<mixed, mixed>|null $payload
|
||||
*/
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public SessionEntity $session,
|
||||
public int $apiKeyId,
|
||||
public IpAddressEntity|IpAddressEnrichedEntity|IpAddressLocalhostEnrichedEntity $ipAddress,
|
||||
public UrlEntity $url,
|
||||
public ?string $eventType,
|
||||
public ?string $httpMethod,
|
||||
public DeviceEntity $device,
|
||||
public ?RefererEntity $referer,
|
||||
public EmailEntity|EmailEnrichedEntity|null $email,
|
||||
public PhoneEntity|PhoneEnrichedEntity|PhoneInvalidEntity|null $phone,
|
||||
public ?int $httpCode,
|
||||
public \DateTimeImmutable $eventTime,
|
||||
public ?string $traceId,
|
||||
public ?PayloadEntity $payload,
|
||||
public CountryEntity $country,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class IpAddressEnrichedEntity {
|
||||
/**
|
||||
* @param string[] $domainsCount
|
||||
*/
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $ipAddress,
|
||||
public ?string $hash,
|
||||
public int $countryId,
|
||||
public bool $hosting,
|
||||
public bool $vpn,
|
||||
public bool $tor,
|
||||
public bool $relay,
|
||||
public bool $starlink,
|
||||
public bool $blocklist,
|
||||
public array $domainsCount,
|
||||
public ?string $cidr,
|
||||
public ?bool $alertList,
|
||||
public bool $fraudDetected,
|
||||
public ?IspEnrichedEntity $isp,
|
||||
public bool $checked,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class IpAddressEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $ipAddress,
|
||||
public ?string $hash,
|
||||
public bool $fraudDetected,
|
||||
public IspEntity|IspLocalhostEntity|IspEnrichedEntity $isp,
|
||||
public ?bool $checked, // null if was not sent to enrichment
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class IpAddressLocalhostEnrichedEntity {
|
||||
/**
|
||||
* @param string[] $domainsCount
|
||||
*/
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $ipAddress,
|
||||
public ?string $hash,
|
||||
public bool $fraudDetected,
|
||||
public ?IspLocalhostEntity $isp,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
public int $countryId = 0,
|
||||
public bool $hosting = false,
|
||||
public bool $vpn = false,
|
||||
public bool $tor = false,
|
||||
public bool $relay = false,
|
||||
public bool $starlink = false,
|
||||
public bool $blocklist = false,
|
||||
public array $domainsCount = [],
|
||||
public ?string $cidr = null,
|
||||
public ?bool $alertList = null,
|
||||
public bool $checked = true,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class IspEnrichedEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public int $asn,
|
||||
public ?string $name,
|
||||
public ?string $description,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class IspEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
public int $asn = 64496,
|
||||
public string $name = 'N/A',
|
||||
public ?string $description = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class IspLocalhostEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
public int $asn = 0,
|
||||
public string $name = 'Local area network',
|
||||
public ?string $description = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class LogbookEntity {
|
||||
public const ERROR_TYPE_SUCCESS = 0;
|
||||
public const ERROR_TYPE_VALIDATION_ERROR = 1;
|
||||
public const ERROR_TYPE_CRITICAL_VALIDATION_ERROR = 2;
|
||||
public const ERROR_TYPE_CRITICAL_ERROR = 3;
|
||||
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $ip,
|
||||
public ?int $eventId,
|
||||
public int $errorType,
|
||||
public ?string $errorText,
|
||||
public string $raw,
|
||||
public ?string $started,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class PayloadEntity {
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public int $apiKeyId,
|
||||
public array|string $payload,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class PhoneEnrichedEntity {
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public int $apiKeyId,
|
||||
public string $phoneNumber,
|
||||
public ?string $hash,
|
||||
public int $profiles,
|
||||
public ?int $countryId,
|
||||
public int $callingCountryCode,
|
||||
public string $nationalFormat,
|
||||
public bool $invalid,
|
||||
public ?string $validationErrors,
|
||||
public ?string $carrierName,
|
||||
public string $type,
|
||||
public ?bool $alertList,
|
||||
public bool $fraudDetected,
|
||||
public bool $checked,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class PhoneEntity {
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public int $apiKeyId,
|
||||
public string $phoneNumber,
|
||||
public ?string $hash,
|
||||
public ?int $countryId,
|
||||
public bool $fraudDetected,
|
||||
public ?bool $checked, // null if was not sent to enrichment
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class PhoneInvalidEntity {
|
||||
public function __construct(
|
||||
public int $accountId,
|
||||
public int $apiKeyId,
|
||||
public string $phoneNumber,
|
||||
public ?string $hash,
|
||||
public int $countryId,
|
||||
public bool $fraudDetected,
|
||||
public string $validationErrors,
|
||||
public bool $checked,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class RefererEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $referer,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class SessionEntity {
|
||||
public function __construct(
|
||||
public int $id,
|
||||
public int $accountId,
|
||||
public int $apiKeyId,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class UrlEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $url,
|
||||
public ?UrlQueryEntity $query,
|
||||
public ?string $title,
|
||||
public ?int $httpCode,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class UrlQueryEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $query,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class UserAgentEnrichedEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public string $userAgent,
|
||||
public ?string $device,
|
||||
public ?string $browserName,
|
||||
public ?string $browserVersion,
|
||||
public ?string $osName,
|
||||
public ?string $osVersion,
|
||||
public bool $modified,
|
||||
public bool $checked,
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Entity;
|
||||
|
||||
class UserAgentEntity {
|
||||
public function __construct(
|
||||
public int $apiKeyId,
|
||||
public ?string $userAgent,
|
||||
public ?bool $checked, // null if was not sent to enrichment
|
||||
public \DateTimeImmutable $lastSeen,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Exception;
|
||||
|
||||
class AuthException extends \RuntimeException {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Exception;
|
||||
|
||||
class ForbiddenException extends \RuntimeException {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Exception;
|
||||
|
||||
class RateLimitException extends \RuntimeException {
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Exception;
|
||||
|
||||
class ValidationException extends \RuntimeException {
|
||||
public function __construct(
|
||||
string $message,
|
||||
private string $key,
|
||||
) {
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
public function getKey(): string {
|
||||
return $this->key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Factory;
|
||||
|
||||
use Sensor\Model\Enriched\EnrichedData;
|
||||
use Sensor\Model\Enriched\DomainEnriched;
|
||||
use Sensor\Model\Enriched\DomainNotFoundEnriched;
|
||||
use Sensor\Model\Enriched\DomainEnrichFailed;
|
||||
use Sensor\Model\Enriched\EmailEnriched;
|
||||
use Sensor\Model\Enriched\EmailEnrichFailed;
|
||||
use Sensor\Model\Enriched\IpAddressEnriched;
|
||||
use Sensor\Model\Enriched\IpAddressLocalhostEnriched;
|
||||
use Sensor\Model\Enriched\IpAddressEnrichFailed;
|
||||
use Sensor\Model\Enriched\IspEnriched;
|
||||
use Sensor\Model\Enriched\IspEnrichedEmpty;
|
||||
use Sensor\Model\Enriched\IspEnrichedLocalhost;
|
||||
use Sensor\Model\Enriched\PhoneEnriched;
|
||||
use Sensor\Model\Enriched\PhoneInvalidEnriched;
|
||||
use Sensor\Model\Enriched\PhoneEnrichFailed;
|
||||
use Sensor\Service\Enrichment\DataEnrichmentClientInterface;
|
||||
use Sensor\Service\Logger;
|
||||
|
||||
/**
|
||||
* @phpstan-import-type EnrichmentClientResponse from DataEnrichmentClientInterface
|
||||
*/
|
||||
class EnrichedDataFactory {
|
||||
private const IP_IS_BOGON_ERROR_TEXT = 'IP is bogon';
|
||||
private const VALIDATION_ERROR_TEXT = 'Validation failed';
|
||||
private const SERVER_ERROR = 'Server Error';
|
||||
|
||||
public function __construct(
|
||||
private Logger $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param EnrichmentClientResponse $data
|
||||
*/
|
||||
public function createFromResponse(array $data, array $origin): EnrichedData {
|
||||
$email = null;
|
||||
if (isset($data['email']['email'])) {
|
||||
try {
|
||||
$earliestBreach = $data['email']['earliest_breach'] !== null ? new \DateTimeImmutable($data['email']['earliest_breach']) : null;
|
||||
$email = new EmailEnriched(
|
||||
$data['email']['email'],
|
||||
$data['email']['blockemails'],
|
||||
$data['email']['data_breach'],
|
||||
$data['email']['data_breaches'],
|
||||
$earliestBreach,
|
||||
$data['email']['profiles'],
|
||||
$data['email']['domain_contact_email'],
|
||||
$data['email']['alert_list'],
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->logWarning('Error during parsing email response', $e);
|
||||
}
|
||||
} elseif (isset($data['email']['value'])) {
|
||||
$email = new EmailEnrichFailed(
|
||||
$data['email']['error'] === self::SERVER_ERROR ? $origin['email'] : $data['email']['value'],
|
||||
$data['email']['error'] === self::VALIDATION_ERROR_TEXT, // checked must be true on validation error to prevent repeating requests
|
||||
);
|
||||
}
|
||||
|
||||
$domain = null;
|
||||
if (isset($data['domain']['domain']) && array_key_exists('ip', $data['domain'])) {
|
||||
try {
|
||||
$domain = new DomainEnriched(
|
||||
$data['domain']['domain'],
|
||||
$data['domain']['blockdomains'],
|
||||
$data['domain']['disposable_domains'],
|
||||
$data['domain']['free_email_provider'],
|
||||
$data['domain']['ip'],
|
||||
$data['domain']['geo_ip'],
|
||||
$data['domain']['geo_html'],
|
||||
$data['domain']['web_server'],
|
||||
$data['domain']['hostname'],
|
||||
$data['domain']['emails'],
|
||||
$data['domain']['phone'],
|
||||
$data['domain']['discovery_date'],
|
||||
$data['domain']['tranco_rank'],
|
||||
$data['domain']['creation_date'],
|
||||
$data['domain']['expiration_date'],
|
||||
$data['domain']['return_code'],
|
||||
$data['domain']['disabled'],
|
||||
$data['domain']['closest_snapshot'],
|
||||
$data['domain']['mx_record'],
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->logWarning('Error during parsing domain response', $e);
|
||||
}
|
||||
} elseif (isset($data['domain']['domain'])) {
|
||||
$domain = new DomainNotFoundEnriched(
|
||||
$data['domain']['domain'],
|
||||
$data['domain']['blockdomains'],
|
||||
$data['domain']['disposable_domains'],
|
||||
$data['domain']['free_email_provider'],
|
||||
$data['domain']['creation_date'],
|
||||
$data['domain']['expiration_date'],
|
||||
$data['domain']['return_code'],
|
||||
$data['domain']['disabled'],
|
||||
$data['domain']['closest_snapshot'],
|
||||
$data['domain']['mx_record'],
|
||||
);
|
||||
} elseif (isset($data['domain']['value'])) {
|
||||
$domain = new DomainEnrichFailed(
|
||||
$data['domain']['error'] === self::SERVER_ERROR ? $origin['domain'] : $data['domain']['value'],
|
||||
$data['domain']['error'] === self::VALIDATION_ERROR_TEXT, // checked must be true on validation error to prevent repeating requests
|
||||
);
|
||||
}
|
||||
|
||||
$ip = $isp = null;
|
||||
if (isset($data['ip']['ip'])) {
|
||||
try {
|
||||
$ip = new IpAddressEnriched(
|
||||
$data['ip']['ip'],
|
||||
$data['ip']['country'],
|
||||
$data['ip']['hosting'],
|
||||
$data['ip']['vpn'],
|
||||
$data['ip']['tor'],
|
||||
$data['ip']['relay'],
|
||||
$data['ip']['starlink'],
|
||||
$data['ip']['blocklist'],
|
||||
$data['ip']['domains_count'],
|
||||
$data['ip']['cidr'],
|
||||
$data['ip']['alert_list'],
|
||||
);
|
||||
|
||||
if (isset($data['ip']['asn'])) {
|
||||
$isp = new IspEnriched(
|
||||
$data['ip']['asn'],
|
||||
$data['ip']['name'],
|
||||
$data['ip']['description'],
|
||||
);
|
||||
} else {
|
||||
$isp = new IspEnrichedEmpty();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->logWarning('Error during parsing IP response', $e);
|
||||
}
|
||||
} elseif (isset($data['ip']['error'])) {
|
||||
if ($data['ip']['error'] === self::IP_IS_BOGON_ERROR_TEXT) {
|
||||
$ip = new IpAddressLocalhostEnriched(
|
||||
$data['ip']['value'],
|
||||
);
|
||||
$isp = new IspEnrichedLocalhost();
|
||||
} else {
|
||||
$ip = new IpAddressEnrichFailed(
|
||||
$data['ip']['error'] === self::SERVER_ERROR ? $origin['ip'] : $data['ip']['value'],
|
||||
$data['ip']['error'] === self::VALIDATION_ERROR_TEXT, // checked must be true on validation error to prevent repeating requests
|
||||
);
|
||||
$isp = new IspEnrichedEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
$phone = null;
|
||||
if (isset($data['phone']['phone_number']) && isset($data['phone']['profiles'])) {
|
||||
try {
|
||||
$phone = new PhoneEnriched(
|
||||
$data['phone']['phone_number'],
|
||||
$data['phone']['profiles'],
|
||||
$data['phone']['iso_country_code'],
|
||||
$data['phone']['calling_country_code'],
|
||||
$data['phone']['national_format'],
|
||||
$data['phone']['invalid'],
|
||||
$data['phone']['validation_error'],
|
||||
$data['phone']['carrier_name'],
|
||||
$data['phone']['type'],
|
||||
$data['phone']['alert_list'],
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->logWarning('Error during parsing phone response', $e);
|
||||
}
|
||||
} elseif (isset($data['phone']['validation_error'])) {
|
||||
$this->logger->logWarning('Error getting phone from Enrichment API: ' . json_encode($data['phone']));
|
||||
$phone = new PhoneInvalidEnriched(
|
||||
$data['phone']['phone_number'],
|
||||
$data['phone']['invalid'],
|
||||
$data['phone']['validation_error'],
|
||||
);
|
||||
} elseif (isset($data['phone']['value'])) {
|
||||
$phone = new PhoneEnrichFailed(
|
||||
$data['phone']['error'] === self::SERVER_ERROR ? $origin['phone'] : $data['phone']['value'],
|
||||
$data['phone']['error'] === self::VALIDATION_ERROR_TEXT, // checked must be true on validation error to prevent repeating requests
|
||||
);
|
||||
}
|
||||
|
||||
// Check/log errors
|
||||
foreach ($data as $key => $value) {
|
||||
if (isset($value['error'])) {
|
||||
$this->logger->logWarning(sprintf(
|
||||
'Error getting %s from Enrichment API: %s',
|
||||
$key,
|
||||
json_encode($value),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return new EnrichedData($email, $domain, $ip, $isp, $phone, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Factory;
|
||||
|
||||
use Sensor\Entity\DeviceEntity;
|
||||
use Sensor\Entity\DomainEnrichedEntity;
|
||||
use Sensor\Entity\DomainEntity;
|
||||
use Sensor\Entity\DomainNotFoundEntity;
|
||||
use Sensor\Entity\EmailEnrichedEntity;
|
||||
use Sensor\Entity\EmailEntity;
|
||||
use Sensor\Entity\EventEntity;
|
||||
use Sensor\Entity\IpAddressEnrichedEntity;
|
||||
use Sensor\Entity\IpAddressLocalhostEnrichedEntity;
|
||||
use Sensor\Entity\IpAddressEntity;
|
||||
use Sensor\Entity\CountryEntity;
|
||||
use Sensor\Entity\IspEntity;
|
||||
use Sensor\Entity\IspEnrichedEntity;
|
||||
use Sensor\Entity\IspLocalhostEntity;
|
||||
use Sensor\Entity\PhoneEnrichedEntity;
|
||||
use Sensor\Entity\PhoneEntity;
|
||||
use Sensor\Entity\PhoneInvalidEntity;
|
||||
use Sensor\Entity\RefererEntity;
|
||||
use Sensor\Entity\SessionEntity;
|
||||
use Sensor\Entity\UrlEntity;
|
||||
use Sensor\Entity\UrlQueryEntity;
|
||||
use Sensor\Entity\UserAgentEnrichedEntity;
|
||||
use Sensor\Entity\UserAgentEntity;
|
||||
use Sensor\Entity\PayloadEntity;
|
||||
use Sensor\Model\Blacklist\FraudDetected;
|
||||
use Sensor\Model\CreateEventDto;
|
||||
use Sensor\Model\DeviceDetected;
|
||||
use Sensor\Repository\CountryRepository;
|
||||
use Sensor\Model\Enriched\EnrichedData;
|
||||
use Sensor\Model\Enriched\IpAddressEnriched;
|
||||
use Sensor\Model\Enriched\IpAddressLocalhostEnriched;
|
||||
use Sensor\Model\Enriched\IpAddressEnrichFailed;
|
||||
use Sensor\Model\Enriched\PhoneEnriched;
|
||||
use Sensor\Model\Enriched\PhoneInvalidEnriched;
|
||||
use Sensor\Model\Enriched\PhoneEnrichFailed;
|
||||
use Sensor\Model\Enriched\DomainEnriched;
|
||||
use Sensor\Model\Enriched\DomainNotFoundEnriched;
|
||||
use Sensor\Model\Enriched\DomainEnrichFailed;
|
||||
use Sensor\Model\Enriched\EmailEnriched;
|
||||
use Sensor\Model\Enriched\EmailEnrichFailed;
|
||||
|
||||
class EventFactory {
|
||||
public function __construct(
|
||||
private CountryRepository $countryRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
public function createFromDto(
|
||||
int $accountId,
|
||||
int $sessionId,
|
||||
int $apiKeyId,
|
||||
CreateEventDto $dto,
|
||||
?EnrichedData $enrichedData,
|
||||
FraudDetected $fraudDetected,
|
||||
?DeviceDetected $deviceDetected,
|
||||
?string $query,
|
||||
): EventEntity {
|
||||
$lastSeen = $dto->eventTime;
|
||||
|
||||
// Remove query from url
|
||||
$urlWithoutQuery = $query !== null ? str_replace($query, '', $dto->url) : $dto->url;
|
||||
|
||||
$queryEntity = null;
|
||||
if ($query !== null) {
|
||||
$queryEntity = new UrlQueryEntity($apiKeyId, $query, $lastSeen);
|
||||
}
|
||||
$url = new UrlEntity($apiKeyId, $urlWithoutQuery, $queryEntity, $dto->pageTitle, $dto->httpCode, $lastSeen);
|
||||
$eventType = $dto->eventType;
|
||||
$httpMethod = $dto->httpMethod;
|
||||
|
||||
if ($dto->httpReferer !== null) {
|
||||
$referer = new RefererEntity($apiKeyId, $dto->httpReferer, $lastSeen);
|
||||
}
|
||||
|
||||
$session = new SessionEntity($sessionId, $accountId, $apiKeyId, $lastSeen);
|
||||
|
||||
// set countryId after inserting ip
|
||||
$country = new CountryEntity($apiKeyId, 0, $lastSeen);
|
||||
|
||||
$ipAddress = null;
|
||||
if ($dto->ipAddress->localhost) {
|
||||
// sensor-defined localhost
|
||||
$isp = new IspLocalhostEntity($apiKeyId, $lastSeen);
|
||||
$ipAddress = new IpAddressLocalhostEnrichedEntity(
|
||||
$apiKeyId,
|
||||
$dto->ipAddress->value,
|
||||
$dto->ipAddress->hash,
|
||||
$fraudDetected->ip,
|
||||
$isp,
|
||||
$lastSeen,
|
||||
);
|
||||
} else {
|
||||
if ($enrichedData?->ip instanceof IpAddressEnriched || $enrichedData?->ip instanceof IpAddressLocalhostEnriched) {
|
||||
// isp IspEnriched or IspEnrichedEmpty
|
||||
// it's a new ip, checked is true; should be INSERTed or UPDATEd
|
||||
$countryId = $this->countryRepository->getCountryIdByCode($enrichedData->ip->countryCode);
|
||||
$isp = new IspEnrichedEntity(
|
||||
$apiKeyId,
|
||||
$enrichedData->isp->asn,
|
||||
$enrichedData->isp->name,
|
||||
$enrichedData->isp->description,
|
||||
$lastSeen,
|
||||
);
|
||||
$ipAddress = new IpAddressEnrichedEntity(
|
||||
$apiKeyId,
|
||||
$enrichedData->ip->ipAddress,
|
||||
$dto->ipAddress->hash,
|
||||
$countryId,
|
||||
$enrichedData->ip->hosting,
|
||||
$enrichedData->ip->vpn,
|
||||
$enrichedData->ip->tor,
|
||||
$enrichedData->ip->relay,
|
||||
$enrichedData->ip->starlink,
|
||||
$enrichedData->ip->blocklist,
|
||||
$enrichedData->ip->domainsCount,
|
||||
$enrichedData->ip->cidr,
|
||||
$enrichedData->ip->alertList,
|
||||
$fraudDetected->ip,
|
||||
$isp,
|
||||
true,
|
||||
$lastSeen,
|
||||
);
|
||||
} elseif ($enrichedData?->ip instanceof IpAddressEnrichFailed) {
|
||||
// checked can be false or true on bogon ip; should be INSERTed or UPDATEd (if it is reenrichment)
|
||||
// isp made of IspEnrichedLocalhost or IspEnrichedEmpty
|
||||
$isp = new IspEnrichedEntity(
|
||||
$apiKeyId,
|
||||
$enrichedData->isp->asn,
|
||||
$enrichedData->isp->name,
|
||||
$enrichedData->isp->description,
|
||||
$lastSeen,
|
||||
);
|
||||
$ipAddress = new IpAddressEntity(
|
||||
$apiKeyId,
|
||||
$enrichedData->ip->ipAddress,
|
||||
$dto->ipAddress->hash,
|
||||
$fraudDetected->ip,
|
||||
$isp,
|
||||
$enrichedData->ip->checked,
|
||||
$lastSeen,
|
||||
);
|
||||
} else {
|
||||
// ip already exists and has checked true or enrichment is off; should be UPDATEd or INSERTed if enrichment is off
|
||||
// isp unknown, N/A will be used if enrichment is off or failed
|
||||
$isp = new IspEntity(
|
||||
$apiKeyId,
|
||||
$lastSeen,
|
||||
);
|
||||
$ipAddress = new IpAddressEntity(
|
||||
$apiKeyId,
|
||||
$dto->ipAddress->value,
|
||||
$dto->ipAddress->hash,
|
||||
$fraudDetected->ip,
|
||||
$isp,
|
||||
null, // enrichment is off or was enriched earlier
|
||||
$lastSeen,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$domain = null;
|
||||
if ($dto->emailDomain !== null) {
|
||||
if ($enrichedData?->domain instanceof DomainEnriched) {
|
||||
$domain = new DomainEnrichedEntity(
|
||||
$apiKeyId,
|
||||
$enrichedData->domain->domain,
|
||||
$enrichedData->domain->blockdomains,
|
||||
$enrichedData->domain->disposableDomains,
|
||||
$enrichedData->domain->freeEmailProvider,
|
||||
$enrichedData->domain->ip,
|
||||
$enrichedData->domain->geoIp,
|
||||
$enrichedData->domain->geoHtml,
|
||||
$enrichedData->domain->webServer,
|
||||
$enrichedData->domain->hostname,
|
||||
$enrichedData->domain->emails,
|
||||
$enrichedData->domain->phone,
|
||||
$enrichedData->domain->discoveryDate,
|
||||
$enrichedData->domain->trancoRank,
|
||||
$enrichedData->domain->creationDate,
|
||||
$enrichedData->domain->expirationDate,
|
||||
$enrichedData->domain->returnCode,
|
||||
$enrichedData->domain->disabled,
|
||||
$enrichedData->domain->closestSnapshot,
|
||||
$enrichedData->domain->mxRecord,
|
||||
true,
|
||||
$lastSeen,
|
||||
);
|
||||
} elseif ($enrichedData?->domain instanceof DomainNotFoundEnriched) {
|
||||
$domain = new DomainNotFoundEntity(
|
||||
$apiKeyId,
|
||||
$enrichedData->domain->domain,
|
||||
$enrichedData->domain->blockdomains,
|
||||
$enrichedData->domain->disposableDomains,
|
||||
$enrichedData->domain->freeEmailProvider,
|
||||
$enrichedData->domain->creationDate,
|
||||
$enrichedData->domain->expirationDate,
|
||||
$enrichedData->domain->returnCode,
|
||||
$enrichedData->domain->disabled,
|
||||
$enrichedData->domain->closestSnapshot,
|
||||
$enrichedData->domain->mxRecord,
|
||||
true,
|
||||
$lastSeen,
|
||||
);
|
||||
} elseif ($enrichedData?->domain instanceof DomainEnrichFailed) {
|
||||
$domain = new DomainEntity(
|
||||
$apiKeyId,
|
||||
$enrichedData->domain->domain,
|
||||
$enrichedData->domain->checked,
|
||||
$lastSeen,
|
||||
);
|
||||
} else {
|
||||
$domain = new DomainEntity(
|
||||
$apiKeyId,
|
||||
$dto->emailDomain,
|
||||
null, // enrichment is off or was enriched earlier
|
||||
$lastSeen,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$email = null;
|
||||
if ($dto->emailAddress !== null && $domain !== null) {
|
||||
if ($enrichedData?->email instanceof EmailEnriched) {
|
||||
$email = new EmailEnrichedEntity(
|
||||
$accountId,
|
||||
$apiKeyId,
|
||||
$enrichedData->email->email,
|
||||
$dto->emailAddress->hash,
|
||||
$domain,
|
||||
$enrichedData->email->blockEmails,
|
||||
$enrichedData->email->dataBreach,
|
||||
$enrichedData->email->dataBreaches,
|
||||
$enrichedData->email->earliestBreach,
|
||||
$enrichedData->email->profiles,
|
||||
$enrichedData->email->domainContactEmail,
|
||||
$enrichedData->email->alertList,
|
||||
$fraudDetected->email,
|
||||
true,
|
||||
$lastSeen,
|
||||
);
|
||||
} elseif ($enrichedData?->email instanceof EmailEnrichFailed) {
|
||||
$email = new EmailEntity(
|
||||
$accountId,
|
||||
$apiKeyId,
|
||||
$enrichedData->email->email,
|
||||
$dto->emailAddress->hash,
|
||||
$domain,
|
||||
$fraudDetected->email,
|
||||
$enrichedData->email->checked,
|
||||
$lastSeen,
|
||||
);
|
||||
} else {
|
||||
$email = new EmailEntity(
|
||||
$accountId,
|
||||
$apiKeyId,
|
||||
$dto->emailAddress->value,
|
||||
$dto->emailAddress->hash,
|
||||
$domain,
|
||||
$fraudDetected->email,
|
||||
null, // enrichment is off or was enriched earlier
|
||||
$lastSeen,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$phone = null;
|
||||
if ($dto->phoneNumber !== null) {
|
||||
$countryId = 0;
|
||||
if ($enrichedData?->phone instanceof PhoneEnriched) {
|
||||
if ($enrichedData->phone->countryCode !== null) {
|
||||
$countryId = $this->countryRepository->getCountryIdByCode($enrichedData->phone->countryCode);
|
||||
}
|
||||
$phone = new PhoneEnrichedEntity(
|
||||
$accountId,
|
||||
$apiKeyId,
|
||||
$enrichedData->phone->phoneNumber,
|
||||
$dto->phoneNumber->hash,
|
||||
$enrichedData->phone->profiles,
|
||||
$countryId,
|
||||
$enrichedData->phone->callingCountryCode,
|
||||
$enrichedData->phone->nationalFormat,
|
||||
$enrichedData->phone->invalid,
|
||||
$enrichedData->phone->validationErrors,
|
||||
$enrichedData->phone->carrierName,
|
||||
$enrichedData->phone->type,
|
||||
$enrichedData->phone->alertList,
|
||||
$fraudDetected->phone,
|
||||
true,
|
||||
$lastSeen,
|
||||
);
|
||||
} elseif ($enrichedData?->phone instanceof PhoneInvalidEnriched) {
|
||||
$phone = new PhoneInvalidEntity(
|
||||
$accountId,
|
||||
$apiKeyId,
|
||||
$enrichedData->phone->phoneNumber,
|
||||
$dto->phoneNumber->hash,
|
||||
$countryId,
|
||||
$fraudDetected->phone,
|
||||
$enrichedData->phone->validationErrors,
|
||||
true,
|
||||
$lastSeen,
|
||||
);
|
||||
} elseif ($enrichedData?->phone instanceof PhoneEnrichFailed) {
|
||||
$phone = new PhoneEntity(
|
||||
$accountId,
|
||||
$apiKeyId,
|
||||
$enrichedData->phone->phoneNumber,
|
||||
$dto->phoneNumber->hash,
|
||||
$countryId,
|
||||
$fraudDetected->phone,
|
||||
$enrichedData->phone->checked,
|
||||
$lastSeen,
|
||||
);
|
||||
} else {
|
||||
$phone = new PhoneEntity(
|
||||
$accountId,
|
||||
$apiKeyId,
|
||||
$dto->phoneNumber->value,
|
||||
$dto->phoneNumber->hash,
|
||||
$countryId, // set country to 0 if enrichment is off or keep existing country in query
|
||||
$fraudDetected->phone,
|
||||
null, // enrichment is off or was enriched earlier
|
||||
$lastSeen,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$userAgent = null;
|
||||
if ($deviceDetected instanceof DeviceDetected) {
|
||||
$userAgent = new UserAgentEnrichedEntity(
|
||||
$apiKeyId,
|
||||
$deviceDetected->userAgent,
|
||||
$deviceDetected->device,
|
||||
$deviceDetected->browserName,
|
||||
$deviceDetected->browserVersion,
|
||||
$deviceDetected->osName,
|
||||
$deviceDetected->osVersion,
|
||||
$deviceDetected->modified,
|
||||
true,
|
||||
$lastSeen,
|
||||
);
|
||||
} else {
|
||||
$userAgent = new UserAgentEntity(
|
||||
$apiKeyId,
|
||||
$dto->userAgent,
|
||||
null, // ua is null, was enriched earlier or enrichment is off
|
||||
$lastSeen,
|
||||
);
|
||||
}
|
||||
|
||||
$device = new DeviceEntity($accountId, $apiKeyId, $userAgent, $dto->browserLanguage, $lastSeen);
|
||||
|
||||
$payload = ($dto->payload) ? (new PayloadEntity($accountId, $apiKeyId, $dto->payload, $lastSeen)) : null;
|
||||
|
||||
return new EventEntity(
|
||||
$accountId,
|
||||
$session,
|
||||
$apiKeyId,
|
||||
$ipAddress,
|
||||
$url,
|
||||
$eventType,
|
||||
$httpMethod,
|
||||
$device,
|
||||
$referer ?? null,
|
||||
$email ?? null,
|
||||
$phone ?? null,
|
||||
$dto->httpCode,
|
||||
$dto->eventTime,
|
||||
$dto->traceId,
|
||||
$payload,
|
||||
$country,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
namespace Sensor\Factory;
|
||||
|
||||
use Sensor\Entity\LogbookEntity;
|
||||
use Sensor\Model\Http\ErrorResponse;
|
||||
use Sensor\Model\Http\RegularResponse;
|
||||
use Sensor\Model\Http\Request;
|
||||
use Sensor\Model\Http\ValidationFailedResponse;
|
||||
use Sensor\Repository\ApiKeyRepository;
|
||||
|
||||
class LogbookEntityFactory {
|
||||
public function create(
|
||||
int $apiKeyId,
|
||||
\DateTime $startedTime,
|
||||
RegularResponse|ErrorResponse $response,
|
||||
): LogbookEntity {
|
||||
$eventId = null;
|
||||
if ($response instanceof RegularResponse) {
|
||||
$errorText = $response->validationErrors();
|
||||
$errorType = $errorText !== null
|
||||
? LogbookEntity::ERROR_TYPE_VALIDATION_ERROR
|
||||
: LogbookEntity::ERROR_TYPE_SUCCESS
|
||||
;
|
||||
$eventId = $response->eventId;
|
||||
} elseif ($response instanceof ValidationFailedResponse) {
|
||||
$errorType = LogbookEntity::ERROR_TYPE_CRITICAL_VALIDATION_ERROR;
|
||||
$errorText = json_encode([$response->jsonSerialize()]);
|
||||
} elseif ($response instanceof ErrorResponse) {
|
||||
$errorType = LogbookEntity::ERROR_TYPE_CRITICAL_ERROR;
|
||||
$errorText = json_encode([$response->jsonSerialize()]);
|
||||
} else {
|
||||
$errorType = LogbookEntity::ERROR_TYPE_CRITICAL_ERROR;
|
||||
$errorText = json_encode(['Undefined error']);
|
||||
}
|
||||
|
||||
return new LogbookEntity(
|
||||
$apiKeyId,
|
||||
$_SERVER['REMOTE_ADDR'],
|
||||
$eventId,
|
||||
$errorType,
|
||||
$errorText,
|
||||
$this->getRawRequest(),
|
||||
$this->formatStarted($startedTime),
|
||||
);
|
||||
}
|
||||
|
||||
public function createFromException(
|
||||
int $apiKeyId,
|
||||
\DateTime $startedTime,
|
||||
string $errorText,
|
||||
): LogbookEntity {
|
||||
return new LogbookEntity(
|
||||
$apiKeyId,
|
||||
$_SERVER['REMOTE_ADDR'],
|
||||
null,
|
||||
3,
|
||||
$errorText,
|
||||
$this->getRawRequest(),
|
||||
$this->formatStarted($startedTime),
|
||||
);
|
||||
}
|
||||
|
||||
private function getRawRequest(): string {
|
||||
return json_encode(array_intersect_key($_POST, array_flip(Request::ACCEPTABLE_FIELDS)));
|
||||
}
|
||||
|
||||
private function formatStarted(\DateTime $startedTime): string {
|
||||
$milliseconds = (int) ($startedTime->format('u') / 1000);
|
||||
|
||||
return $startedTime->format('Y-m-d H:i:s') . '.' . sprintf('%03d', $milliseconds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Factory;
|
||||
|
||||
use Sensor\Exception\ValidationException;
|
||||
use Sensor\Model\CreateEventDto;
|
||||
use Sensor\Model\HashedValue;
|
||||
use Sensor\Model\Validated\Email;
|
||||
use Sensor\Model\Validated\IpAddress;
|
||||
use Sensor\Model\Validated\Phone;
|
||||
use Sensor\Model\Validated\Timestamp;
|
||||
use Sensor\Model\Validated\HttpCode;
|
||||
use Sensor\Model\Validated\Firstname;
|
||||
use Sensor\Model\Validated\Lastname;
|
||||
use Sensor\Model\Validated\Fullname;
|
||||
use Sensor\Model\Validated\HttpReferer;
|
||||
use Sensor\Model\Validated\Userid;
|
||||
use Sensor\Model\Validated\PageTitle;
|
||||
use Sensor\Model\Validated\Url;
|
||||
use Sensor\Model\Validated\UserAgent;
|
||||
use Sensor\Model\Validated\BrowserLanguage;
|
||||
use Sensor\Model\Validated\EventType;
|
||||
use Sensor\Model\Validated\HttpMethod;
|
||||
use Sensor\Model\Validated\UserCreated;
|
||||
use Sensor\Model\Validated\Payloads\FieldEditPayload;
|
||||
use Sensor\Model\Validated\Payloads\PageSearchPayload;
|
||||
use Sensor\Model\Validated\Payloads\EmailChangePayload;
|
||||
use Sensor\Repository\EventRepository;
|
||||
use Sensor\Service\Constants;
|
||||
|
||||
class RequestFactory {
|
||||
private const REQUIRED_FIELDS = ['ipAddress', 'url', 'eventTime'];
|
||||
|
||||
/**
|
||||
* @param array<string, string> $data
|
||||
*/
|
||||
public static function createFromArray(array $data, ?string $traceId, EventRepository $eventRepository): CreateEventDto {
|
||||
foreach (self::REQUIRED_FIELDS as $key) {
|
||||
if (!isset($data[$key])) {
|
||||
throw new ValidationException('Required field is missing or empty', $key);
|
||||
}
|
||||
}
|
||||
|
||||
$eventTime = new Timestamp($data['eventTime']);
|
||||
|
||||
$userCreated = isset($data['userCreated']) ? (new UserCreated($data['userCreated'])) : null;
|
||||
|
||||
$referer = isset($data['httpReferer']) ? (new HttpReferer($data['httpReferer'])) : null;
|
||||
$httpCode = isset($data['httpCode']) ? (new HttpCode($data['httpCode'])) : null;
|
||||
|
||||
$ipAddress = new IpAddress($data['ipAddress']);
|
||||
|
||||
$phone = isset($data['phoneNumber']) ? (new Phone($data['phoneNumber'])) : null;
|
||||
|
||||
$email = isset($data['emailAddress']) ? (new Email($data['emailAddress'])) : null;
|
||||
$firstname = isset($data['firstName']) ? (new Firstname($data['firstName'])) : null;
|
||||
$lastname = isset($data['lastName']) ? (new Lastname($data['lastName'])) : null;
|
||||
$fullname = isset($data['fullName']) ? (new Fullname($data['fullName'])) : null;
|
||||
$username = isset($data['userName']) ? (new Userid($data['userName'])) : null;
|
||||
$pageTitle = isset($data['pageTitle']) ? (new PageTitle($data['pageTitle'])) : null;
|
||||
$url = isset($data['url']) ? (new Url($data['url'])) : null;
|
||||
$userAgent = isset($data['userAgent']) ? (new UserAgent($data['userAgent'])) : null;
|
||||
$browserLang = isset($data['browserLanguage']) ? (new BrowserLanguage($data['browserLanguage'])) : null;
|
||||
$eventType = isset($data['eventType']) ? (new EventType($data['eventType'])) : null;
|
||||
$httpMethod = isset($data['httpMethod']) ? (new HttpMethod($data['httpMethod'])) : null;
|
||||
|
||||
$payload = null;
|
||||
$payloadRaw = $data['payload'] ?? null;
|
||||
|
||||
if ($eventType?->value) {
|
||||
$eventTypeId = $eventRepository->getEventType($eventType->value);
|
||||
|
||||
if ($eventTypeId === Constants::FIELD_EDIT_EVENT_TYPE_ID) {
|
||||
$payload = new FieldEditPayload($payloadRaw);
|
||||
} elseif ($payloadRaw) {
|
||||
switch ($eventTypeId) {
|
||||
case Constants::ACCOUNT_EMAIL_CHANGE_EVENT_TYPE_ID:
|
||||
$payload = new EmailChangePayload($payloadRaw);
|
||||
break;
|
||||
case Constants::PAGE_SEARCH_EVENT_TYPE_ID:
|
||||
$payload = new PageSearchPayload($payloadRaw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$validatedParams = [
|
||||
$email, $eventTime, $userCreated, $referer, $httpCode, $ipAddress,
|
||||
$phone, $firstname, $lastname, $fullname, $username, $pageTitle,
|
||||
$url, $userAgent, $browserLang, $eventType, $httpMethod, $payload,
|
||||
];
|
||||
|
||||
$changedParams = self::changedParams($validatedParams);
|
||||
|
||||
//$email = !isset($data['emailAddress']) && !isset($data['userName']) ? Email::makePlaceholder() : $email;
|
||||
//$username = $username === null ? md5($email->value) : $username->value;
|
||||
|
||||
if ($email === null && $username === null) {
|
||||
$username = 'N/A';
|
||||
} else {
|
||||
$username = $username === null ? md5($email->value) : $username->value;
|
||||
}
|
||||
|
||||
return new CreateEventDto(
|
||||
$firstname?->value,
|
||||
$lastname?->value,
|
||||
$fullname?->value,
|
||||
$pageTitle?->value,
|
||||
$username,
|
||||
$email !== null ? new HashedValue($email) : null,
|
||||
$email !== null ? explode('@', $email->value)[1] : null,
|
||||
$phone !== null && !$phone->isEmpty() ? new HashedValue($phone) : null,
|
||||
new HashedValue($ipAddress),
|
||||
$url?->value,
|
||||
$userAgent?->value,
|
||||
$eventTime->value,
|
||||
$referer?->value,
|
||||
$httpCode?->value,
|
||||
$browserLang?->value,
|
||||
$eventType?->value,
|
||||
$httpMethod?->value,
|
||||
$userCreated?->value,
|
||||
$traceId,
|
||||
$payload?->value,
|
||||
$changedParams,
|
||||
);
|
||||
}
|
||||
|
||||
private static function changedParams(array $validatedParams): array {
|
||||
$result = [];
|
||||
|
||||
foreach ($validatedParams as $param) {
|
||||
if ($param !== null) {
|
||||
$validation = $param->validationStatement();
|
||||
if ($validation !== null) {
|
||||
$result[] = $validation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Blacklist;
|
||||
|
||||
class FraudDetected {
|
||||
public function __construct(
|
||||
public bool $email,
|
||||
public bool $ip,
|
||||
public bool $phone,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Config;
|
||||
|
||||
class Config implements \JsonSerializable {
|
||||
public function __construct(
|
||||
public DatabaseConfig $databaseConfig,
|
||||
public ?string $enrichmentApiUrl = null,
|
||||
#[\SensitiveParameter]
|
||||
public ?string $enrichmentApiKey = null,
|
||||
public ?string $scoreApiUrl = null,
|
||||
public ?string $userAgent = null,
|
||||
public bool $debugLog = false,
|
||||
public bool $allowEmailPhone = false,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
return [
|
||||
'databaseConfig' => $this->databaseConfig,
|
||||
'enrichmentApiUrl' => $this->enrichmentApiUrl,
|
||||
'scoreApiUrl' => $this->scoreApiUrl,
|
||||
'debugLog' => $this->debugLog,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Config;
|
||||
|
||||
class DatabaseConfig implements \JsonSerializable {
|
||||
public function __construct(
|
||||
public string $dbHost,
|
||||
public int $dbPort,
|
||||
public string $dbUser,
|
||||
#[\SensitiveParameter]
|
||||
public string $dbPassword,
|
||||
public string $dbDatabaseName,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
return [
|
||||
'dbHost' => $this->dbHost,
|
||||
'dbPort' => $this->dbPort,
|
||||
'dbUser' => $this->dbUser,
|
||||
'dbDatabaseName' => $this->dbDatabaseName,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model;
|
||||
|
||||
class CreateEventDto {
|
||||
/**
|
||||
* @param array<mixed, mixed>|null $payload
|
||||
*/
|
||||
public function __construct(
|
||||
public ?string $firstName,
|
||||
public ?string $lastName,
|
||||
public ?string $fullName,
|
||||
public ?string $pageTitle,
|
||||
public string $userName,
|
||||
public ?HashedValue $emailAddress,
|
||||
public ?string $emailDomain,
|
||||
public ?HashedValue $phoneNumber,
|
||||
public HashedValue $ipAddress,
|
||||
public string $url,
|
||||
public ?string $userAgent,
|
||||
public \DateTimeImmutable $eventTime,
|
||||
public ?string $httpReferer,
|
||||
public ?int $httpCode,
|
||||
public ?string $browserLanguage,
|
||||
public ?string $eventType,
|
||||
public ?string $httpMethod,
|
||||
public ?\DateTimeImmutable $userCreated,
|
||||
public ?string $traceId,
|
||||
public array|string|null $payload,
|
||||
public array $changedParams,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model;
|
||||
|
||||
class DeviceDetected {
|
||||
public function __construct(
|
||||
public ?string $device,
|
||||
public ?string $browserName,
|
||||
public ?string $browserVersion,
|
||||
public ?string $osName,
|
||||
public ?string $osVersion,
|
||||
public string $userAgent,
|
||||
public bool $modified,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class DomainEnrichFailed {
|
||||
public function __construct(
|
||||
public string $domain,
|
||||
public bool $checked = false, // must be true on validation error to prevent repeating requests
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class DomainEnriched {
|
||||
public function __construct(
|
||||
public string $domain,
|
||||
public bool $blockdomains,
|
||||
public bool $disposableDomains,
|
||||
public bool $freeEmailProvider,
|
||||
public ?string $ip,
|
||||
public ?string $geoIp,
|
||||
public ?string $geoHtml,
|
||||
public ?string $webServer,
|
||||
public ?string $hostname,
|
||||
public ?string $emails,
|
||||
public ?string $phone,
|
||||
public string $discoveryDate,
|
||||
public ?int $trancoRank,
|
||||
public ?string $creationDate,
|
||||
public ?string $expirationDate,
|
||||
public ?int $returnCode,
|
||||
public bool $disabled,
|
||||
public ?string $closestSnapshot,
|
||||
public bool $mxRecord,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class DomainNotFoundEnriched {
|
||||
public function __construct(
|
||||
public string $domain,
|
||||
public bool $blockdomains,
|
||||
public bool $disposableDomains,
|
||||
public bool $freeEmailProvider,
|
||||
public ?string $creationDate,
|
||||
public ?string $expirationDate,
|
||||
public ?int $returnCode,
|
||||
public bool $disabled,
|
||||
public ?string $closestSnapshot,
|
||||
public bool $mxRecord,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class EmailEnrichFailed {
|
||||
public function __construct(
|
||||
public string $email,
|
||||
public bool $checked = false, // must be true on validation error to prevent repeating requests
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class EmailEnriched {
|
||||
public function __construct(
|
||||
public string $email,
|
||||
public bool $blockEmails,
|
||||
public bool $dataBreach,
|
||||
public int $dataBreaches,
|
||||
public ?\DateTimeImmutable $earliestBreach,
|
||||
public int $profiles,
|
||||
public bool $domainContactEmail,
|
||||
public ?bool $alertList,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class EnrichedData {
|
||||
public function __construct(
|
||||
public EmailEnriched|EmailEnrichFailed|null $email,
|
||||
public DomainEnriched|DomainNotFoundEnriched|DomainEnrichFailed|null $domain,
|
||||
public IpAddressEnriched|IpAddressLocalhostEnriched|IpAddressEnrichFailed|null $ip,
|
||||
public IspEnriched|IspEnrichedEmpty|IspEnrichedLocalhost|null $isp, // TODO: move to IP
|
||||
public PhoneEnriched|PhoneInvalidEnriched|PhoneEnrichFailed|null $phone,
|
||||
public bool $reached,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class IpAddressEnrichFailed {
|
||||
public function __construct(
|
||||
public string $ipAddress,
|
||||
public bool $checked = false, // must be true on validation error to prevent repeating requests
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class IpAddressEnriched {
|
||||
/**
|
||||
* @param string[] $domainsCount
|
||||
*/
|
||||
public function __construct(
|
||||
public string $ipAddress,
|
||||
public string $countryCode,
|
||||
public bool $hosting,
|
||||
public bool $vpn,
|
||||
public bool $tor,
|
||||
public bool $relay,
|
||||
public bool $starlink,
|
||||
public bool $blocklist,
|
||||
public array $domainsCount,
|
||||
public string $cidr,
|
||||
public ?bool $alertList,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class IpAddressLocalhostEnriched {
|
||||
/**
|
||||
* @param string[] $domainsCount
|
||||
*/
|
||||
public function __construct(
|
||||
public string $ipAddress,
|
||||
public string $countryCode = 'N/A',
|
||||
public bool $hosting = false,
|
||||
public bool $vpn = false,
|
||||
public bool $tor = false,
|
||||
public bool $relay = false,
|
||||
public bool $starlink = false,
|
||||
public bool $blocklist = false,
|
||||
public ?array $domainsCount = [],
|
||||
public ?string $cidr = null,
|
||||
public ?bool $alertList = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class IspEnriched {
|
||||
public function __construct(
|
||||
public int $asn,
|
||||
public ?string $name,
|
||||
public ?string $description,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class IspEnrichedEmpty {
|
||||
public function __construct(
|
||||
public int $asn = 64496,
|
||||
public ?string $name = 'N/A',
|
||||
public ?string $description = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class IspEnrichedLocalhost {
|
||||
public function __construct(
|
||||
public int $asn = 0,
|
||||
public ?string $name = 'Local area network',
|
||||
public ?string $description = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class PhoneEnrichFailed {
|
||||
public function __construct(
|
||||
public string $phoneNumber,
|
||||
public bool $checked = false, // must be true on validation error to prevent repeating requests
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class PhoneEnriched {
|
||||
public function __construct(
|
||||
public string $phoneNumber,
|
||||
public int $profiles,
|
||||
public ?string $countryCode,
|
||||
public int $callingCountryCode,
|
||||
public string $nationalFormat,
|
||||
public bool $invalid,
|
||||
public ?string $validationErrors,
|
||||
public ?string $carrierName,
|
||||
public string $type,
|
||||
public ?bool $alertList,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Enriched;
|
||||
|
||||
class PhoneInvalidEnriched {
|
||||
public function __construct(
|
||||
public string $phoneNumber,
|
||||
public bool $invalid,
|
||||
public string $validationErrors,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model;
|
||||
|
||||
use Sensor\Model\Validated\Email;
|
||||
use Sensor\Model\Validated\IpAddress;
|
||||
use Sensor\Model\Validated\Phone;
|
||||
|
||||
class HashedValue {
|
||||
public string $value;
|
||||
public string $hash;
|
||||
public ?bool $localhost = null;
|
||||
|
||||
public function __construct(
|
||||
Email|IpAddress|Phone $input,
|
||||
) {
|
||||
$this->value = $input->value;
|
||||
$this->hash = hash('sha256', $this->value);
|
||||
if ($input instanceof IpAddress) {
|
||||
$this->localhost = $input->isLocalhost();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{value: string, hash: ?string}
|
||||
*/
|
||||
public function toArray(bool $hashExchange): array {
|
||||
return [
|
||||
'value' => $this->value,
|
||||
'hash' => $hashExchange ? $this->hash : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Http;
|
||||
|
||||
class ErrorResponse {
|
||||
public function __construct(
|
||||
public string $errorMessage,
|
||||
public int $httpCode,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->errorMessage;
|
||||
}
|
||||
|
||||
public function jsonSerialize() {
|
||||
return $this->__toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Http;
|
||||
|
||||
class RegularResponse {
|
||||
public function __construct(
|
||||
public int $eventId,
|
||||
public array $changedParams,
|
||||
) {
|
||||
}
|
||||
|
||||
public function validationErrors(): ?string {
|
||||
return count($this->changedParams) ? json_encode($this->changedParams) : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Http;
|
||||
|
||||
class Request {
|
||||
public const ACCEPTABLE_FIELDS = [
|
||||
'userName',
|
||||
'emailAddress',
|
||||
'ipAddress',
|
||||
'url',
|
||||
'userAgent',
|
||||
'eventTime',
|
||||
'firstName',
|
||||
'lastName',
|
||||
'fullName',
|
||||
'pageTitle',
|
||||
'phoneNumber',
|
||||
'httpReferer',
|
||||
'httpCode',
|
||||
'browserLanguage',
|
||||
'eventType',
|
||||
'httpMethod',
|
||||
'userCreated',
|
||||
'payload',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array<string,string> $body
|
||||
*/
|
||||
public function __construct(
|
||||
public array $body,
|
||||
#[\SensitiveParameter]
|
||||
public ?string $apiKey,
|
||||
public ?string $traceId,
|
||||
) {
|
||||
// all acceptable $this->body values should be either string or null
|
||||
foreach (self::ACCEPTABLE_FIELDS as $key) {
|
||||
if (isset($this->body[$key])) {
|
||||
$value = $this->body[$key];
|
||||
|
||||
if (is_bool($value)) {
|
||||
$this->body[$key] = ($value) ? 'true' : 'false';
|
||||
} elseif (is_array($value)) {
|
||||
$this->body[$key] = $this->cleanArrayEncoding($value);
|
||||
if ($key !== 'payload') {
|
||||
$this->body[$key] = json_encode($this->body[$key]);
|
||||
}
|
||||
} elseif ($value !== null) {
|
||||
$this->body[$key] = $this->cleanArrayEncoding(strval($value));
|
||||
}
|
||||
} else {
|
||||
$this->body[$key] = null;
|
||||
}
|
||||
}
|
||||
$this->body['hashEmailAddress'] = null;
|
||||
$this->body['hashPhoneNumber'] = null;
|
||||
$this->body['hashIpAddress'] = null;
|
||||
}
|
||||
|
||||
// recursive array encoding cleanup
|
||||
private function cleanArrayEncoding(mixed $data): mixed {
|
||||
if (is_string($data)) {
|
||||
return mb_convert_encoding($data, 'UTF-8', 'UTF-8');
|
||||
} elseif (is_array($data)) {
|
||||
foreach ($data as $key => $value) {
|
||||
$data[$key] = $this->cleanArrayEncoding($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Http;
|
||||
|
||||
use Sensor\Exception\ValidationException;
|
||||
|
||||
class ValidationFailedResponse extends ErrorResponse {
|
||||
public function __construct(
|
||||
private ValidationException $exception,
|
||||
) {
|
||||
parent::__construct('Validation error', 400);
|
||||
}
|
||||
|
||||
public function __toString(): string {
|
||||
return sprintf(
|
||||
'Validation error: "%s" for key "%s"',
|
||||
$this->exception->getMessage(),
|
||||
$this->exception->getKey(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Score;
|
||||
|
||||
class ScoreAccount {
|
||||
public function __construct(
|
||||
public string $apiKey,
|
||||
public int $accountId,
|
||||
public string $userId,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Base {
|
||||
private string $type;
|
||||
public bool $invalid;
|
||||
public string $origin;
|
||||
|
||||
public function __construct(string $value, string $type) {
|
||||
$this->origin = $value;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function validationStatement(): ?string {
|
||||
if ($this->invalid) {
|
||||
return "$this->type validation error on `$this->origin`";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class BrowserLanguage extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'browserLanguage', 255);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Email extends Length {
|
||||
private const PLACEHOLDER = 'unknown@localhost';
|
||||
private const INVALIDPLACEHOLDER = 'broken@user.local';
|
||||
|
||||
public string $value;
|
||||
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'emailAddress', 255);
|
||||
$value = strtolower(str_replace(' ', '', $value));
|
||||
|
||||
if (!self::isPlaceholder($value) && filter_var($value, \FILTER_VALIDATE_EMAIL) === false) {
|
||||
$this->value = self::INVALIDPLACEHOLDER;
|
||||
} else {
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
$this->invalid = $this->invalid || (!self::isPlaceholder($value) && filter_var($value, \FILTER_VALIDATE_EMAIL) === false);
|
||||
}
|
||||
|
||||
public static function makePlaceholder(): self {
|
||||
return new self(self::PLACEHOLDER);
|
||||
}
|
||||
|
||||
public static function isPlaceholder(string $email): bool {
|
||||
return self::PLACEHOLDER === $email;
|
||||
}
|
||||
|
||||
public static function isInvalid(string $value): bool {
|
||||
return self::INVALIDPLACEHOLDER === $value;
|
||||
}
|
||||
|
||||
public static function isPlaceholderDomain(string $email): bool {
|
||||
return explode('@', self::PLACEHOLDER)[1] === $email;
|
||||
}
|
||||
|
||||
public static function isInvalidDomain(string $value): bool {
|
||||
return explode('@', self::INVALIDPLACEHOLDER)[1] === $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class EventType extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'eventType');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Firstname extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'firstName');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Fullname extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'fullName');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class HttpCode extends Base {
|
||||
private const INVALIDPLACEHOLDER = '0';
|
||||
public int $value;
|
||||
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'httpCode');
|
||||
$this->value = (int) (ctype_digit($value) ? $value : self::INVALIDPLACEHOLDER);
|
||||
$this->invalid = !ctype_digit($value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class HttpMethod extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'httpMethod');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class HttpReferer extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'httpReferer', 2047);
|
||||
|
||||
$this->value = urldecode($this->value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class IpAddress extends Base {
|
||||
private const INVALIDPLACEHOLDER = '0.0.0.0';
|
||||
private const LOCALHOST_NETS = [
|
||||
'0.0.0.0/8', '10.0.0.0/8', '100.64.0.0/10', '127.0.0.0/8',
|
||||
'169.254.0.0/16', '172.16.0.0/12', '192.0.0.0/24', '192.0.2.0/24',
|
||||
'192.168.0.0/16', '198.18.0.0/15', '198.51.100.0/24', '203.0.113.0/24',
|
||||
'224.0.0.0/4', '240.0.0.0/4', '255.255.255.255/32',
|
||||
'::/128', '::1/128', '::ffff:0:0/96', '::/96', '100::/64', '2001:10::/28',
|
||||
'2001:db8::/32', 'fc00::/7', 'fe80::/10', 'fec0::/10', 'ff00::/8',
|
||||
];
|
||||
public string $value;
|
||||
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'ipAddress');
|
||||
$value = str_replace(' ', '', $value);
|
||||
|
||||
if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) === false) {
|
||||
$this->value = self::INVALIDPLACEHOLDER;
|
||||
} else {
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
$this->invalid = filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) === false;
|
||||
}
|
||||
|
||||
public static function isInvalid(string $value): bool {
|
||||
return self::INVALIDPLACEHOLDER === $value;
|
||||
}
|
||||
|
||||
public function isLocalhost(): bool {
|
||||
if (filter_var($this->value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$size = filter_var($this->value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 4 : 16;
|
||||
$ip = inet_pton($this->value);
|
||||
|
||||
foreach (self::LOCALHOST_NETS as $cidr) {
|
||||
[$net, $maskBits] = explode('/', $cidr);
|
||||
$net = inet_pton($net);
|
||||
if (!$net) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$solid = (int) floor($maskBits / 8);
|
||||
$solidBits = $solid * 8;
|
||||
$mask = str_repeat(chr(255), $solid);
|
||||
for ($i = $solidBits; $i < $maskBits; $i += 8) {
|
||||
$bits = max(0, min(8, $maskBits - $i));
|
||||
$mask .= chr((pow(2, $bits) - 1) << (8 - $bits));
|
||||
}
|
||||
$mask = str_pad($mask, $size, chr(0));
|
||||
|
||||
if (($ip & $mask) === ($net & $mask)) {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Lastname extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'lastName');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Length extends Base {
|
||||
public string $value;
|
||||
|
||||
public function __construct(string $value, string $type, int $limit = 100) {
|
||||
parent::__construct($value, $type);
|
||||
|
||||
if (strlen($value) > $limit) {
|
||||
$this->value = substr($value, 0, $limit);
|
||||
} else {
|
||||
// even if empty string!
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
$this->invalid = strlen($value) > $limit;
|
||||
}
|
||||
|
||||
public function isEmpty(): bool {
|
||||
return $this->value === '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class PageTitle extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'pageTitle', 255);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated\Payloads;
|
||||
|
||||
class Base extends \Sensor\Model\Validated\Base {
|
||||
protected array $optionalFields;
|
||||
protected array $requiredFields;
|
||||
|
||||
protected bool $set;
|
||||
protected bool $dump;
|
||||
|
||||
public array|string|null $value;
|
||||
|
||||
public function __construct(mixed $value) {
|
||||
parent::__construct(json_encode($value), 'payload');
|
||||
|
||||
if (!is_array($value)) {
|
||||
$this->invalid = true;
|
||||
$this->value = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->invalid = false;
|
||||
$data = [];
|
||||
|
||||
if (!$this->set) {
|
||||
$data = $this->preserveItem($value);
|
||||
} else {
|
||||
foreach ($value as $payload) {
|
||||
$item = [];
|
||||
if ($payload && is_array($payload)) {
|
||||
$item = $this->preserveItem($payload);
|
||||
|
||||
if ($item && count($item)) {
|
||||
$data[] = $item;
|
||||
} else {
|
||||
$this->invalid = true;
|
||||
}
|
||||
} else {
|
||||
$this->invalid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!count($data)) {
|
||||
$this->invalid = true;
|
||||
}
|
||||
|
||||
$this->value = count($data) ? ($this->dump ? json_encode($data) : $data) : null;
|
||||
}
|
||||
|
||||
private function preserveItem(array $item): ?array {
|
||||
$data = [];
|
||||
|
||||
foreach ($this->requiredFields as $key) {
|
||||
if (isset($item[$key])) {
|
||||
$data[$key] = $this->convert($item[$key]);
|
||||
} else {
|
||||
$data[$key] = null;
|
||||
$this->invalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->optionalFields as $key) {
|
||||
$data[$key] = isset($item[$key]) ? $this->convert($item[$key]) : null;
|
||||
}
|
||||
|
||||
return count($data) ? $data : null;
|
||||
}
|
||||
|
||||
private function convert(mixed $val): ?string {
|
||||
if (is_array($val)) {
|
||||
return json_encode($val);
|
||||
}
|
||||
|
||||
if (is_int($val) || is_float($val) || is_string($val) || is_bool($val)) {
|
||||
return strval($val);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated\Payloads;
|
||||
|
||||
class EmailChangePayload extends Base {
|
||||
public function __construct(mixed $value) {
|
||||
$this->requiredFields = [
|
||||
'new_value',
|
||||
];
|
||||
|
||||
$this->optionalFields = [
|
||||
'old_value',
|
||||
];
|
||||
|
||||
$this->set = false;
|
||||
$this->dump = true;
|
||||
|
||||
parent::__construct($value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated\Payloads;
|
||||
|
||||
class FieldEditPayload extends Base {
|
||||
public function __construct(mixed $value) {
|
||||
$this->requiredFields = [
|
||||
'new_value',
|
||||
];
|
||||
|
||||
$this->optionalFields = [
|
||||
'field_id',
|
||||
'field_name',
|
||||
'old_value',
|
||||
'parent_id',
|
||||
'parent_name',
|
||||
];
|
||||
|
||||
$this->set = true;
|
||||
$this->dump = false;
|
||||
|
||||
parent::__construct($value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated\Payloads;
|
||||
|
||||
class PageSearchPayload extends Base {
|
||||
public function __construct(mixed $value) {
|
||||
$this->requiredFields = [
|
||||
'field_id',
|
||||
'value',
|
||||
];
|
||||
|
||||
$this->optionalFields = [
|
||||
'field_name',
|
||||
];
|
||||
|
||||
$this->set = false;
|
||||
$this->dump = true;
|
||||
|
||||
parent::__construct($value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Phone extends Base {
|
||||
private const MAX_PHONE_LENGTH = 19;
|
||||
public string $value;
|
||||
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'phoneNumber');
|
||||
$value = str_replace(' ', '', $value);
|
||||
|
||||
if (strlen($value) > self::MAX_PHONE_LENGTH) {
|
||||
$this->value = substr($value, 0, self::MAX_PHONE_LENGTH);
|
||||
} else {
|
||||
// even if empty string!
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
$this->invalid = strlen($value) > self::MAX_PHONE_LENGTH;
|
||||
}
|
||||
|
||||
public function isEmpty(): bool {
|
||||
return $this->value === '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Timestamp extends Base {
|
||||
public const EVENTFORMAT = 'Y-m-d H:i:s.v';
|
||||
public const FORMAT = 'Y-m-d H:i:s';
|
||||
public const MICROSECONDS = 'Y-m-d H:i:s.u';
|
||||
|
||||
public \DateTimeImmutable $value;
|
||||
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'timestamp');
|
||||
$invalid = false;
|
||||
|
||||
try {
|
||||
$val = \DateTimeImmutable::createFromFormat(self::EVENTFORMAT, $value);
|
||||
} catch (\Throwable $e) {
|
||||
// \DateTimeImmutable::createFromFormat throws ValueError when the datetime contains NULL-bytes
|
||||
$invalid = true;
|
||||
$val = self::currentTime();
|
||||
}
|
||||
|
||||
if ($val === false) {
|
||||
$val = \DateTimeImmutable::createFromFormat(self::FORMAT, $value);
|
||||
}
|
||||
|
||||
if ($val === false) {
|
||||
$val = \DateTimeImmutable::createFromFormat(self::MICROSECONDS, $value);
|
||||
}
|
||||
|
||||
if ($val === false) {
|
||||
$invalid = true;
|
||||
$val = self::currentTime();
|
||||
}
|
||||
|
||||
$this->value = $val;
|
||||
$this->invalid = $invalid;
|
||||
}
|
||||
|
||||
private function currentTime(): \DateTimeImmutable {
|
||||
return new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tirreno ~ Open source user analytics
|
||||
* Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
*
|
||||
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright (c) Tirreno Technologies Sàrl (https://www.tirreno.com)
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
||||
* @link https://www.tirreno.com Tirreno(tm)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sensor\Model\Validated;
|
||||
|
||||
class Url extends Length {
|
||||
public function __construct(string $value) {
|
||||
parent::__construct($value, 'url', 2047);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user