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,53 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
abstract class Base extends \Models\BaseSql {
|
||||
protected $DB_TABLE_NAME = 'event';
|
||||
|
||||
abstract public function getContext(array $accountIds, int $apiKey): array;
|
||||
|
||||
abstract protected function getDetails(array $accountIds, int $apiKey): array;
|
||||
|
||||
protected function getRequestParams(array $accountIds, int $apiKey): array {
|
||||
[$params, $placeHolders] = $this->getArrayPlaceholders($accountIds);
|
||||
$params[':api_key'] = $apiKey;
|
||||
|
||||
return [$params, $placeHolders];
|
||||
}
|
||||
|
||||
protected function groupRecordsByAccount(array $records): array {
|
||||
$recordsByAccount = [];
|
||||
$iters = count($records);
|
||||
|
||||
for ($i = 0; $i < $iters; ++$i) {
|
||||
$item = $records[$i];
|
||||
$accountId = $item['accountid'];
|
||||
|
||||
if (!isset($recordsByAccount[$accountId])) {
|
||||
$recordsByAccount[$accountId] = [];
|
||||
}
|
||||
|
||||
$recordsByAccount[$accountId][] = $item;
|
||||
}
|
||||
|
||||
return $recordsByAccount;
|
||||
}
|
||||
|
||||
protected function getUniqueArray(array $array): array {
|
||||
return array_values(array_unique($array));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class Data {
|
||||
private \Models\Context\User $userModel;
|
||||
private \Models\Context\Ip $ipModel;
|
||||
private \Models\Context\Device $deviceModel;
|
||||
private \Models\Context\Email $emailModel;
|
||||
private \Models\Context\Phone $phoneModel;
|
||||
private \Models\Context\Event $eventModel;
|
||||
private \Models\Context\Session $sessionModel;
|
||||
private \Models\ApiKeys $keyModel;
|
||||
|
||||
private array $suspiciousWordsUrl;
|
||||
private array $suspiciousWordsUserAgent;
|
||||
private array $suspiciousWordsEmail;
|
||||
|
||||
public function __construct() {
|
||||
$this->userModel = new User();
|
||||
$this->ipModel = new Ip();
|
||||
$this->deviceModel = new Device();
|
||||
$this->emailModel = new Email();
|
||||
$this->phoneModel = new Phone();
|
||||
$this->eventModel = new Event();
|
||||
$this->sessionModel = new Session();
|
||||
$this->keyModel = new \Models\ApiKeys();
|
||||
|
||||
$this->suspiciousWordsUrl = \Utils\WordsLists\Url::getWords();
|
||||
$this->suspiciousWordsUserAgent = \Utils\WordsLists\UserAgent::getWords();
|
||||
$this->suspiciousWordsEmail = \Utils\WordsLists\Email::getWords();
|
||||
}
|
||||
|
||||
public function getContext(array $accountIds, int $apiKey): array {
|
||||
$userDetails = $this->userModel->getContext($accountIds, $apiKey);
|
||||
$ipDetails = $this->ipModel->getContext($accountIds, $apiKey);
|
||||
$deviceDetails = $this->deviceModel->getContext($accountIds, $apiKey);
|
||||
$emailDetails = $this->emailModel->getContext($accountIds, $apiKey);
|
||||
$phoneDetails = $this->phoneModel->getContext($accountIds, $apiKey);
|
||||
$eventDetails = $this->eventModel->getContext($accountIds, $apiKey);
|
||||
//$domainDetails = $this->domainModel->getContext($accountIds, $apiKey);
|
||||
|
||||
$timezoneName = $this->keyModel->getTimezoneByKeyId($apiKey);
|
||||
$utcTime = new \DateTime('now', new \DateTimeZone('UTC'));
|
||||
$timezone = new \DateTimeZone($timezoneName);
|
||||
$offsetInSeconds = $timezone->getOffset($utcTime);
|
||||
|
||||
// get only suspicious sessions
|
||||
$sessionDetails = $this->sessionModel->getContext($accountIds, $apiKey, $offsetInSeconds);
|
||||
|
||||
//Extend user details context
|
||||
foreach ($userDetails as $userId => $user) {
|
||||
$user['le_exists'] = ($user['le_email'] ?? null) !== null;
|
||||
$user['le_email'] = $user['le_email'] ?? '';
|
||||
$user['le_local_part'] = explode('@', $user['le_email'])[0] ?? '';
|
||||
$user['le_domain_part'] = explode('@', $user['le_email'])[1] ?? '';
|
||||
|
||||
$userId = $user['ea_id'];
|
||||
$ip = $ipDetails[$userId] ?? [];
|
||||
$device = $deviceDetails[$userId] ?? [];
|
||||
$email = $emailDetails[$userId] ?? [];
|
||||
$phone = $phoneDetails[$userId] ?? [];
|
||||
$events = $eventDetails[$userId] ?? [];
|
||||
$session = $sessionDetails[$userId] ?? [];
|
||||
|
||||
$user['eip_ip_id'] = $ip['eip_ip_id'] ?? [];
|
||||
$user['eip_ip'] = $ip['eip_ip'] ?? [];
|
||||
$user['eip_cidr'] = $ip['eip_cidr'] ?? [];
|
||||
$user['eip_country_id'] = $ip['eip_country_id'] ?? [];
|
||||
$user['eip_data_center'] = $ip['eip_data_center'] ?? [];
|
||||
$user['eip_tor'] = $ip['eip_tor'] ?? [];
|
||||
$user['eip_vpn'] = $ip['eip_vpn'] ?? [];
|
||||
$user['eip_relay'] = $ip['eip_relay'] ?? [];
|
||||
$user['eip_starlink'] = $ip['eip_starlink'] ?? [];
|
||||
$user['eip_total_visit'] = $ip['eip_total_visit'] ?? [];
|
||||
$user['eip_blocklist'] = $ip['eip_blocklist'] ?? [];
|
||||
$user['eip_shared'] = $ip['eip_shared'] ?? [];
|
||||
//$user['eip_domains'] = $ip['eip_domains'] ?? [];
|
||||
$user['eip_country_id'] = $ip['eip_country_id'] ?? [];
|
||||
$user['eip_fraud_detected'] = $ip['eip_fraud_detected'] ?? [];
|
||||
$user['eip_alert_list'] = $ip['eip_alert_list'] ?? [];
|
||||
$user['eip_domains_count_len'] = $ip['eip_domains_count_len'] ?? [];
|
||||
|
||||
$user['eup_device'] = $device['eup_device'] ?? [];
|
||||
$user['eup_device_id'] = $device['eup_device_id'] ?? [];
|
||||
$user['eup_browser_name'] = $device['eup_browser_name'] ?? [];
|
||||
$user['eup_browser_version'] = $device['eup_browser_version'] ?? [];
|
||||
$user['eup_os_name'] = $device['eup_os_name'] ?? [];
|
||||
$user['eup_lang'] = $device['eup_lang'] ?? [];
|
||||
$user['eup_ua'] = $device['eup_ua'] ?? [];
|
||||
// $user['eup_lastseen'] = $device['eup_lastseen'] ?? [];
|
||||
// $user['eup_created'] = $device['eup_created'] ?? [];
|
||||
|
||||
$user['ee_email'] = $email['ee_email'] ?? [];
|
||||
$user['ee_earliest_breach'] = $email['ee_earliest_breach'] ?? [];
|
||||
|
||||
$user['ep_phone_number'] = $phone['ep_phone_number'] ?? [];
|
||||
$user['ep_shared'] = $phone['ep_shared'] ?? [];
|
||||
$user['ep_type'] = $phone['ep_type'] ?? [];
|
||||
|
||||
$user['event_ip'] = $events['event_ip'] ?? [];
|
||||
$user['event_url_string'] = $events['event_url_string'] ?? [];
|
||||
$user['event_empty_referer'] = $events['event_empty_referer'] ?? [];
|
||||
$user['event_device'] = $events['event_device'] ?? [];
|
||||
$user['event_type'] = $events['event_type'] ?? [];
|
||||
$user['event_http_method'] = $events['event_http_method'] ?? [];
|
||||
$user['event_http_code'] = $events['event_http_code'] ?? [];
|
||||
$user['event_device_created'] = $events['event_device_created'] ?? [];
|
||||
$user['event_device_lastseen'] = $events['event_device_lastseen'] ?? [];
|
||||
|
||||
$user['event_session_multiple_country'] = $session[0]['event_session_multiple_country'] ?? false;
|
||||
$user['event_session_multiple_ip'] = $session[0]['event_session_multiple_ip'] ?? false;
|
||||
$user['event_session_multiple_device'] = $session[0]['event_session_multiple_device'] ?? false;
|
||||
$user['event_session_night_time'] = $session[0]['event_session_night_time'] ?? false;
|
||||
|
||||
//Extra params for rules
|
||||
$user = $this->extendParams($user);
|
||||
|
||||
$userDetails[$userId] = $this->extendEventParams($user);
|
||||
}
|
||||
|
||||
return $userDetails;
|
||||
}
|
||||
|
||||
private function extendParams(array $record): array {
|
||||
//$record['timezone']
|
||||
|
||||
$localPartLen = strlen($record['le_local_part']);
|
||||
$domainPartLen = strlen($record['le_domain_part']);
|
||||
$fullName = $this->getUserFullName($record);
|
||||
|
||||
$record['le_local_part_len'] = $localPartLen;
|
||||
$record['ea_fullname_has_numbers'] = preg_match('~[0-9]+~', $fullName) > 0;
|
||||
$record['ea_fullname_has_spaces_hyphens'] = preg_match('~[\-\s]~', $fullName) > 0;
|
||||
$record['ea_days_since_account_creation'] = $this->getDaysSinceAccountCreation($record);
|
||||
$record['ea_days_since_last_visit'] = $this->getDaysSinceLastVisit($record);
|
||||
|
||||
//$record['le_has_no_profiles'] = $record['le_profiles'] === 0;
|
||||
$record['le_has_no_data_breaches'] = $record['le_data_breach'] === false;
|
||||
$record['le_has_suspicious_str'] = $this->checkEmailForSuspiciousString($record);
|
||||
$record['le_has_numeric_only_local_part'] = preg_match('/^[0-9]+$/', $record['le_local_part']) > 0;
|
||||
$record['le_email_has_consec_s_chars'] = preg_match('/[^a-zA-Z0-9]{2,}/', $record['le_local_part']) > 0;
|
||||
$record['le_email_has_consec_nums'] = preg_match('/\d{2}/', $record['le_local_part']) > 0;
|
||||
$record['le_email_has_no_digits'] = !preg_match('/\d/', $record['le_local_part']);
|
||||
$record['le_email_has_vowels'] = preg_match('/[aeoui]/i', $record['le_local_part']) > 0;
|
||||
$record['le_email_has_consonants'] = preg_match('/[bcdfghjklmnpqrstvwxyz]/i', $record['le_local_part']) > 0;
|
||||
|
||||
$record['le_with_long_local_part_length'] = $localPartLen > \Utils\Constants::get('RULE_EMAIL_MAXIMUM_LOCAL_PART_LENGTH');
|
||||
$record['le_with_long_domain_length'] = $domainPartLen > \Utils\Constants::get('RULE_EMAIL_MAXIMUM_DOMAIN_LENGTH');
|
||||
$record['le_email_in_blockemails'] = $record['le_blockemails'] ?? false;
|
||||
$record['le_is_invalid'] = $record['le_exists'] && filter_var($record['le_email'], FILTER_VALIDATE_EMAIL) === false;
|
||||
|
||||
$record['le_appears_on_alert_list'] = $record['le_alert_list'] ?? false;
|
||||
|
||||
$record['ld_is_disposable'] = $record['ld_disposable_domains'] ?? false;
|
||||
$record['ld_days_since_domain_creation'] = $this->getDaysSinceDomainCreation($record);
|
||||
$record['ld_domain_free_email_provider'] = $record['ld_free_email_provider'] ?? false;
|
||||
$record['ld_from_blockdomains'] = $record['ld_blockdomains'] ?? false;
|
||||
$record['ld_domain_without_mx_record'] = $record['ld_mx_record'] === false;
|
||||
$record['ld_website_is_disabled'] = $record['ld_disabled'] ?? false;
|
||||
$record['ld_tranco_rank'] = $record['ld_tranco_rank'] ?? -1;
|
||||
|
||||
$record['lp_invalid_phone'] = $record['lp_invalid'] === true;
|
||||
$record['ep_shared_phone'] = (bool) count(array_filter($record['ep_shared'], static function ($item) {
|
||||
return $item !== null && $item > 1;
|
||||
}));
|
||||
|
||||
$daysSinceBreaches = array_map(function ($item) {
|
||||
return $this->getDaysTillToday($item);
|
||||
}, $record['ee_earliest_breach']);
|
||||
|
||||
$record['ee_days_since_first_breach'] = count($daysSinceBreaches) ? max($daysSinceBreaches) : -1;
|
||||
|
||||
$onlyNonResidentialParams = !(bool) count(array_filter(array_merge(
|
||||
$record['eip_fraud_detected'],
|
||||
$record['eip_blocklist'],
|
||||
$record['eip_tor'],
|
||||
$record['eip_starlink'],
|
||||
$record['eip_relay'],
|
||||
$record['eip_vpn'],
|
||||
$record['eip_data_center'],
|
||||
), static function ($value): bool {
|
||||
return $value === true;
|
||||
}));
|
||||
$record['eip_only_residential'] = $onlyNonResidentialParams && !in_array(0, $record['eip_country_id']);
|
||||
$record['eip_has_fraud'] = in_array(true, $record['eip_fraud_detected']);
|
||||
$record['eip_unique_cidrs'] = count(array_unique($record['eip_cidr']));
|
||||
$record['lp_fraud_detected'] = $record['lp_fraud_detected'] ?? false;
|
||||
$record['le_fraud_detected'] = $record['le_fraud_detected'] ?? false;
|
||||
|
||||
$record['eup_has_rare_browser'] = (bool) count(array_diff($record['eup_browser_name'], array_keys(\Utils\Constants::get('RULE_REGULAR_BROWSER_NAMES'))));
|
||||
$record['eup_has_rare_os'] = (bool) count(array_diff($record['eup_os_name'], \Utils\Constants::get('RULE_REGULAR_OS_NAMES')));
|
||||
$record['eup_device_count'] = count($record['eup_device']);
|
||||
|
||||
$record['eup_vulnerable_ua'] = false;
|
||||
|
||||
if (count($this->suspiciousWordsUserAgent)) {
|
||||
foreach ($record['eup_ua'] as $url) {
|
||||
foreach ($this->suspiciousWordsUserAgent as $sub) {
|
||||
if (stripos($url, $sub) !== false) {
|
||||
$record['eup_vulnerable_ua'] = true;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
private function extendEventParams(array $record): array {
|
||||
// Remove null values specifically
|
||||
$eventTypeFiltered = $this->filterStringNum($record['event_type']);
|
||||
$eventHttpCodeFiltered = $this->filterStringNum($record['event_http_code']);
|
||||
|
||||
$eventTypeCount = array_count_values($eventTypeFiltered);
|
||||
|
||||
//$accountLoginFailId = \Utils\Constants::get('ACCOUNT_LOGIN_FAIL_EVENT_TYPE_ID');
|
||||
$accountEmailChangeId = \Utils\Constants::get('ACCOUNT_EMAIL_CHANGE_EVENT_TYPE_ID');
|
||||
$accountPwdChangeId = \Utils\Constants::get('ACCOUNT_PASSWORD_CHANGE_EVENT_TYPE_ID');
|
||||
|
||||
//$record['event_failed_login_attempts'] = $eventTypeCount[$accountLoginFailId] ?? 0;
|
||||
$record['event_email_changed'] = array_key_exists($accountEmailChangeId, $eventTypeCount);
|
||||
$record['event_password_changed'] = array_key_exists($accountPwdChangeId, $eventTypeCount);
|
||||
|
||||
$record['event_http_method_head'] = in_array(\Utils\Constants::get('EVENT_REQUEST_TYPE_HEAD'), $record['event_http_method']);
|
||||
|
||||
$record['event_empty_referer'] = in_array(true, $record['event_empty_referer'], true);
|
||||
|
||||
$clientErrors = 0;
|
||||
$serverErrors = 0;
|
||||
$successEvents = 0;
|
||||
foreach ($eventHttpCodeFiltered as $code) {
|
||||
if (is_int($code) && $code >= 400 && $code < 500) {
|
||||
++$clientErrors;
|
||||
} elseif (is_int($code) && $code >= 500 && $code < 600) {
|
||||
++$serverErrors;
|
||||
} elseif (is_int($code) && $code >= 200 && $code < 300) {
|
||||
++$successEvents;
|
||||
}
|
||||
}
|
||||
|
||||
$record['event_multiple_5xx_http'] = $serverErrors;
|
||||
$record['event_multiple_4xx_http'] = $clientErrors;
|
||||
|
||||
$record['event_2xx_http'] = (bool) $successEvents;
|
||||
|
||||
$record['event_vulnerable_url'] = false;
|
||||
|
||||
if (count($this->suspiciousWordsUrl)) {
|
||||
foreach ($record['event_url_string'] as $url) {
|
||||
foreach ($this->suspiciousWordsUrl as $sub) {
|
||||
if (stripos($url, $sub) !== false) {
|
||||
$record['event_vulnerable_url'] = true;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
private function getDaysSinceDomainCreation(array $params): int {
|
||||
$dt1 = date('Y-m-d');
|
||||
$dt2 = $params['ld_creation_date'];
|
||||
|
||||
return $this->getDaysDiff($dt1, $dt2);
|
||||
}
|
||||
|
||||
private function getDaysSinceAccountCreation(array $params): int {
|
||||
$dt1 = date('Y-m-d');
|
||||
$dt2 = $params['ea_created'] ?? null;
|
||||
|
||||
return $this->getDaysDiff($dt1, $dt2);
|
||||
}
|
||||
|
||||
private function getDaysSinceLastVisit(array $params): int {
|
||||
$dt1 = date('Y-m-d');
|
||||
$dt2 = $params['ea_lastseen'] ?? null;
|
||||
|
||||
return $this->getDaysDiff($dt1, $dt2);
|
||||
}
|
||||
|
||||
private function getDaysTillToday(?string $dt2): int {
|
||||
$diff = -1;
|
||||
|
||||
if ($dt2 !== null) {
|
||||
$dt1 = date('Y-m-d');
|
||||
$dt1 = new \DateTime($dt1);
|
||||
$dt2 = new \DateTime($dt2);
|
||||
$diff = $dt1->diff($dt2)->format('%a');
|
||||
}
|
||||
|
||||
return $diff;
|
||||
}
|
||||
|
||||
private function getDaysDiff(?string $dt1, ?string $dt2): int {
|
||||
$diff = -1;
|
||||
|
||||
if ($dt2) {
|
||||
$dt1 = new \DateTime($dt1);
|
||||
$dt2 = new \DateTime($dt2);
|
||||
$diff = $dt1->diff($dt2)->format('%a');
|
||||
}
|
||||
|
||||
return $diff;
|
||||
}
|
||||
|
||||
private function getUserFullName(array $record): string {
|
||||
$name = [];
|
||||
$fName = $record['ea_firstname'] ?? '';
|
||||
if ($fName) {
|
||||
$name[] = $fName;
|
||||
}
|
||||
|
||||
$lName = $record['ea_lastname'] ?? '';
|
||||
if ($lName) {
|
||||
$name[] = $lName;
|
||||
}
|
||||
|
||||
return trim(join(' ', $name));
|
||||
}
|
||||
|
||||
private function checkEmailForSuspiciousString(array $record): bool {
|
||||
foreach ($this->suspiciousWordsEmail as $sub) {
|
||||
if (stripos($record['le_email'], $sub) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function filterStringNum(array $record): array {
|
||||
return array_filter($record, static function ($value): bool {
|
||||
return is_string($value) || is_int($value);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class Device extends Base {
|
||||
public function getContext(array $accountIds, int $apiKey): array {
|
||||
$record = $this->getDetails($accountIds, $apiKey);
|
||||
$recordByAccount = $this->groupRecordsByAccount($record);
|
||||
|
||||
foreach ($recordByAccount as $key => $value) {
|
||||
$recordByAccount[$key] = [
|
||||
'eup_device' => array_column($value, 'eup_device'),
|
||||
'eup_device_id' => array_column($value, 'eup_device_id'),
|
||||
'eup_browser_name' => array_column($value, 'eup_browser_name'),
|
||||
'eup_browser_version' => array_column($value, 'eup_browser_version'),
|
||||
'eup_os_name' => array_column($value, 'eup_os_name'),
|
||||
'eup_lang' => array_column($value, 'eup_lang'),
|
||||
'eup_ua' => array_column($value, 'eup_ua'),
|
||||
// 'eup_lastseen' => array_column($value, 'eup_lastseen'),
|
||||
// 'eup_created' => array_column($value, 'eup_created'),
|
||||
];
|
||||
}
|
||||
|
||||
return $recordByAccount;
|
||||
}
|
||||
|
||||
protected function getDetails(array $accountIds, int $apiKey): array {
|
||||
[$params, $placeHolders] = $this->getRequestParams($accountIds, $apiKey);
|
||||
|
||||
$query = (
|
||||
"SELECT
|
||||
event_device.account_id AS accountid,
|
||||
event_device.id AS eup_device_id,
|
||||
event_ua_parsed.device AS eup_device,
|
||||
event_ua_parsed.browser_name AS eup_browser_name,
|
||||
event_ua_parsed.browser_version AS eup_browser_version,
|
||||
event_ua_parsed.os_name AS eup_os_name,
|
||||
event_ua_parsed.ua AS eup_ua,
|
||||
-- event_device.lastseen AS eup_lastseen,
|
||||
-- event_device.created AS eup_created,
|
||||
event_device.lang AS eup_lang
|
||||
|
||||
FROM
|
||||
event_device
|
||||
|
||||
INNER JOIN event_ua_parsed
|
||||
ON(event_device.user_agent=event_ua_parsed.id)
|
||||
|
||||
WHERE
|
||||
event_device.key = :api_key
|
||||
AND event_ua_parsed.checked = true
|
||||
AND event_device.account_id IN ({$placeHolders})"
|
||||
);
|
||||
|
||||
return $this->execQuery($query, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class Domain extends Base {
|
||||
public function getContext(array $accountIds, int $apiKey): array {
|
||||
$records = $this->getDetails($accountIds, $apiKey);
|
||||
$recordsByAccount = $this->groupRecordsByAccount($records);
|
||||
|
||||
foreach ($recordsByAccount as $key => $value) {
|
||||
$recordsByAccount[$key] = [
|
||||
'ed_domain' => $this->getUniqueArray(array_column($value, 'ed_domain')),
|
||||
'ed_blockdomains' => $this->getUniqueArray(array_column($value, 'ed_blockdomains')),
|
||||
'ed_disposable_domains' => $this->getUniqueArray(array_column($value, 'ed_disposable_domains')),
|
||||
'ed_free_email_provider' => $this->getUniqueArray(array_column($value, 'ed_free_email_provider')),
|
||||
'ed_creation_date' => $this->getUniqueArray(array_column($value, 'ed_creation_date')),
|
||||
'ed_disabled' => $this->getUniqueArray(array_column($value, 'ed_disabled')),
|
||||
'ed_mx_record' => $this->getUniqueArray(array_column($value, 'ed_mx_record')),
|
||||
];
|
||||
}
|
||||
|
||||
return $recordsByAccount;
|
||||
}
|
||||
|
||||
protected function getDetails(array $accountIds, int $apiKey): array {
|
||||
[$params, $placeHolders] = $this->getRequestParams($accountIds, $apiKey);
|
||||
|
||||
$query = (
|
||||
"SELECT
|
||||
event_email.account_id AS accountid,
|
||||
event_domain.domain AS ed_domain,
|
||||
event_domain.blockdomains AS ed_blockdomains,
|
||||
event_domain.disposable_domains AS ed_disposable_domains,
|
||||
event_domain.free_email_provider AS ed_free_email_provider,
|
||||
event_domain.creation_date AS ed_creation_date,
|
||||
event_domain.disabled AS ed_disabled,
|
||||
event_domain.mx_record AS ed_mx_record
|
||||
|
||||
FROM
|
||||
event_domain
|
||||
|
||||
INNER JOIN event_email
|
||||
ON event_domain.id = event_email.domain
|
||||
|
||||
WHERE
|
||||
event_email.key = :api_key
|
||||
AND event_email.account_id IN ({$placeHolders})"
|
||||
);
|
||||
|
||||
return $this->execQuery($query, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class Email extends Base {
|
||||
public function getContext(array $accountIds, int $apiKey): array {
|
||||
$records = $this->getDetails($accountIds, $apiKey);
|
||||
$recordsByAccount = $this->groupRecordsByAccount($records);
|
||||
|
||||
foreach ($recordsByAccount as $key => $value) {
|
||||
$recordsByAccount[$key] = [
|
||||
'ee_email' => $this->getUniqueArray(array_column($value, 'ee_email')),
|
||||
'ee_earliest_breach' => $this->getUniqueArray(array_column($value, 'ee_earliest_breach')),
|
||||
];
|
||||
}
|
||||
|
||||
return $recordsByAccount;
|
||||
}
|
||||
|
||||
protected function getDetails(array $accountIds, int $apiKey): array {
|
||||
[$params, $placeHolders] = $this->getRequestParams($accountIds, $apiKey);
|
||||
|
||||
$query = (
|
||||
"SELECT
|
||||
event_email.account_id AS accountid,
|
||||
event_email.email AS ee_email,
|
||||
event_email.earliest_breach AS ee_earliest_breach
|
||||
FROM
|
||||
event_email
|
||||
|
||||
WHERE
|
||||
event_email.key = :api_key
|
||||
AND event_email.checked = 'True'
|
||||
AND event_email.account_id IN ({$placeHolders})"
|
||||
);
|
||||
|
||||
return $this->execQuery($query, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class Event extends Base {
|
||||
public function getContext(array $accountIds, int $apiKey): array {
|
||||
$records = $this->getDetails($accountIds, $apiKey);
|
||||
$recordsByAccount = $this->groupRecordsByAccount($records);
|
||||
|
||||
foreach ($recordsByAccount as $key => $value) {
|
||||
$recordsByAccount[$key] = [
|
||||
'event_ip' => array_column($value, 'event_ip'),
|
||||
'event_url_string' => array_column($value, 'event_url_string'),
|
||||
'event_empty_referer' => array_column($value, 'event_empty_referer'),
|
||||
'event_device' => array_column($value, 'event_device'),
|
||||
'event_type' => array_column($value, 'event_type'),
|
||||
'event_http_code' => array_column($value, 'event_http_code'),
|
||||
'event_device_created' => array_column($value, 'event_device_created'),
|
||||
'event_device_lastseen' => array_column($value, 'event_device_lastseen'),
|
||||
'event_http_method' => array_column($value, 'event_http_method'),
|
||||
];
|
||||
}
|
||||
|
||||
return $recordsByAccount;
|
||||
}
|
||||
|
||||
protected function getDetails(array $accountIds, int $apiKey): array {
|
||||
[$params, $placeHolders] = $this->getRequestParams($accountIds, $apiKey);
|
||||
$contextLimit = \Utils\Constants::get('RULE_EVENT_CONTEXT_LIMIT');
|
||||
|
||||
$query = (
|
||||
"WITH ranked_events AS (
|
||||
SELECT
|
||||
event.account AS accountid,
|
||||
event.id AS event_id,
|
||||
event.ip AS event_ip,
|
||||
event_url.url AS event_url_string,
|
||||
event_referer.referer AS event_referer_string,
|
||||
event.device AS event_device,
|
||||
event.time AS event_time,
|
||||
event.type AS event_type,
|
||||
event.http_code AS event_http_code,
|
||||
event.http_method AS event_http_method,
|
||||
ROW_NUMBER() OVER (PARTITION BY event.account ORDER BY event.time DESC) AS rn
|
||||
FROM event
|
||||
LEFT JOIN event_url ON event_url.id = event.url
|
||||
LEFT JOIN event_referer ON event_referer.id = event.referer
|
||||
WHERE event.key = :api_key
|
||||
AND event.account IN ({$placeHolders})
|
||||
)
|
||||
SELECT
|
||||
accountid,
|
||||
event_ip,
|
||||
event_url_string,
|
||||
(event_referer_string IS NULL OR event_referer_string = '') AS event_empty_referer,
|
||||
event_device,
|
||||
ed.created AS event_device_created,
|
||||
ed.lastseen AS event_device_lastseen,
|
||||
event_type,
|
||||
event_http_code,
|
||||
event_http_method
|
||||
FROM ranked_events
|
||||
LEFT JOIN event_device AS ed
|
||||
ON ranked_events.event_device = ed.id
|
||||
WHERE rn <= {$contextLimit}
|
||||
ORDER BY event_time DESC;"
|
||||
);
|
||||
|
||||
return $this->execQuery($query, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class Ip extends Base {
|
||||
public function getContext(array $accountIds, int $apiKey): array {
|
||||
$records = $this->getDetails($accountIds, $apiKey);
|
||||
$recordsByAccount = $this->groupRecordsByAccount($records);
|
||||
|
||||
foreach ($recordsByAccount as $key => $value) {
|
||||
$recordsByAccount[$key] = [
|
||||
'eip_ip_id' => array_column($value, 'eip_ip_id'),
|
||||
'eip_ip' => array_column($value, 'eip_ip'),
|
||||
'eip_cidr' => array_column($value, 'eip_cidr'),
|
||||
'eip_data_center' => array_column($value, 'eip_data_center'),
|
||||
'eip_tor' => array_column($value, 'eip_tor'),
|
||||
'eip_vpn' => array_column($value, 'eip_vpn'),
|
||||
'eip_relay' => array_column($value, 'eip_relay'),
|
||||
'eip_starlink' => array_column($value, 'eip_starlink'),
|
||||
'eip_total_visit' => array_column($value, 'eip_total_visit'),
|
||||
'eip_blocklist' => array_column($value, 'eip_blocklist'),
|
||||
'eip_shared' => array_column($value, 'eip_shared'),
|
||||
//'eip_domains' => $this->getUniqueArray(array_column($value, 'eip_domains')),
|
||||
'eip_domains_count_len' => array_column($value, 'eip_domains_count_len'),
|
||||
'eip_country_id' => array_column($value, 'eip_country_id'),
|
||||
'eip_fraud_detected' => array_column($value, 'eip_fraud_detected'),
|
||||
'eip_alert_list' => array_column($value, 'eip_alert_list'),
|
||||
];
|
||||
}
|
||||
|
||||
return $recordsByAccount;
|
||||
}
|
||||
|
||||
protected function getDetails(array $accountIds, int $apiKey): array {
|
||||
[$params, $placeHolders] = $this->getRequestParams($accountIds, $apiKey);
|
||||
|
||||
$query = (
|
||||
"SELECT DISTINCT
|
||||
event.account AS accountid,
|
||||
|
||||
event_ip.id AS eip_ip_id,
|
||||
event_ip.ip AS eip_ip,
|
||||
event_ip.cidr::text AS eip_cidr,
|
||||
event_ip.country AS eip_country_id,
|
||||
event_ip.data_center AS eip_data_center,
|
||||
event_ip.tor AS eip_tor,
|
||||
event_ip.vpn AS eip_vpn,
|
||||
event_ip.relay AS eip_relay,
|
||||
event_ip.starlink AS eip_starlink,
|
||||
event_ip.total_visit AS eip_total_visit,
|
||||
event_ip.blocklist AS eip_blocklist,
|
||||
event_ip.shared AS eip_shared,
|
||||
-- event_ip.domains_count AS eip_domains,
|
||||
json_array_length(event_ip.domains_count::json) AS eip_domains_count_len,
|
||||
event_ip.fraud_detected AS eip_fraud_detected,
|
||||
event_ip.alert_list AS eip_alert_list
|
||||
|
||||
FROM
|
||||
event_ip
|
||||
|
||||
INNER JOIN event
|
||||
ON (event_ip.id = event.ip)
|
||||
|
||||
WHERE
|
||||
event_ip.key = :api_key
|
||||
AND event_ip.checked = 'True'
|
||||
AND event.account IN ({$placeHolders})
|
||||
|
||||
-- ORDER BY event_ip.id DESC"
|
||||
);
|
||||
|
||||
if (count($accountIds) === 1) {
|
||||
$query .= ' LIMIT 100 OFFSET 0';
|
||||
}
|
||||
|
||||
return $this->execQuery($query, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class Phone extends Base {
|
||||
public function getContext(array $accountIds, int $apiKey): array {
|
||||
$records = $this->getDetails($accountIds, $apiKey);
|
||||
$recordsByAccount = $this->groupRecordsByAccount($records);
|
||||
|
||||
foreach ($recordsByAccount as $key => $value) {
|
||||
$recordsByAccount[$key] = [
|
||||
//'ep_calling_country_code' => $this->getUniqueArray(array_column($value, 'ep_calling_country_code')),
|
||||
//'ep_carrier_name' => $this->getUniqueArray(array_column($value, 'ep_carrier_name')),
|
||||
//'ep_checked' => $this->getUniqueArray(array_column($value, 'ep_checked')),
|
||||
//'ep_country_code' => $this->getUniqueArray(array_column($value, 'ep_country_code')),
|
||||
//'ep_created' => $this->getUniqueArray(array_column($value, 'ep_created')),
|
||||
//'ep_lastseen' => $this->getUniqueArray(array_column($value, 'ep_lastseen')),
|
||||
//'ep_mobile_country_code' => $this->getUniqueArray(array_column($value, 'ep_mobile_country_code')),
|
||||
//'ep_mobile_network_code' => $this->getUniqueArray(array_column($value, 'ep_mobile_network_code')),
|
||||
//'ep_national_format' => $this->getUniqueArray(array_column($value, 'ep_national_format')),
|
||||
'ep_phone_number' => $this->getUniqueArray(array_column($value, 'ep_phone_number')),
|
||||
'ep_shared' => $this->getUniqueArray(array_column($value, 'ep_shared')),
|
||||
'ep_type' => $this->getUniqueArray(array_column($value, 'ep_type')),
|
||||
//'ep_invalid' => $this->getUniqueArray(array_column($value, 'ep_invalid')),
|
||||
//'ep_validation_errors' => $this->getUniqueArray(array_column($value, 'ep_validation_errors')),
|
||||
//'ep_alert_list' => $this->getUniqueArray(array_column($value, 'ep_alert_list')),
|
||||
];
|
||||
}
|
||||
|
||||
return $recordsByAccount;
|
||||
}
|
||||
|
||||
protected function getDetails(array $accountIds, int $apiKey): array {
|
||||
[$params, $placeHolders] = $this->getRequestParams($accountIds, $apiKey);
|
||||
|
||||
$query = (
|
||||
"SELECT
|
||||
event_phone.account_id AS accountid,
|
||||
|
||||
-- event_phone.calling_country_code AS ep_calling_country_code,
|
||||
-- event_phone.carrier_name AS ep_carrier_name,
|
||||
-- event_phone.checked AS ep_checked,
|
||||
-- event_phone.country_code AS ep_country_code,
|
||||
-- event_phone.created AS ep_created,
|
||||
-- event_phone.lastseen AS ep_lastseen,
|
||||
-- event_phone.mobile_country_code AS ep_mobile_country_code,
|
||||
-- event_phone.mobile_network_code AS ep_mobile_network_code,
|
||||
-- event_phone.national_format AS ep_national_format,
|
||||
event_phone.phone_number AS ep_phone_number,
|
||||
event_phone.shared AS ep_shared,
|
||||
event_phone.type AS ep_type
|
||||
-- event_phone.invalid AS ep_invalid,
|
||||
-- event_phone.validation_errors AS ep_validation_errors,
|
||||
-- event_phone.alert_list AS ep_alert_list
|
||||
|
||||
FROM
|
||||
event_phone
|
||||
|
||||
WHERE
|
||||
event_phone.key = :api_key
|
||||
AND event_phone.account_id IN ({$placeHolders})"
|
||||
);
|
||||
|
||||
return $this->execQuery($query, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class Session extends Base {
|
||||
public function getContext(array $accountIds, int $apiKey, int $timezoneOffset = 0): array {
|
||||
$records = $this->getDetails($accountIds, $apiKey, $timezoneOffset);
|
||||
// one record per account
|
||||
$recordsByAccount = $this->groupRecordsByAccount($records);
|
||||
|
||||
return $recordsByAccount;
|
||||
}
|
||||
|
||||
protected function getDetails(array $accountIds, int $apiKey, int $timezoneOffset = 0): array {
|
||||
[$params, $placeHolders] = $this->getRequestParams($accountIds, $apiKey);
|
||||
|
||||
$params[':night_start'] = gmdate('H:i:s', \Utils\Constants::get('NIGHT_RANGE_SECONDS_START') - $timezoneOffset);
|
||||
$params[':night_end'] = gmdate('H:i:s', \Utils\Constants::get('NIGHT_RANGE_SECONDS_END') - $timezoneOffset);
|
||||
|
||||
// boolean logic for defining time ranges overlap
|
||||
$query = (
|
||||
"SELECT
|
||||
event_session.account_id AS accountid,
|
||||
BOOL_OR(event_session.total_country > 1) AS event_session_multiple_country,
|
||||
BOOL_OR(event_session.total_ip > 1) AS event_session_multiple_ip,
|
||||
BOOL_OR(event_session.total_device > 1) AS event_session_multiple_device,
|
||||
BOOL_OR(
|
||||
(event_session.lastseen - event_session.created) > INTERVAL '1 day' OR
|
||||
(
|
||||
CASE WHEN :night_start::time < :night_end::time
|
||||
THEN
|
||||
(event_session.lastseen::time >= :night_start::time AND event_session.lastseen::time <= :night_end::time) OR
|
||||
(event_session.created::time >= :night_start::time AND event_session.created::time <= :night_end::time) OR
|
||||
(
|
||||
CASE WHEN event_session.lastseen::time > event_session.created::time
|
||||
THEN
|
||||
event_session.total_visit > 1 AND :night_start::time >= event_session.created::time AND :night_start::time <= event_session.lastseen::time
|
||||
ELSE
|
||||
event_session.total_visit > 1 AND (:night_start::time >= event_session.created::time OR :night_start::time <= event_session.lastseen::time)
|
||||
END
|
||||
)
|
||||
ELSE
|
||||
event_session.lastseen::time >= :night_start::time OR event_session.lastseen::time <= :night_end::time OR
|
||||
event_session.created::time >= :night_start::time OR event_session.created::time <= :night_end::time OR
|
||||
event_session.lastseen::time < event_session.created::time
|
||||
END
|
||||
)) AS event_session_night_time
|
||||
FROM
|
||||
event_session
|
||||
WHERE
|
||||
event_session.key = :api_key AND
|
||||
event_session.account_id IN ({$placeHolders})
|
||||
GROUP BY event_session.account_id"
|
||||
);
|
||||
|
||||
return $this->execQuery($query, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?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 Models\Context;
|
||||
|
||||
class User extends Base {
|
||||
use \Traits\Enrichment\Emails;
|
||||
|
||||
public function getContext(array $accountIds, int $apiKey): array {
|
||||
$results = $this->getDetails($accountIds, $apiKey);
|
||||
|
||||
$this->calculateEmailReputationForContext($results);
|
||||
|
||||
$recordsByAccount = [];
|
||||
foreach ($results as $item) {
|
||||
$recordsByAccount[$item['ea_id']] = $item;
|
||||
}
|
||||
|
||||
return $recordsByAccount;
|
||||
}
|
||||
|
||||
protected function getDetails(array $accountIds, int $apiKey): array {
|
||||
[$params, $placeHolders] = $this->getRequestParams($accountIds, $apiKey);
|
||||
|
||||
$query = (
|
||||
"SELECT
|
||||
event_account.id AS ea_id,
|
||||
event_account.userid AS ea_userid,
|
||||
event_account.created AS ea_created,
|
||||
event_account.lastseen AS ea_lastseen,
|
||||
event_account.total_visit AS ea_total_visit,
|
||||
event_account.total_country AS ea_total_country,
|
||||
event_account.total_ip AS ea_total_ip,
|
||||
event_account.total_device AS ea_total_device,
|
||||
event_account.firstname AS ea_firstname,
|
||||
event_account.lastname AS ea_lastname,
|
||||
|
||||
event_email.email AS ee_email,
|
||||
event_email.blockemails AS ee_blockemails,
|
||||
event_email.data_breach AS ee_data_breach,
|
||||
-- event_email.profiles AS ee_profiles,
|
||||
event_email.checked AS ee_checked,
|
||||
|
||||
event_domain.discovery_date AS ed_discovery_date,
|
||||
event_domain.blockdomains AS ed_blockdomains,
|
||||
event_domain.disposable_domains AS ed_disposable_domains,
|
||||
-- event_domain.total_account AS ed_total_account,
|
||||
event_domain.free_email_provider AS ed_free_provider,
|
||||
event_domain.tranco_rank AS ed_tranco_rank,
|
||||
event_domain.creation_date AS ed_creation_date,
|
||||
event_domain.expiration_date AS ed_expiration_date,
|
||||
event_domain.return_code AS ed_return_code,
|
||||
event_domain.closest_snapshot AS ed_closest_snapshot,
|
||||
event_domain.mx_record AS ed_mx_record,
|
||||
|
||||
lastemail_record.email AS le_email,
|
||||
lastemail_record.blockemails AS le_blockemails,
|
||||
lastemail_record.data_breach AS le_data_breach,
|
||||
-- lastemail_record.profiles AS le_profiles,
|
||||
lastemail_record.checked AS le_checked,
|
||||
lastemail_record.fraud_detected AS le_fraud_detected,
|
||||
lastemail_record.alert_list AS le_alert_list,
|
||||
|
||||
lastdomain_record.disposable_domains AS ld_disposable_domains,
|
||||
lastdomain_record.free_email_provider AS ld_free_email_provider,
|
||||
lastdomain_record.blockdomains AS ld_blockdomains,
|
||||
lastdomain_record.mx_record AS ld_mx_record,
|
||||
lastdomain_record.disabled AS ld_disabled,
|
||||
lastdomain_record.creation_date AS ld_creation_date,
|
||||
lastdomain_record.tranco_rank AS ld_tranco_rank,
|
||||
|
||||
lastphone_record.phone_number AS lp_phone_number,
|
||||
lastphone_record.country_code AS lp_country_code,
|
||||
lastphone_record.invalid AS lp_invalid,
|
||||
lastphone_record.fraud_detected AS lp_fraud_detected,
|
||||
lastphone_record.alert_list AS lp_alert_list
|
||||
|
||||
FROM
|
||||
event_account
|
||||
|
||||
LEFT JOIN event_phone
|
||||
ON (event_account.id = event_phone.account_id)
|
||||
|
||||
LEFT JOIN event_email
|
||||
ON event_account.id = event_email.account_id
|
||||
|
||||
LEFT JOIN event_domain
|
||||
ON event_email.domain = event_domain.id
|
||||
|
||||
LEFT JOIN event_email AS lastemail_record
|
||||
ON event_account.lastemail = lastemail_record.id
|
||||
|
||||
LEFT JOIN event_phone AS lastphone_record
|
||||
ON event_account.lastphone = lastphone_record.id
|
||||
|
||||
LEFT JOIN event_domain AS lastdomain_record
|
||||
ON lastemail_record.domain = lastdomain_record.id
|
||||
|
||||
WHERE
|
||||
event_account.key = :api_key
|
||||
AND event_account.id IN ({$placeHolders})"
|
||||
);
|
||||
|
||||
return $this->execQuery($query, $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
Reference in New Issue
Block a user