update installer class and ui

This commit is contained in:
envoyr
2022-04-30 11:59:38 +02:00
parent 10313d9058
commit 4ea31c7124
9 changed files with 287 additions and 442 deletions

View File

@@ -1,105 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2003-2009 the SysCP Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at https://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 https://files.froxlor.org/misc/COPYING.txt
* @package Language
*
*/
$lng['requirements']['title'] = 'Checking system requirements...';
$lng['requirements']['installed'] = 'installed';
$lng['requirements']['not_true'] = 'no';
$lng['requirements']['notfound'] = 'not found';
$lng['requirements']['notinstalled'] = 'not installed';
$lng['requirements']['activated'] = 'enabled';
$lng['requirements']['phpversion'] = 'PHP version >= 7.4';
$lng['requirements']['newerphpprefered'] = 'Good, but php-8.x is preferred.';
$lng['requirements']['phppdo'] = 'PHP PDO extension and PDO-MySQL driver...';
$lng['requirements']['phpsession'] = 'PHP session-extension...';
$lng['requirements']['phpctype'] = 'PHP ctype-extension...';
$lng['requirements']['phpsimplexml'] = 'PHP SimpleXML-extension...';
$lng['requirements']['phpxml'] = 'PHP XML-extension...';
$lng['requirements']['phpfilter'] = 'PHP filter-extension...';
$lng['requirements']['phpposix'] = 'PHP posix-extension...';
$lng['requirements']['phpbcmath'] = 'PHP bcmath-extension...';
$lng['requirements']['phpcurl'] = 'PHP curl-extension...';
$lng['requirements']['phpmbstring'] = 'PHP mbstring-extension...';
$lng['requirements']['phpzip'] = 'PHP zip-extension...';
$lng['requirements']['phpjson'] = 'PHP json-extension...';
$lng['requirements']['phpgmp'] = 'PHP gmp-extension...';
$lng['requirements']['bcmathdescription'] = 'Traffic-calculation related functions will not work correctly!';
$lng['requirements']['zipdescription'] = 'The auto-update feature requires the zip extension.';
$lng['requirements']['openbasedir'] = 'open_basedir...';
$lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the corresponding php.ini';
$lng['requirements']['mysqldump'] = 'MySQL dump tool';
$lng['requirements']['mysqldumpmissing'] = 'Automatic backup of possible existing database is not possible. Please install mysql-client tools';
$lng['requirements']['diedbecauseofrequirements'] = 'Cannot install Froxlor without these requirements! Try to fix them and retry.';
$lng['requirements']['froxlor_succ_checks'] = 'All requirements are satisfied';
$lng['install']['lngtitle'] = 'Froxlor install - choose language';
$lng['install']['language'] = 'Installation language';
$lng['install']['lngbtn_go'] = 'Change language';
$lng['install']['title'] = 'Froxlor install - setup';
$lng['install']['welcometext'] = 'Thank you for choosing Froxlor. Please fill out the following fields with the required information to start the installation.<br /><b>Attention:</b> If the database you chose for Froxlor already exists on your System, it will be erased with all containing data!';
$lng['install']['database'] = 'Database connection';
$lng['install']['mysql_host'] = 'MySQL-Hostname';
$lng['install']['mysql_database'] = 'Database name';
$lng['install']['mysql_forcecreate'] = 'Backup and overwrite database if exists?';
$lng['install']['mysql_unpriv_user'] = 'Username for the unprivileged MySQL-account';
$lng['install']['mysql_unpriv_pass'] = 'Password for the unprivileged MySQL-account';
$lng['install']['mysql_root_user'] = 'Username for the MySQL-root-account';
$lng['install']['mysql_root_pass'] = 'Password for the MySQL-root-account';
$lng['install']['mysql_ssl_ca_file'] = 'MySQL server certificate file path<br><small>(optional)</small>';
$lng['install']['mysql_ssl_verify_server_certificate'] = 'Verify MySQL TLS certificate';
$lng['install']['admin_account'] = 'Administrator Account';
$lng['install']['admin_user'] = 'Administrator Username';
$lng['install']['admin_pass1'] = 'Administrator Password';
$lng['install']['admin_pass2'] = 'Administrator-Password (confirm)';
$lng['install']['activate_newsfeed'] = 'Enable the official newsfeed<br><small>(https://inside.froxlor.org/news/)</small>';
$lng['install']['serversettings'] = 'Server settings';
$lng['install']['distribution'] = 'Distribution';
$lng['install']['servername'] = 'Server name (FQDN, no ip-address)';
$lng['install']['serverip'] = 'Server IP';
$lng['install']['webserver'] = 'Webserver';
$lng['install']['apache2'] = 'Apache 2.2';
$lng['install']['apache24'] = 'Apache 2.4';
$lng['install']['lighttpd'] = 'LigHTTPd';
$lng['install']['nginx'] = 'NGINX';
$lng['install']['httpuser'] = 'HTTP username';
$lng['install']['httpgroup'] = 'HTTP groupname';
$lng['install']['use_ssl'] = 'Enable SSL via port 443';
$lng['install']['testing_mysql'] = 'Checking MySQL-root access...';
$lng['install']['testing_mysql_fail'] = 'There seems to be a problem with the database-connection. Cannot continue. Please go back and check your credentials.';
$lng['install']['backup_old_db'] = 'Creating backup of old database...';
$lng['install']['backup_binary_missing'] = 'Could not find mysqldump';
$lng['install']['backup_failed'] = 'Could not backup database';
$lng['install']['check_db_exists'] = 'Checking database...';
$lng['install']['db_exists'] = 'Unable to create database. A database with the same name exists and should not be overwritten';
$lng['install']['prepare_db'] = 'Preparing database...';
$lng['install']['create_mysqluser_and_db'] = 'Creating database and username...';
$lng['install']['testing_new_db'] = 'Testing if database and user have been created correctly...';
$lng['install']['importing_data'] = 'Importing data...';
$lng['install']['changing_data'] = 'Adjusting settings...';
$lng['install']['creating_entries'] = 'Inserting new values...';
$lng['install']['adding_admin_user'] = 'Creating admin-account...';
$lng['install']['creating_configfile'] = 'Creating configfile...';
$lng['install']['creating_configfile_temp'] = 'File was saved in %s, please move to ' . dirname(__DIR__, 2) . '/lib/userdata.inc.php';
$lng['install']['creating_configfile_failed'] = 'Could not create ' . dirname(__DIR__, 2) . '/lib/userdata.inc.php, please create it manually with the following content:';
$lng['install']['froxlor_succ_installed'] = 'Froxlor was installed successfully.';
$lng['install']['failed'] = 'failed';
$lng['click_here_to_refresh'] = 'Click here to check again';
$lng['click_here_to_goback'] = 'Click here to go back';
$lng['click_here_to_continue'] = 'Click here to continue';
$lng['click_here_to_login'] = 'Click here to login.';

View File

@@ -1,88 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2003-2009 the SysCP Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at https://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 https://files.froxlor.org/misc/COPYING.txt
* @package Language
*
*/
$lng['requirements']['title'] = 'Vérification des prérequis système...';
$lng['requirements']['installed'] = 'installé';
$lng['requirements']['not_true'] = 'non';
$lng['requirements']['notfound'] = 'introuvable';
$lng['requirements']['notinstalled'] = 'non installé';
$lng['requirements']['activated'] = 'activé';
$lng['requirements']['phpversion'] = 'PHP version >= 7.4';
$lng['requirements']['newerphpprefered'] = 'Bien, mais php-8.x est recommandé.';
$lng['requirements']['phppdo'] = 'extension PHP PDO et pilote PDO-MySQL ...';
$lng['requirements']['phpxml'] = 'extension PHP XML...';
$lng['requirements']['phpfilter'] = 'extension PHP filter ...';
$lng['requirements']['phpposix'] = 'extension PHP posix ...';
$lng['requirements']['phpbcmath'] = 'extension PHP bcmath ...';
$lng['requirements']['phpcurl'] = 'extension PHP curl...';
$lng['requirements']['phpmbstring'] = 'extension PHP mbstring...';
$lng['requirements']['bcmathdescription'] = 'Les fonctions de calcul de traffic ne fonctionneront pas correctement!';
$lng['requirements']['openbasedir'] = 'open_basedir...';
$lng['requirements']['openbasedirenabled'] = 'Froxlor ne fonctionnera pas correctement avec open_basedir activé. Merci de désactiver open_basedir pour Froxlor dans le php.ini correspondant';
$lng['requirements']['diedbecauseofrequirements'] = 'Impossible d\'installer Froxlor sans ces prérequis! Essayez de les corriger et essayez à nouveau.';
$lng['requirements']['froxlor_succ_checks'] = 'Tous les prérequis sont vérifiés';
$lng['install']['lngtitle'] = 'Installation de Froxlor - choisisez la langue';
$lng['install']['language'] = 'Langue d\'installation';
$lng['install']['lngbtn_go'] = 'Changer la langue';
$lng['install']['title'] = 'Installation de Froxlor - paramètrage';
$lng['install']['welcometext'] = 'Merci d\'avoir choisi Froxlor. Merci de remplir les champs suivant avec les informations nécessaires pour démarrer l\'installation.<br /><b>Attention:</b> Si la base de données que vous choisissez existe déjà sur votre système, elle sera écrasée ainsi que les données contenues!';
$lng['install']['database'] = 'Connexion à la base de données';
$lng['install']['mysql_host'] = 'Nom d\'hôte MySQL';
$lng['install']['mysql_database'] = 'Nom de la base de données';
$lng['install']['mysql_unpriv_user'] = 'Nom d\'utilisateur pour le compte non priviligié MySQL';
$lng['install']['mysql_unpriv_pass'] = 'Mot de passe pour le compte non priviligié MySQL';
$lng['install']['mysql_root_user'] = 'Nom d\'utilisateur pour le compte MySQL root';
$lng['install']['mysql_root_pass'] = 'Mot de passe pour le compte MySQL root';
$lng['install']['admin_account'] = 'Compte administrateur';
$lng['install']['admin_user'] = 'Nom d\'utilisateur administrateur';
$lng['install']['admin_pass1'] = 'Mot de passe administrateur';
$lng['install']['admin_pass2'] = 'Mot de passe administrateur (confirmez)';
$lng['install']['serversettings'] = 'Réglages serveur';
$lng['install']['distribution'] = 'Distribution';
$lng['install']['servername'] = 'Nom du serveur (FQDN, pas d\'adresse IP)';
$lng['install']['serverip'] = 'Adresse IP du serveur';
$lng['install']['webserver'] = 'Serveur Web';
$lng['install']['apache2'] = 'Apache 2';
$lng['install']['apache24'] = 'Apache 2.4';
$lng['install']['lighttpd'] = 'LigHTTPd';
$lng['install']['nginx'] = 'NGINX';
$lng['install']['httpuser'] = 'Nom d\'utilisateur HTTP';
$lng['install']['httpgroup'] = 'Nom de groupe HTTP';
$lng['install']['testing_mysql'] = 'Vérification de l\'accès root MySQL...';
$lng['install']['testing_mysql_fail'] = 'Il semble y avoir un problème avec la connexion à la base de données. Impossible de continuer. Merci de revenir en arrière et de vérifier les informations d\'identification.';
$lng['install']['backup_old_db'] = 'Création des sauvegardes de l\'ancienne base de données...';
$lng['install']['backup_binary_missing'] = 'Impossible de trouver mysqldump';
$lng['install']['backup_failed'] = 'Impossible de sauvegarde la base de données';
$lng['install']['prepare_db'] = 'Préparation de la base de données...';
$lng['install']['create_mysqluser_and_db'] = 'Création de la base de données et l\'utilisateur...';
$lng['install']['testing_new_db'] = 'Teste si la base de données et l\'utilisateur ont été créés correctement...';
$lng['install']['importing_data'] = 'Import des données...';
$lng['install']['changing_data'] = 'Ajustement des paramètres...';
$lng['install']['creating_entries'] = 'Insertion des nouvelles valeurs...';
$lng['install']['adding_admin_user'] = 'Création du compte administrateur...';
$lng['install']['creating_configfile'] = 'Création du fichier de configuration...';
$lng['install']['creating_configfile_temp'] = 'Le fichier a été enregistré dans %s, merci de le déplacer dans ' . dirname(__DIR__, 2) . '/lib/userdata.inc.php';
$lng['install']['creating_configfile_failed'] = 'Impossible de créer ' . dirname(__DIR__, 2) . '/lib/userdata.inc.php, merci de le créer manuellement avec le contenu suivant:';
$lng['install']['froxlor_succ_installed'] = 'Froxlor a été installé avec succès.';
$lng['click_here_to_refresh'] = 'Cliquez ici pour vérifier à nouveau';
$lng['click_here_to_goback'] = 'Cliquez ici pour revenir';
$lng['click_here_to_continue'] = 'Cliquez ici pour continuer';
$lng['click_here_to_login'] = 'Cliquez ici pour vous connecter.';

View File

@@ -1,105 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2003-2009 the SysCP Team (see authors).
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at https://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Florian Lippert <flo@syscp.org> (2003-2009)
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 https://files.froxlor.org/misc/COPYING.txt
* @package Language
*
*/
$lng['requirements']['title'] = 'Prüfe Systemvoraussetzungen...';
$lng['requirements']['installed'] = 'installiert';
$lng['requirements']['not_true'] = 'nein';
$lng['requirements']['notfound'] = 'nicht gefunden';
$lng['requirements']['notinstalled'] = 'nicht installiert';
$lng['requirements']['activated'] = 'ist aktiviert.';
$lng['requirements']['phpversion'] = 'PHP Version >= 7.4';
$lng['requirements']['newerphpprefered'] = 'Ausreichend, aber php-8.x wird bevorzugt.';
$lng['requirements']['phppdo'] = 'PHP PDO Erweiterung und PDO-MySQL Treiber...';
$lng['requirements']['phpsession'] = 'PHP session-Erweiterung...';
$lng['requirements']['phpctype'] = 'PHP ctype-Erweiterung...';
$lng['requirements']['phpsimplexml'] = 'PHP SimpleXML-Erweiterung...';
$lng['requirements']['phpxml'] = 'PHP XML-Erweiterung...';
$lng['requirements']['phpfilter'] = 'PHP filter-Erweiterung...';
$lng['requirements']['phpposix'] = 'PHP posix-Erweiterung...';
$lng['requirements']['phpbcmath'] = 'PHP bcmath-Erweiterung...';
$lng['requirements']['phpcurl'] = 'PHP curl-Erweiterung...';
$lng['requirements']['phpmbstring'] = 'PHP mbstring-Erweiterung...';
$lng['requirements']['phpzip'] = 'PHP zip-Erweiterung...';
$lng['requirements']['phpjson'] = 'PHP json-Erweiterung...';
$lng['requirements']['phpgmp'] = 'PHP gmp-Erweiterung...';
$lng['requirements']['bcmathdescription'] = 'Traffic-Berechnungs bezogene Funktionen stehen nicht vollständig zur Verfügung!';
$lng['requirements']['zipdescription'] = 'Die Auto-Update Funktion benötigt die zip Erweiterung.';
$lng['requirements']['openbasedir'] = 'open_basedir genutzt wird...';
$lng['requirements']['openbasedirenabled'] = 'Froxlor wird mit aktiviertem open_basedir nicht vollständig funktionieren. Bitte deaktivieren Sie open_basedir für Froxlor in der entsprechenden php.ini';
$lng['requirements']['mysqldump'] = 'MySQL dump Tool';
$lng['requirements']['mysqldumpmissing'] = 'Ein automatisches Backup einer möglicherweise schon existierenden Datenbank nicht möglich. Bitte mysql-client installieren';
$lng['requirements']['diedbecauseofrequirements'] = 'Kann Froxlor ohne diese Voraussetzungen nicht installieren! Beheben Sie die angezeigten Probleme und versuchen Sie es erneut.';
$lng['requirements']['froxlor_succ_checks'] = 'Alle Vorraussetzungen sind erfüllt';
$lng['install']['lngtitle'] = 'Froxlor Installation - Sprache auswählen';
$lng['install']['language'] = 'Sprache für die Installation';
$lng['install']['lngbtn_go'] = 'Sprache ändern';
$lng['install']['title'] = 'Froxlor Installation - Einrichtung';
$lng['install']['welcometext'] = 'Vielen Dank dass Sie sich für Froxlor entschieden haben. Um die Installation von Froxlor zu starten, füllen Sie bitte alle Felder mit den geforderten Angaben aus.<br /><b>Achtung:</b> Eine eventuell existierende Datenbank, die den selben Namen hat wie den Gewählten, wird mit allen enthaltenen Daten gelöscht!';
$lng['install']['database'] = 'Datenbankverbindung';
$lng['install']['mysql_host'] = 'MySQL-Hostname';
$lng['install']['mysql_database'] = 'Datenbank Name';
$lng['install']['mysql_forcecreate'] = 'Datenbank sichern und überschreiben wenn vorhanden?';
$lng['install']['mysql_unpriv_user'] = 'Benutzername für den unprivilegierten MySQL-Account';
$lng['install']['mysql_unpriv_pass'] = 'Passwort für den unprivilegierten MySQL-Account';
$lng['install']['mysql_root_user'] = 'Benutzername für den MySQL-Root-Account';
$lng['install']['mysql_root_pass'] = 'Passwort für den MySQL-Root-Account';
$lng['install']['mysql_ssl_ca_file'] = 'MySQL-Server Zertifikatspfad<br><small>(optional)</small>';
$lng['install']['mysql_ssl_verify_server_certificate'] = 'Validieren des MySQL-Server Zertifikats';
$lng['install']['admin_account'] = 'Admin-Zugang';
$lng['install']['admin_user'] = 'Administrator-Benutzername';
$lng['install']['admin_pass1'] = 'Administrator-Passwort';
$lng['install']['admin_pass2'] = 'Administrator-Passwort (Bestätigung)';
$lng['install']['activate_newsfeed'] = 'Aktiviere das offizielle Newsfeed<br><small>(https://inside.froxlor.org/news/)</small>';
$lng['install']['serversettings'] = 'Servereinstellungen';
$lng['install']['distribution'] = 'Distribution';
$lng['install']['servername'] = 'Servername (FQDN, keine IP-Adresse)';
$lng['install']['serverip'] = 'Server-IP';
$lng['install']['webserver'] = 'Webserver';
$lng['install']['apache2'] = 'Apache 2';
$lng['install']['apache24'] = 'Apache 2.4';
$lng['install']['lighttpd'] = 'LigHTTPd';
$lng['install']['nginx'] = 'NGINX';
$lng['install']['httpuser'] = 'HTTP Username';
$lng['install']['httpgroup'] = 'HTTP Gruppenname';
$lng['install']['use_ssl'] = 'Aktiviere SSL via Port 443';
$lng['install']['testing_mysql'] = 'Teste MySQL-Root Zugang...';
$lng['install']['testing_mysql_fail'] = 'Bei der Verwendung der Datenbank gibt es scheinbar Probleme. Installation kann nicht fortgesetzt werden. Bitte Zugangsdaten prüfen und erneut versuchen.';
$lng['install']['backup_old_db'] = 'Sicherung vorheriger Datenbank...';
$lng['install']['backup_binary_missing'] = 'Konnte mysqldump nicht finden';
$lng['install']['backup_failed'] = 'Sicherung fehlgeschlagen';
$lng['install']['check_db_exists'] = 'Databenbank wird geprüft...';
$lng['install']['db_exists'] = 'Datenbank kann nicht erstellt werden. Eine Datenbank mit dem selben Namen existiert bereits und soll nicht überschrieben werden.';
$lng['install']['prepare_db'] = 'Datenbank wird vorbereitet...';
$lng['install']['create_mysqluser_and_db'] = 'Erstelle Datenbank und Benutzer...';
$lng['install']['testing_new_db'] = 'Teste, ob Datenbank und Benutzer korrekt angelegt wurden...';
$lng['install']['importing_data'] = 'Importiere Daten...';
$lng['install']['changing_data'] = 'Einstellungen anpassen...';
$lng['install']['creating_entries'] = 'Trage neue Werte ein...';
$lng['install']['adding_admin_user'] = 'Erstelle Admin-Benutzer...';
$lng['install']['creating_configfile'] = 'Erstelle Konfigurationsdatei...';
$lng['install']['creating_configfile_temp'] = 'Datei wurde in %s gespeichert, bitte nach ' . dirname(__DIR__, 2) . '/lib/userdata.inc.php verschieben.';
$lng['install']['creating_configfile_failed'] = 'Konnte ' . dirname(__DIR__, 2) . '/lib/userdata.inc.php nicht erstellen, bitte manuell mit folgendem Inhalt anlegen:';
$lng['install']['froxlor_succ_installed'] = 'Froxlor wurde erfolgreich installiert.';
$lng['install']['failed'] = 'fehlgeschlagen';
$lng['click_here_to_refresh'] = 'Hier klicken, um erneut zu prüfen';
$lng['click_here_to_goback'] = 'Einen Schritt zurück';
$lng['click_here_to_continue'] = 'Installation fortführen';
$lng['click_here_to_login'] = 'Hier geht es weiter zum Login-Fenster.';

View File

View File

@@ -25,30 +25,118 @@
namespace Froxlor\Install;
use Exception;
use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request;
class Install
{
public $step = 0;
public $currentStep;
public $maxSteps;
public $phpVersion;
public $formfield;
public string $requiredVersion = '7.4.0';
public array $requiredExtensions = ['libxml', 'zip'];
public array $suggestedExtensions = ['curl'];
public array $suggestions = [];
public array $criticals = [];
public array $loadedExtensions;
public array $supportedOS = [
'focal' => 'Ubuntu 20.04 LTS (Focal Fossa)'
];
public function __construct()
{
$this->step = Request::get('step');
// set formfield, so we can get the fields and steps etc.
$this->formfield = require dirname(__DIR__, 3) . '/lib/formfields/install/formfield.install.php';
// set actual step
$this->currentStep = Request::get('step', 0);
$this->maxSteps = count($this->formfield['install']['sections']);
// set actual php version and extensions
$this->phpVersion = phpversion();
$this->loadedExtensions = get_loaded_extensions();
$this->checkExtensions();
// init twig
UI::initTwig(true);
UI::sendHeaders();
// set global variables
UI::twig()->addGlobal('install_mode', true);
UI::twig()->addGlobal('basehref', '../');
// unset session if user goes back to step 0
if (isset($_SESSION['installation']) && $this->currentStep == 0) {
unset($_SESSION['installation']);
}
}
public function checkExtensions()
/**
* @return void
* @throws Exception
*/
public function handle(): void
{
// handle form data
if (!is_null(Request::get('submit')) && $this->currentStep) {
try {
$this->handleFormData($this->formfield['install']);
} catch (Exception $e) {
$error = $e->getMessage();
}
}
// load template
UI::twigBuffer('/install/index.html.twig', [
'setup' => [
'step' => $this->currentStep,
],
'preflight' => $this->checkExtensions(),
'page' => [
'title' => 'Database',
'description' => 'Test',
],
'section' => $this->formfield['install']['sections']['step' . $this->currentStep] ?? [],
'error' => $error ?? null,
]);
// output view
UI::twigOutputBuffer();
}
/**
* @throws Exception
*/
private function handleFormData(array $formfield): void
{
// Validate user data
$validatedData = $this->validateRequest($formfield['sections']['step' . $this->currentStep]['fields']);
// handle current step
if ($this->currentStep <= $this->maxSteps) {
// Check database connection (
if ($this->currentStep == 1) {
$this->checkDatabase($validatedData);
}
// Store validated data for later use
$_SESSION['installation'] = array_merge($_SESSION['installation'] ?? [], $validatedData);
}
// also handle completion of installation if it's the last step
if ($this->currentStep == $this->maxSteps) {
$this->startInstallation($validatedData);
header('Location: ../');
return;
}
header('Location: ?step=' . ($this->currentStep + 1));
}
/**
* @return array
*/
private function checkExtensions(): array
{
// check for required extensions
foreach ($this->requiredExtensions as $requiredExtension) {
@@ -65,42 +153,18 @@ class Install
}
$this->suggestions['missing_extensions'][] = $suggestedExtension;
}
return [
'text' => $this->getInformationText(),
'suggestions' => $this->suggestions,
'criticals' => $this->criticals,
];
}
public function handle()
{
$formfield = require dirname(__DIR__, 3) . '/lib/formfields/install/formfield.install.php';
// init twig
UI::initTwig(true);
UI::sendHeaders();
// set global variables
UI::twig()->addGlobal('install_mode', true);
UI::twig()->addGlobal('basehref', '../');
// load template
UI::twigBuffer('/install/index.html.twig', [
'setup' => [
'step' => $this->step,
],
'preflight' => [
'text' => $this->getPreflightText(),
'suggestions' => $this->suggestions,
'criticals' => $this->criticals,
],
'page' => [
'title' => 'Database',
'description' => 'Test',
],
'section' => $formfield['install']['sections'][sprintf('step%s', $this->step)] ?? [],
]);
// output view
UI::twigOutputBuffer();
}
public function getPreflightText(): string
/**
* @return string
*/
private function getInformationText(): string
{
if (version_compare($this->requiredVersion, PHP_VERSION, "<")) {
$text = 'Your system is running with PHP ' . $this->phpVersion;
@@ -108,7 +172,93 @@ class Install
$text = 'Your system is running a lower version than PHP ' . $this->requiredVersion;
$this->criticals[] = 'Update your current PHP Version from ' . $this->phpVersion . ' to ' . $this->requiredVersion . ' or higher';
}
return $text;
}
/**
* @throws Exception
*/
private function validateRequest(array $fields): array
{
$attributes = [];
foreach ($fields as $name => $field) {
$attributes[$name] = $this->validateAttribute(Request::get($name), $field);
if (isset($field['next_to'])) {
$attributes = array_merge($attributes, $this->validateRequest($field['next_to']));
}
}
return $attributes;
}
/**
* @return mixed
* @throws Exception
*/
private function validateAttribute($attribute, array $field)
{
// TODO: do validations
if (isset($field['mandatory']) && $field['mandatory'] && empty($attribute)) {
throw new Exception('Mandatory field is not set!');
}
return $attribute;
}
/**
* @throws Exception
*/
private function checkDatabase(array $validatedData): void
{
$dsn = sprintf('mysql:host=%s;charset=utf8mb4', $validatedData['sql_hostname']);
$pdo = new \PDO($dsn, $validatedData['sql_root_username'], $validatedData['sql_root_password']);
// check if the database already exist
$stmt = $pdo->prepare('SHOW DATABASES LIKE ?');
$stmt->execute([
$validatedData['sql_database']
]);
$hasDatabase = $stmt->fetch();
if ($hasDatabase && !$validatedData['sql_override_database']) {
throw new Exception('Database already exist, please set override option to rebuild!');
}
// check if we can create a new database
$testDatabase = uniqid('froxlor_tmp_');
if ($pdo->exec('CREATE DATABASE IF NOT EXISTS ' . $testDatabase . ';') === false) {
throw new Exception('cant create test db');
}
if ($pdo->exec('DROP DATABASE IF EXISTS ' . $testDatabase . ';') === false) {
throw new Exception('Cant drop test db');
}
// FIXME: seems not to work
// check if the user already exist
$stmt = $pdo->prepare("SELECT `user` FROM `mysql.user` WHERE `user` = '?'");
if ($stmt->rowCount()) {
throw new Exception('Username already exist, please use another username!');
}
// check if we can create a new user
$testUser = uniqid('froxlor_tmp_');
$stmt = $pdo->prepare('CREATE USER ?@? IDENTIFIED BY ?');
if ($stmt->execute([$testUser, $validatedData['sql_hostname'], uniqid()]) === false) {
throw new Exception('cant create test user');
}
$stmt = $pdo->prepare('DROP USER ?@?');
if ($stmt->execute([$testUser, $validatedData['sql_hostname']]) === false) {
throw new Exception('cant create test user');
}
if ($pdo->prepare('FLUSH PRIVILEGES')->execute() === false) {
throw new Exception('Cant flush privileges');
}
}
/**
* @param array $validatedData
* @return void
* @throws Exception
*/
private function startInstallation(array $validatedData): void
{
// TODO: do the installation (maybe in an own class?)
}
}

View File

@@ -30,153 +30,111 @@ return [
'self_overview' => ['section' => 'admins', 'page' => 'admins'],
'sections' => [
'step1' => [
'title' => lng('install.dabatase'),
'title' => lng('install.database.title'),
'fields' => [
'sql_hostname' => [
'label' => lng('sql_hostname'),
'type' => 'text',
'mandatory' => true,
'value' => 'localhost'
'value' => old('sql_hostname', 'localhost', 'installation')
],
'sql_root_username' => [
'label' => lng('sql_root_username'),
'type' => 'password',
'type' => 'text',
'mandatory' => true,
'value' => old('sql_root_username', 'froxroot', 'installation'),
'next_to' => [
'sql_root_password' => [
'label' => lng('sql_root_password'),
'type' => 'password',
'mandatory' => true
'mandatory' => true,
'value' => old('sql_root_password', null, 'installation'),
],
]
],
'sql_username' => [
'label' => lng('sql_username'),
'type' => 'password',
'type' => 'text',
'mandatory' => true,
'value' => old('sql_username', 'froxlor', 'installation'),
'next_to' => [
'sql_password' => [
'label' => lng('sql_password'),
'type' => 'password',
'mandatory' => true
'mandatory' => true,
'value' => old('sql_password', null, 'installation'),
],
]
],
'sql_database' => [
'label' => lng('sql_database'),
'type' => 'text',
'mandatory' => true,
'value' => old('sql_database', 'froxlor', 'installation'),
],
'sql_override_database' => [
'label' => lng('sql_override_database'),
'type' => 'checkbox',
'value' => '1',
'checked' => old('sql_override_database', '0', 'installation')
],
]
],
'step2' => [
'title' => lng('admin.contactdata'),
'image' => 'icons/user_add.png',
'title' => lng('install.admin.title'),
'fields' => [
'name' => [
'label' => lng('name'),
'type' => 'text',
'mandatory' => true
'mandatory' => true,
'value' => old('name', 'Administrator', 'installation'),
],
'username' => [
'label' => lng('username'),
'type' => 'text',
'mandatory' => true
'mandatory' => true,
'value' => old('username', 'admin', 'installation'),
],
'password' => [
'label' => lng('password'),
'type' => 'password',
'mandatory' => true
'mandatory' => true,
'value' => old('password', null, 'installation'),
],
'email' => [
'label' => lng('email'),
'type' => 'text',
'mandatory' => true
'mandatory' => true,
'value' => old('email', null, 'installation'),
],
]
],
'step3' => [
'title' => lng('admin.servicedata'),
'image' => 'icons/user_add.png',
'title' => lng('install.system.title'),
'fields' => [
'ipaddress' => [
'label' => lng('serversettings.ipaddress.title'),
'type' => 'select'
'system' => [
'label' => lng('install.system.system'),
'type' => 'select',
'select_var' => $this->supportedOS,
],
'change_serversettings' => [
'label' => lng('admin.change_serversettings'),
'test' => [
'label' => lng('install.system.test'),
'type' => 'checkbox',
'value' => '1',
'checked' => false
],
'customers' => [
'label' => lng('admin.customers'),
'type' => 'textul',
'value' => 0,
'maxlength' => 9,
'mandatory' => true
]
],
'step4' => [
'title' => lng('install.system.title'),
'fields' => [
'system' => [
'label' => lng('install.system.system'),
'type' => 'textarea',
'value' => '/var/www/html/froxlor/bin/froxlor-cli cron --force',
'readonly' => true,
'rows' => 1
],
'customers_see_all' => [
'label' => lng('admin.customers_see_all'),
'type' => 'checkbox',
'value' => '1',
'checked' => false
],
'domains' => [
'label' => lng('admin.domains'),
'type' => 'textul',
'value' => 0,
'maxlength' => 9,
'mandatory' => true
],
'domains_see_all' => [
'label' => lng('admin.domains_see_all'),
'type' => 'checkbox',
'value' => '1',
'checked' => false
],
'caneditphpsettings' => [
'label' => lng('admin.caneditphpsettings'),
'type' => 'checkbox',
'value' => '1',
'checked' => false
],
'subdomains' => [
'label' => lng('customer.subdomains'),
'type' => 'textul',
'value' => 0,
'maxlength' => 9,
'mandatory' => true
],
'emails' => [
'label' => lng('customer.emails'),
'type' => 'textul',
'value' => 0,
'maxlength' => 9,
'mandatory' => true
],
'email_accounts' => [
'label' => lng('customer.accounts'),
'type' => 'textul',
'value' => 0,
'maxlength' => 9,
'mandatory' => true
],
'email_forwarders' => [
'label' => lng('customer.forwarders'),
'type' => 'textul',
'value' => 0,
'maxlength' => 9,
'mandatory' => true
],
'ftps' => [
'label' => lng('customer.ftps'),
'type' => 'textul',
'value' => 0,
'maxlength' => 9
],
'mysqls' => [
'label' => lng('customer.mysqls'),
'type' => 'textul',
'value' => 0,
'maxlength' => 9,
'mandatory' => true
]
]
]
]

View File

@@ -24,6 +24,7 @@
*/
use Froxlor\Language;
use Froxlor\UI\Request;
function view($template, $attributes)
{
@@ -36,3 +37,11 @@ function lng(string $identifier, array $arguments = [])
{
return Language::getTranslation($identifier, $arguments);
}
function old(string $identifier, string $default = null, string $session = null)
{
if ($session && isset($_SESSION[$session])) {
return $_SESSION[$session][$identifier] ?? $default;
}
return Request::get($identifier, $default);
}

View File

@@ -2447,4 +2447,10 @@ Yours sincerely, your administrator',
'notice' => 'API access is not allowed for your account.',
],
],
'install' => [
'dependency_check' => [
'title' => 'Welcome to froxlor',
'description' => 'We check the system for dependencies to ensure that all required php extensions and modules are enabled so that froxlor runs properly.',
],
],
];

View File

@@ -2,18 +2,38 @@
{% block content %}
<div class="container max-w-lg flex align-content-center mt-5">
<img src="{{ basehref|default('') }}templates/Froxlor/assets/img/logo.png" class="mb-5" alt="Froxlor Server Management Panel"/>
<img src="{{ basehref|default('') }}templates/Froxlor/assets/img/logo.png" class="mb-5" alt="{{ lng('slogan') }}"/>
{% if error is not null %}
<div class="alert alert-danger mb-4">{{ error }}</div>
{% endif %}
<div class="row text-center gx-0">
<div class="col p-3{{ setup.step == 0 ? ' bg-white shadow rounded-top' : '' }}"><i class="far fa-circle{{ setup.step > 0 ? '-check' : '' }}"></i> Preflight</div>
<div class="col p-3{{ setup.step == 1 ? ' bg-white shadow rounded-top' : '' }}"><i class="far fa-circle{{ setup.step > 1 ? '-check' : '' }}"></i> Database</div>
<div class="col p-3{{ setup.step == 2 ? ' bg-white shadow rounded-top' : '' }}"><i class="far fa-circle{{ setup.step > 2 ? '-check' : '' }}"></i> Admin</div>
<div class="col p-3{{ setup.step == 3 ? ' bg-white shadow rounded-top' : '' }}"><i class="far fa-circle{{ setup.step > 3 ? '-check' : '' }}"></i> System</div>
<div class="col p-3{{ setup.step == 0 ? ' bg-white shadow rounded-top' : '' }}">
<i class="far fa-circle{{ setup.step > 0 ? '-check' : '' }}"></i>
{% if setup.step > 0 %}<a href="?step=0" class="text-decoration-none">{{ lng('preflight') }}</a>{% else %}{{ lng('preflight') }}{% endif %}
</div>
<div class="col p-3{{ setup.step == 1 ? ' bg-white shadow rounded-top' : '' }}">
<i class="far fa-circle{{ setup.step > 1 ? '-check' : '' }}"></i>
{% if setup.step > 1 %}<a href="?step=1" class="text-decoration-none">{{ lng('database') }}</a>{% else %}{{ lng('database') }}{% endif %}
</div>
<div class="col p-3{{ setup.step == 2 ? ' bg-white shadow rounded-top' : '' }}">
<i class="far fa-circle{{ setup.step > 2 ? '-check' : '' }}"></i>
{% if setup.step > 2 %}<a href="?step=2" class="text-decoration-none">{{ lng('admin') }}</a>{% else %}{{ lng('admin') }}{% endif %}
</div>
<div class="col p-3{{ setup.step == 3 ? ' bg-white shadow rounded-top' : '' }}">
<i class="far fa-circle{{ setup.step > 3 ? '-check' : '' }}"></i>
{% if setup.step > 3 %}<a href="?step=3" class="text-decoration-none">{{ lng('system') }}</a>{% else %}{{ lng('system') }}{% endif %}
</div>
<div class="col p-3{{ setup.step == 4 ? ' bg-white shadow rounded-top' : '' }}">
<i class="far fa-circle{{ setup.step > 4 ? '-check' : '' }}"></i>
{% if setup.step > 4 %}<a href="?step=4" class="text-decoration-none">{{ lng('install') }}</a>{% else %}{{ lng('install') }}{% endif %}
</div>
</div>
<div class="card border-0 shadow">
<div class="card-body p-5">
<form method="post" action="?step={{ setup.step + 1 }}">
<form method="post" action="?step={{ setup.step }}">
{% if setup.step > 0 %}
<h4 class="mb-3">{{ section.title }}</h4>
<p class="lead">{{ section.description }}</p>
@@ -25,12 +45,12 @@
{% endfor %}
<div class="d-flex justify-content-between mt-4">
<a href="?step={{ setup.step - 1 }}" class="btn btn-secondary">&laquo;</a>
<button class="btn btn-primary">Next</button>
<a href="?step={{ setup.step - 1 }}" class="btn btn-secondary">&laquo; {{ lng('back') }}</a>
<button type="submit" name="submit" class="btn btn-primary">{{ lng('next') }} &raquo;</button>
</div>
{% else %}
<h4 class="mb-3">Welcome to froxlor</h4>
<p class="lead">We check the system for dependencies to ensure that all required php extensions and modules are enabled so that froxlor runs properly.</p>
<h4 class="mb-3">{{ lng('install.dependency_check.title') }}</h4>
<p class="lead">{{ lng('install.dependency_check.description') }}</p>
<p class="lead {{ preflight.criticals ? 'text-danger' : preflight.suggestions ? 'text-warning' : 'text-success'}}">
<i class="{{ preflight.criticals ? 'fa fa-triangle-exclamation' : preflight.suggestions ? 'fa-circle-info' : 'far fa-circle-check' }}"></i>
@@ -38,7 +58,7 @@
</p>
{% if preflight.criticals %}
<p class="text-muted">Critical Error</p>
<p class="text-muted">{{ lng('critical_error') }}</p>
<ul>
{% for critical in preflight.criticals %}
<li>{{ critical|json_encode }}</li>
@@ -47,7 +67,7 @@
{% endif %}
{% if preflight.suggestions %}
<p class="text-muted">Suggestions</p>
<p class="text-muted">{{ lng('suggestions') }}</p>
<ul>
{% for suggestion in preflight.suggestions %}
<li>{{ suggestion|json_encode }}</li>
@@ -57,9 +77,9 @@
<div class="d-flex justify-content-end mt-4">
{% if preflight.criticals or preflight.suggestions %}
<a href="" class="btn btn-secondary"><i class="fa fa-arrow-rotate-left"></i> Check again</a>
<a href="" class="btn btn-secondary"><i class="fa fa-arrow-rotate-left"></i> {{ lng('check_again') }}</a>
{% else %}
<a href="?step=1" class="btn btn-primary">Start installation</a>
<a href="?step=1" class="btn btn-primary">{{ lng('start_installation') }}</a>
{% endif %}
</div>
{% endif %}