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:
2025-10-30 11:43:06 -05:00
parent 0ce353ea9d
commit 91d52d2de5
1692 changed files with 202851 additions and 0 deletions

View File

@@ -0,0 +1,307 @@
<?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 Controllers\Admin\User;
class Data extends \Controllers\Base {
use \Traits\ApiKeys;
public function proceedPostRequest(array $params): array {
return match ($params['cmd']) {
'riskScore' => $this->recalculateRiskScore($params),
'reenrichment' => $this->enrichEntity($params),
'delete' => $this->deleteUser($params),
default => []
};
}
public function recalculateRiskScore(array $params): array {
$result = [];
set_error_handler([\Utils\ErrorHandler::class, 'exceptionErrorHandler']);
try {
$apiKey = $this->getCurrentOperatorApiKeyId();
$userId = (int) $params['accountid'];
[$score, $rules] = $this->getUserScore($userId, $apiKey);
$result = [
'SUCCESS_MESSAGE' => $this->f3->get('AdminUser_recalculate_risk_score_success_message'),
'score' => $score,
'rules' => $rules,
];
} catch (\ErrorException $e) {
$result = ['ERROR_CODE' => \Utils\ErrorCodes::RISK_SCORE_UPDATE_UNKNOWN_ERROR];
}
restore_error_handler();
return $result;
}
public function enrichEntity(array $params): array {
$dataController = new \Controllers\Admin\Enrichment\Data();
$apiKey = $this->getCurrentOperatorApiKeyId();
$enrichmentKey = $this->getCurrentOperatorEnrichmentKeyString();
$type = $params['type'];
$search = $params['search'] ?? null;
$entityId = isset($params['entityId']) ? (int) $params['entityId'] : null;
return $dataController->enrichEntity($type, $search, $entityId, $apiKey, $enrichmentKey);
}
public function deleteUser(array $params): void {
$apiKey = $this->getCurrentOperatorApiKeyId();
if ($apiKey) {
$accountId = (int) $params['accountid'];
$actionType = new \Type\QueueAccountOperationActionType(\Type\QueueAccountOperationActionType::DELETE);
$accountOpQueueModel = new \Models\Queue\AccountOperationQueue($actionType);
$code = \Utils\ErrorCodes::REST_API_USER_ALREADY_SCHEDULED_FOR_DELETION;
if (!$accountOpQueueModel->isInQueue($accountId, $apiKey)) {
$code = \Utils\ErrorCodes::REST_API_USER_SUCCESSFULLY_ADDED_FOR_DELETION;
$accountOpQueueModel->add($accountId, $apiKey);
}
$this->f3->set('SESSION.extra_message_code', $code);
$this->f3->reroute('/id');
}
}
public function getUserScoreDetails(int $userId, int $apiKey): array {
$model = new \Models\User();
$user = $model->getUser($userId, $apiKey);
return [
'score_details' => $model->getApplicableRulesByAccountId($userId, $apiKey, true),
'score_calculated' => $user !== [] ? $user['score'] !== null : false,
];
}
public function getUserById(int $accountId): array {
$apiKey = $this->getCurrentOperatorApiKeyId();
$model = new \Models\User();
$user = $model->getUser($accountId, $apiKey);
$model = new \Models\Rules();
$rules = $model->getAll();
$details = [];
if ($user['score_details']) {
$scoreDetails = json_decode($user['score_details'], true);
foreach ($scoreDetails as $detail) {
$score = $detail['score'] ?? null;
$ruleUid = $detail['uid'] ?? null;
if ($score !== 0 && isset($rules[$ruleUid])) {
$item = $rules[$ruleUid];
$item['score'] = $score;
$details[] = $item;
}
}
}
usort($details, static function ($a, $b): int {
return $b['score'] <=> $a['score'];
});
$user['score_details'] = $details;
$pageTitle = $user['userid'];
if ($user['firstname'] !== null && $user['firstname'] !== '') {
$pageTitle .= sprintf(' (%s)', $user['firstname']);
}
if ($user['lastname'] !== null && $user['lastname'] !== '') {
$pageTitle .= sprintf(' (%s)', $user['lastname']);
}
$user['page_title'] = $pageTitle;
$tsColumns = ['created', 'lastseen', 'score_updated_at', 'latest_decision', 'updated', 'added_to_review'];
\Utils\TimeZones::localizeTimestampsForActiveOperator($tsColumns, $user);
return $user;
}
public function checkIfOperatorHasAccess(int $userId): bool {
$apiKey = $this->getCurrentOperatorApiKeyId();
$userModel = new \Models\User();
return $userModel->checkAccess($userId, $apiKey);
}
public function checkEnrichmentAvailability(): bool {
return $this->getCurrentOperatorEnrichmentKeyString() !== null;
}
public function addToWatchlist(int $accountId, int $apiKey): void {
$model = new \Models\Watchlist();
$model->add($accountId, $apiKey);
}
public function removeFromWatchlist(int $accountId, int $apiKey): void {
$model = new \Models\Watchlist();
$model->remove($accountId, $apiKey);
}
public function addToBlacklistQueue(int $accountId, bool $fraud, int $apiKey): void {
$actionType = new \Type\QueueAccountOperationActionType(\Type\QueueAccountOperationActionType::BLACKLIST);
$accountOpQueueModel = new \Models\Queue\AccountOperationQueue($actionType);
$inQueue = $accountOpQueueModel->isInQueue($accountId, $apiKey);
if (!$fraud) {
$this->setFraudFlag($accountId, false, $apiKey); // Directly remove blacklisted items
if ($inQueue) {
$accountOpQueueModel->removeFromQueue(); // Cancel queued operation
}
}
if (!$inQueue && $fraud) {
$accountOpQueueModel->add($accountId, $apiKey);
}
$model = new \Models\User();
$model->updateFraudFlag([$accountId], $apiKey, $fraud);
}
public function addToCalulcateRiskScoreQueue(int $accountId): void {
$apiKey = $this->getCurrentOperatorApiKeyObject();
$actionType = new \Type\QueueAccountOperationActionType(\Type\QueueAccountOperationActionType::CALCULATE_RISK_SCORE);
$accountOpQueueModel = new \Models\Queue\AccountOperationQueue($actionType);
$inQueue = $accountOpQueueModel->isInQueue($accountId, $apiKey->id);
if (!$inQueue) {
$accountOpQueueModel->add($accountId, $apiKey->id);
}
}
/**
* @param array{accountId: int, key: int}[] $accounts
*/
public function addBatchToCalulcateRiskScoreQueue(array $accounts): void {
$actionType = new \Type\QueueAccountOperationActionType(\Type\QueueAccountOperationActionType::CALCULATE_RISK_SCORE);
$accountOpQueueModel = new \Models\Queue\AccountOperationQueue($actionType);
$accountOpQueueModel->addBatch($accounts);
}
public function setReviewedFlag(int $accountId, bool $reviewed, int $apiKey): void {
$model = new \Models\User();
$model->updateReviewedFlag($accountId, $apiKey, $reviewed);
}
public function getUserScore(int $accountId, int $apiKey): array {
$total = 0;
$rules = [];
$rulesController = new \Controllers\Admin\Rules\Data();
$rulesController->evaluateUser($accountId, $apiKey);
$model = new \Models\User();
$rules = $model->getApplicableRulesByAccountId($accountId, $apiKey);
$total = $rules[0]['total_score'] ?? 0;
array_walk($rules, function (&$rule): void {
unset($rule['total_score']);
}, $rules);
return [$total, $rules];
}
public function validate(int $accountId, array $params): int|false {
$errorCode = \Utils\Access::CSRFTokenValid($params, $this->f3);
if ($errorCode) {
return $errorCode;
}
$userHasAccess = $this->checkIfOperatorHasAccess($accountId);
return !$userHasAccess ? \Utils\ErrorCodes::OPERATOR_DOES_NOT_HAVE_ACCESS_TO_ACCOUNT : false;
}
public function getScheduledForDeletion(int $userId): array {
$apiKey = $this->getCurrentOperatorApiKeyId();
$actionType = new \Type\QueueAccountOperationActionType(\Type\QueueAccountOperationActionType::DELETE);
$accountOpQueueModel = new \Models\Queue\AccountOperationQueue($actionType);
[$scheduled, $status] = $accountOpQueueModel->isInQueueStatus($userId, $apiKey);
return [$scheduled, ($status === \Type\QueueAccountOperationStatusType::FAILED) ? \Utils\ErrorCodes::USER_DELETION_FAILED : null];
}
public function getScheduledForBlacklist(int $userId): array {
$apiKey = $this->getCurrentOperatorApiKeyId();
$actionType = new \Type\QueueAccountOperationActionType(\Type\QueueAccountOperationActionType::BLACKLIST);
$accountOpQueueModel = new \Models\Queue\AccountOperationQueue($actionType);
[$scheduled, $status] = $accountOpQueueModel->isInQueueStatus($userId, $apiKey);
return [$scheduled, ($status === \Type\QueueAccountOperationStatusType::FAILED) ? \Utils\ErrorCodes::USER_BLACKLISTING_FAILED : null];
}
public function setFraudFlag(int $accountId, bool $fraud, int $apiKey): array {
$blacklistItemsModel = new \Models\BlacklistItems();
$ips = $blacklistItemsModel->getIpsRelatedToAccountWithinOperator($accountId, $apiKey);
$emails = $blacklistItemsModel->getEmailsRelatedToAccountWithinOperator($accountId, $apiKey);
$phones = $blacklistItemsModel->getPhonesRelatedToAccountWithinOperator($accountId, $apiKey);
$relatedIpsIds = array_column($ips, 'id');
$relatedEmailsIds = array_column($emails, 'id');
$relatedPhonesIds = array_column($phones, 'id');
$ips = $blacklistItemsModel->getIpsRelatedToAccountWithinOperator($accountId, $apiKey);
$relatedIpsIds = array_column($ips, 'id');
if (count($relatedIpsIds) !== 0) {
$model = new \Models\Ip();
$model->updateFraudFlag($relatedIpsIds, $fraud, $apiKey);
}
$emails = $blacklistItemsModel->getEmailsRelatedToAccountWithinOperator($accountId, $apiKey);
$relatedEmailsIds = array_column($emails, 'id');
if (count($relatedEmailsIds) !== 0) {
$model = new \Models\Email();
$model->updateFraudFlag($relatedEmailsIds, $fraud, $apiKey);
}
$phones = $blacklistItemsModel->getPhonesRelatedToAccountWithinOperator($accountId, $apiKey);
$relatedPhonesIds = array_column($phones, 'id');
if (count($relatedPhonesIds) !== 0) {
$model = new \Models\Phone();
$model->updateFraudFlag($relatedPhonesIds, $fraud, $apiKey);
}
return array_merge($ips, $emails, $phones);
}
public function updateUserStatus(int $accountId, array $scoreData, int $apiKey): void {
$scoreData['addToReview'] = false;
$keyModel = new \Models\ApiKeys();
$keyModel->getKeyById($apiKey);
$userModel = new \Models\User();
if ($scoreData['score'] <= $keyModel->blacklist_threshold) {
$this->addToBlacklistQueue($accountId, true, $apiKey);
} elseif ($scoreData['score'] <= $keyModel->review_queue_threshold) {
$data = $userModel->getUser($accountId, $apiKey);
$scoreData['addToReview'] = $data['added_to_review'] === null && $data['fraud'] === null;
}
$userModel->updateUserStatus($accountId, $scoreData, $apiKey);
}
}