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,142 @@
<?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\Api;
abstract class Endpoint {
use \Traits\Db;
use \Traits\Debug;
public const API_KEY = 'Api-Key';
protected $f3;
protected \Views\Json $response;
protected \Type\ResponseType $responseType;
protected int $error;
protected array $validationErrors = [];
private string $apiKeyString;
protected \Models\ApiKeys $apiKey;
protected \Interfaces\ApiKeyAccessAuthorizationInterface $authorizationModel;
private array $body = [];
protected array|null $data = null;
public function __construct() {
$this->f3 = \Base::instance();
$this->f3->set('ONERROR', function (): void {
$this->handleInternalServerError();
});
$this->connectToDb(false);
$this->response = new \Views\Json();
$this->responseType = new \Type\ResponseType(\Type\ResponseType::SINGLE);
}
public function beforeRoute(): void {
$this->identify();
$this->authenticate();
$this->parseBody();
}
public function afterRoute(): void {
if (isset($this->error)) {
$errorI18nCode = sprintf('error_%s', $this->error);
$errorMessage = $this->f3->get($errorI18nCode);
$this->response->data = [
'code' => $this->error,
'message' => $errorMessage,
];
$this->data = null;
}
if (($this->data !== null)) {
$this->response->data = $this->data;
}
echo $this->response->render();
}
protected function identify(): void {
$headers = $this->f3->get('HEADERS') ?? [];
if (array_key_exists(self::API_KEY, $headers) && is_string($headers[self::API_KEY])) {
$this->apiKeyString = $headers[self::API_KEY];
return;
}
$this->setError(400, \Utils\ErrorCodes::REST_API_KEY_DOES_NOT_EXIST);
}
protected function authenticate(): void {
$model = new \Models\ApiKeys();
$apiKey = $model->getKeyIdByHash($this->apiKeyString);
if ($apiKey) {
$this->apiKey = $apiKey;
return;
}
$this->setError(401, \Utils\ErrorCodes::REST_API_KEY_IS_NOT_CORRECT);
}
protected function authorize(string $subjectId): void {
if (!isset($this->apiKey) || isset($this->error)) {
exit;
}
$apiKeyId = $this->apiKey->id;
$hasAccess = $this->authorizationModel->checkAccessByExternalId($subjectId, $apiKeyId);
if ($hasAccess) {
return;
}
$this->setError(403, \Utils\ErrorCodes::REST_API_NOT_AUTHORIZED);
}
protected function getBodyProp(string $key, string $paramType = 'string'): string|int|array|null {
$value = $this->body[$key] ?? null;
if (isset($value)) {
settype($value, $paramType);
}
return $value;
}
protected function setError(int $statusCode, int $errorCode): void {
$this->f3->status($statusCode);
$this->error = $errorCode;
$this->afterRoute();
exit;
}
private function parseBody(): void {
$body = $this->f3->get('BODY');
$this->body = json_decode($body, true) ?? [];
}
private function handleInternalServerError(): void {
$errorData = \Utils\ErrorHandler::getErrorDetails($this->f3);
\Utils\ErrorHandler::saveErrorInformation($this->f3, $errorData);
$this->setError(500, 500);
}
}