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,397 @@
|
||||
<?php
|
||||
|
||||
const MIN_PHP_VERSION = '8.0.0';
|
||||
const MIN_MEMORY_LIM = 128 * 1024 * 1024;
|
||||
|
||||
$logo = (
|
||||
' 888
|
||||
888 888
|
||||
888
|
||||
88888888 888 888.d88 888.d88 .d88b. 88.d8b. .d88b.
|
||||
888 888 888P" 888P" d8P Y8b 888 "88b d88""88b
|
||||
888 888 888 888 88888888 888 888 888 888
|
||||
888 888 888 888 Y8b .qq 888 888 888 888
|
||||
888 888 888 888 d8bddr 888 888 R88 88P');
|
||||
|
||||
$style = (
|
||||
'<style>
|
||||
body {
|
||||
background-color: #2b2a3d;
|
||||
color: #d7e6e1;
|
||||
font-family: monospace, monospace;
|
||||
padding: 50px;
|
||||
font-size: 13px;
|
||||
}
|
||||
input[type="text"],input[type="email"]{
|
||||
width: 550px;
|
||||
background-color: #151220;
|
||||
color: #d7e6e1;
|
||||
font-size: 100%;
|
||||
}
|
||||
label {
|
||||
text-align: right;
|
||||
display: block;
|
||||
}
|
||||
a {
|
||||
color: #6e9fff;
|
||||
}
|
||||
</style>');
|
||||
|
||||
$installerHead = '<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Installer</title>' . $style . '<head>';
|
||||
$okTile = '[ <span style="color: #01ee99;">OK</span> ]';
|
||||
$failTile = '[ <span style="color: #fb6e88;">FAIL</span> ]';
|
||||
$nullTile = '[ -- ]';
|
||||
$backButton = '<input action="action" onclick="window.history.go(-1); return false;" type="submit" value="Try again"/>';
|
||||
|
||||
$formBody = (
|
||||
'<body>
|
||||
<h3>Database connection details</h3>
|
||||
<form action="/install/index.php" method="post">
|
||||
<table width="688" cellpadding="5" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td><label for="db_user">Username</label></td>
|
||||
<td><input type="text" id="db-user" name="db_user" autocomplete="off" autocapitalize="off" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="db_pass">Password</label></td>
|
||||
<td><input type="text" id="db-pass" name="db_pass" autocomplete="off" autocapitalize="off" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="db_host">Host</label></td>
|
||||
<td><input type="text" id="db-host" name="db_host" autocomplete="off" autocapitalize="off" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="db_port">Port</label></td>
|
||||
<td><input type="text" id="db-port" name="db_port" autocomplete="off" autocapitalize="off" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="db_name">Database name</label></td>
|
||||
<td><input type="text" id="db-name" name="db_name" autocomplete="off" autocapitalize="off" required></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="admin_email">Admin email</label></td>
|
||||
<td><input type="email" id="admin-email" name="admin_email" autocomplete="off" autocapitalize="off"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<hr>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="submit" value="Connect"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>');
|
||||
|
||||
function resultHtmlStart() {
|
||||
global $installerHead, $logo;
|
||||
return $installerHead . '<body><pre>' . $logo;
|
||||
}
|
||||
|
||||
function resultHtmlEnd() {
|
||||
return '</pre></body></html>';
|
||||
}
|
||||
|
||||
function formHtml() {
|
||||
global $installerHead, $formBody;
|
||||
return $installerHead . $formBody . '</html>';
|
||||
}
|
||||
|
||||
function finishOk() {
|
||||
$out = "\n\n======================== Setup completed! ========================";
|
||||
$out .= "\n* Please delete the ./install directory and all its included files.";
|
||||
$out .= "\n* Visit <a href=\"/signup\">/signup</a> to create your account.";
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
function finishError() {
|
||||
global $backButton;
|
||||
|
||||
$out = "\n====================== Something went wrong ======================";
|
||||
$out .= "\n$backButton";
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
$steps = [
|
||||
[
|
||||
'description' => 'Compatibility checks',
|
||||
'tasks' => [
|
||||
['description' => 'PHP version', 'status' => null],
|
||||
['description' => 'PDO PostgreSQL driver', 'status' => null],
|
||||
['description' => 'Configuration folder (/config) read/write permission', 'status' => null],
|
||||
['description' => '.htaccess available', 'status' => null],
|
||||
['description' => 'cURL', 'status' => null],
|
||||
['description' => 'Memory limit (Min. 128MB)', 'status' => null],
|
||||
],
|
||||
],
|
||||
[
|
||||
'description' => 'Database params',
|
||||
'tasks' => [
|
||||
['description' => 'Schema accessible', 'status' => null],
|
||||
['description' => 'Database name', 'status' => null],
|
||||
['description' => 'Database user', 'status' => null],
|
||||
['description' => 'Database password', 'status' => null],
|
||||
['description' => 'Database host', 'status' => null],
|
||||
['description' => 'Database port', 'status' => null],
|
||||
],
|
||||
],
|
||||
[
|
||||
'description' => 'Database setup',
|
||||
'tasks' => [
|
||||
['description' => 'Database connection', 'status' => null],
|
||||
/*['description' => 'Database version', 'status' => null],*/
|
||||
['description' => 'Apply database schema', 'status' => null],
|
||||
],
|
||||
],
|
||||
[
|
||||
'description' => 'Config build',
|
||||
'tasks' => [
|
||||
['description' => 'Write config file', 'status' => null],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
function proceed() {
|
||||
$out = '';
|
||||
if (configAlreadyExists()) {
|
||||
$out .= resultHtmlStart();
|
||||
$out .= "\nThe app is already configured.";
|
||||
$out .= resultHtmlEnd();
|
||||
|
||||
echo $out;
|
||||
return;
|
||||
}
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$out .= resultHtmlStart();
|
||||
[$status, $result, $config] = execute($_POST);
|
||||
$out .= $result;
|
||||
$out .= $status ? finishOk() : finishError();
|
||||
$out .= resultHtmlEnd();
|
||||
} else {
|
||||
substituteFormWithEnv();
|
||||
$out .= formHtml();
|
||||
}
|
||||
|
||||
echo $out;
|
||||
}
|
||||
|
||||
function execute(array $values) {
|
||||
global $steps;
|
||||
|
||||
$out = '';
|
||||
|
||||
compatibilityCheck(0, $steps);
|
||||
$out .= printTasks($steps[0]);
|
||||
if (!tasksCompleted($steps[0])) {
|
||||
return [false, $out, null];
|
||||
}
|
||||
|
||||
dbConfig(1, $values, $steps);
|
||||
$out .= printTasks($steps[1]);
|
||||
if (!tasksCompleted($steps[1])) {
|
||||
return [false, $out, null];
|
||||
}
|
||||
|
||||
dbSaveConfig(2, $values, $steps);
|
||||
$out .= printTasks($steps[2]);
|
||||
if (!tasksCompleted($steps[2])) {
|
||||
return [false, $out, null];
|
||||
}
|
||||
|
||||
if (strval($values['mode'] ?? '') !== 'schema') {
|
||||
$config = saveConfig(3, $values, $steps);
|
||||
$out .= printTasks($steps[3]);
|
||||
if (!tasksCompleted($steps[3])) {
|
||||
return [false, $out, null];
|
||||
}
|
||||
}
|
||||
|
||||
return [true, $out, $config];
|
||||
}
|
||||
|
||||
function configAlreadyExists(): bool {
|
||||
return (getenv('SITE') && getenv('DATABASE_URL')) || file_exists('../config/local/config.local.ini');
|
||||
}
|
||||
|
||||
function substituteFormWithEnv(): void {
|
||||
global $formBody;
|
||||
|
||||
if (strval($_GET['mode'] ?? '') === 'schema') {
|
||||
$formBody = preg_replace(
|
||||
'/(<form\b[^>]*>)/i',
|
||||
'$1<input type="hidden" name="mode" value="schema">',
|
||||
$formBody
|
||||
);
|
||||
}
|
||||
|
||||
$dbUrl = getenv('DATABASE_URL');
|
||||
if ($dbUrl) {
|
||||
$parts = parse_url($dbUrl);
|
||||
if ($parts) {
|
||||
$values = [
|
||||
'db_user' => $parts['user'] ?? '',
|
||||
'db_pass' => $parts['pass'] ?? '',
|
||||
'db_host' => $parts['host'] ?? '',
|
||||
'db_port' => $parts['port'] ?? '',
|
||||
'db_name' => trim(($parts['path'] ?? ''), '/'),
|
||||
];
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$safe = htmlspecialchars($value, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8');
|
||||
$formBody = preg_replace(
|
||||
'/(<input\b[^>]*\bname="' . preg_quote($key, '/') . '"(?![^>]*\bvalue=)[^>]*)(>)/i',
|
||||
'$1 value="' . $safe . '"$2',
|
||||
$formBody
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compatibilityCheck(int $step, array &$steps) {
|
||||
$steps[$step]['tasks'][0]['status'] = version_compare(PHP_VERSION, MIN_PHP_VERSION) >= 0;
|
||||
$steps[$step]['tasks'][1]['status'] = extension_loaded('pdo_pgsql') && extension_loaded('pgsql');
|
||||
|
||||
try {
|
||||
if (is_writable('../config')) {
|
||||
$f = fopen('../config/local/config.local.ini', 'w');
|
||||
fclose($f);
|
||||
unlink('../config/local/config.local.ini');
|
||||
$steps[$step]['tasks'][2]['status'] = true;
|
||||
} else {
|
||||
$steps[$step]['tasks'][2]['status'] = false;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$steps[$step]['tasks'][2]['status'] = false;
|
||||
}
|
||||
|
||||
$steps[$step]['tasks'][3]['status'] = is_file('../.htaccess') && is_readable('../.htaccess');
|
||||
|
||||
$steps[$step]['tasks'][4]['status'] = extension_loaded('curl');
|
||||
|
||||
$memoryLimit = @ini_get('memory_limit');
|
||||
$memLim = $memoryLimit;
|
||||
preg_match('#^(\d+)(\w+)$#', strtolower($memLim), $match);
|
||||
$memLim = match ($match[2]) {
|
||||
'g' => intval($memLim) * 1024 * 1024 * 1024,
|
||||
'm' => intval($memLim) * 1024 * 1024,
|
||||
'k' => intval($memLim) * 1024,
|
||||
default => intval($memLim),
|
||||
};
|
||||
$steps[$step]['tasks'][5]['status'] = $memLim >= MIN_MEMORY_LIM;
|
||||
}
|
||||
|
||||
function dbConfig(int $step, array &$values, array &$steps) {
|
||||
$steps[$step]['tasks'][0]['status'] = is_file('./install.sql');
|
||||
|
||||
$steps[$step]['tasks'][1]['status'] = $values['db_name'] !== '';
|
||||
$steps[$step]['tasks'][2]['status'] = $values['db_user'] !== '';
|
||||
$steps[$step]['tasks'][3]['status'] = $values['db_pass'] !== '';
|
||||
$steps[$step]['tasks'][4]['status'] = $values['db_host'] !== '';
|
||||
$steps[$step]['tasks'][5]['status'] = $values['db_port'] !== '';
|
||||
}
|
||||
|
||||
function saveConfig(int $step, array $values, array &$steps): ?array {
|
||||
$configData = null;
|
||||
try {
|
||||
$httpHost = strtolower(filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL));
|
||||
if (strpos($httpHost, 'www.') === 0) {
|
||||
$httpHost = substr($httpHost, 4);
|
||||
} elseif (substr_count($httpHost, '.') == 1) {
|
||||
$httpHost = 'www.' . $httpHost;
|
||||
}
|
||||
$httpHost = explode(':', $httpHost)[0];
|
||||
|
||||
$configData = [
|
||||
'SITE' => $httpHost,
|
||||
'DATABASE_URL' => "postgres://$values[db_user]:$values[db_pass]@$values[db_host]:$values[db_port]/$values[db_name]",
|
||||
'PEPPER' => strval(bin2hex(random_bytes(32))),
|
||||
];
|
||||
if ($values['admin_email'] !== '') {
|
||||
$configData['ADMIN_EMAIL'] = $values['admin_email'];
|
||||
}
|
||||
|
||||
$config = "\n[globals]";
|
||||
foreach ($configData as $key => $value) {
|
||||
$config .= "\n$key=$value";
|
||||
}
|
||||
|
||||
$configPath = '../config/local/config.local.ini';
|
||||
$configFile = fopen($configPath, 'w');
|
||||
fwrite($configFile, $config);
|
||||
fclose($configFile);
|
||||
$steps[$step]['tasks'][0]['status'] = true;
|
||||
} catch (\Exception $e) {
|
||||
$steps[$step]['tasks'][0]['status'] = false;
|
||||
$steps[$step]['tasks'][0]['error'] = $e->getMessage();
|
||||
}
|
||||
|
||||
return $configData;
|
||||
}
|
||||
|
||||
function dbSaveConfig(int $step, array $values, array &$steps) {
|
||||
$database = null;
|
||||
|
||||
$dsn = "pgsql:dbname=$values[db_name];host=$values[db_host];port=$values[db_port]";
|
||||
$driverOptions = array(
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
|
||||
);
|
||||
|
||||
try {
|
||||
$database = new \PDO($dsn, $values['db_user'], $values['db_pass'], $driverOptions);
|
||||
} catch (\Exception $e) {
|
||||
$steps[$step]['tasks'][0]['status'] = false;
|
||||
$steps[$step]['tasks'][0]['error'] = $e->getMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
$steps[$step]['tasks'][0]['status'] = true;
|
||||
|
||||
/*$query = $database->query('SELECT VERSION()');
|
||||
[$dbVersion] = $query->fetch(\PDO::FETCH_NUM);
|
||||
if (!preg_match('/PostgreSQL (\d+\.\d+)/', $dbVersion, $matches) || version_compare($matches[1], '12.0', '<')) {
|
||||
$steps[$step]['tasks'][1]['status'] = false;
|
||||
return;
|
||||
}
|
||||
$steps[$step]['tasks'][1]['status'] = true;*/
|
||||
|
||||
try {
|
||||
$sql = file_get_contents('./install.sql');
|
||||
$database->exec($sql);
|
||||
} catch (\Exception $e) {
|
||||
$steps[$step]['tasks'][1]['status'] = false;
|
||||
$steps[$step]['tasks'][1]['error'] = $e->getMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
$steps[$step]['tasks'][1]['status'] = true;
|
||||
}
|
||||
|
||||
function printTasks(array $tasks) {
|
||||
global $okTile, $failTile, $nullTile;
|
||||
|
||||
$out = '';
|
||||
$side = intdiv(64 - strlen($tasks['description']), 2);
|
||||
$header = str_repeat('=', $side) . ' ' . $tasks['description'] . ' ' . str_repeat('=', $side);
|
||||
$out .= "\n\n" . $header;
|
||||
foreach ($tasks['tasks'] as $task) {
|
||||
$st = ($task['status'] === true) ? $okTile : (($task['status'] === false) ? $failTile : $nullTile);
|
||||
$err = array_key_exists('error', $task) ? ' (' . $task['error'] . ')' : '';
|
||||
$out .= "\n" . $st . ' ' . $task['description'] . $err;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
function tasksCompleted(array $tasks) {
|
||||
$results = array_column($tasks['tasks'], 'status');
|
||||
|
||||
return count(array_filter($results)) === count($results);
|
||||
}
|
||||
|
||||
|
||||
proceed();
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user