Compare commits

...

2 Commits
2.0.4 ... 2.0.5

Author SHA1 Message Date
Michael Kaufmann
0f382586ce set version to 2.0.5
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-01-08 23:24:43 +01:00
Michael Kaufmann
9c2f12ecb1 mysql-remote-server fixes
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-01-08 23:20:31 +01:00
15 changed files with 42 additions and 32 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@ install/update.log
install/*.json install/*.json
lib/userdata.inc.php lib/userdata.inc.php
lib/userdata.inc.php.bak lib/userdata.inc.php.bak
lib/config.inc.php
logs/* logs/*
!logs/index.html !logs/index.html
.buildpath .buildpath

View File

@@ -43,12 +43,6 @@ use PHPMailer\PHPMailer\PHPMailer;
const AREA = 'admin'; const AREA = 'admin';
require __DIR__ . '/lib/init.php'; require __DIR__ . '/lib/init.php';
// get sql-root access data
Database::needRoot(true);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
if ($page == 'overview' && $userinfo['change_serversettings'] == '1') { if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
$settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/'); $settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/');
Settings::loadSettingsInto($settings_data); Settings::loadSettingsInto($settings_data);

View File

@@ -92,7 +92,7 @@ if ($page == 'overview' || $page == 'mysqls') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['databasename']) && $result['databasename'] != '') { if (isset($result['databasename']) && $result['databasename'] != '') {
Database::needRoot(true, $result['dbserver']); Database::needRoot(true, $result['dbserver'], false);
Database::needSqlData(); Database::needSqlData();
$sql_root = Database::getSqlData(); $sql_root = Database::getSqlData();
Database::needRoot(false); Database::needRoot(false);

View File

@@ -225,7 +225,7 @@ CREATE TABLE `panel_customers` (
`allowed_mysqlserver` text NOT NULL, `allowed_mysqlserver` text NOT NULL,
PRIMARY KEY (`customerid`), PRIMARY KEY (`customerid`),
UNIQUE KEY `loginname` (`loginname`) UNIQUE KEY `loginname` (`loginname`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `panel_databases`; DROP TABLE IF EXISTS `panel_databases`;
@@ -696,7 +696,7 @@ opcache.validate_timestamps'),
('system', 'distribution', ''), ('system', 'distribution', ''),
('system', 'update_channel', 'stable'), ('system', 'update_channel', 'stable'),
('system', 'updatecheck_data', ''), ('system', 'updatecheck_data', ''),
('system', 'update_notify_last', '2.0.4'), ('system', 'update_notify_last', '2.0.5'),
('system', 'traffictool', 'goaccess'), ('system', 'traffictool', 'goaccess'),
('api', 'enabled', '0'), ('api', 'enabled', '0'),
('2fa', 'enabled', '1'), ('2fa', 'enabled', '1'),
@@ -740,7 +740,7 @@ opcache.validate_timestamps'),
('panel', 'logo_overridetheme', '0'), ('panel', 'logo_overridetheme', '0'),
('panel', 'logo_overridecustom', '0'), ('panel', 'logo_overridecustom', '0'),
('panel', 'settings_mode', '0'), ('panel', 'settings_mode', '0'),
('panel', 'version', '2.0.4'), ('panel', 'version', '2.0.5'),
('panel', 'db_version', '202212060'); ('panel', 'db_version', '202212060');

View File

@@ -66,8 +66,8 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
KEY customerid (customerid) KEY customerid (customerid)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;"; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;";
Database::query($sql); Database::query($sql);
Database::query("SET SESSION innodb_strict_mode=OFF;");
// new customer allowed_mysqlserver field // new customer allowed_mysqlserver field
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ROW_FORMAT=DYNAMIC;");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `customernumber` `customernumber` varchar(100) NOT NULL default '';"); Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `customernumber` `customernumber` varchar(100) NOT NULL default '';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `allowed_phpconfigs` `allowed_phpconfigs` text NOT NULL;"); Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` CHANGE COLUMN `allowed_phpconfigs` `allowed_phpconfigs` text NOT NULL;");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `allowed_mysqlserver` text NOT NULL;"); Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `allowed_mysqlserver` text NOT NULL;");
@@ -273,3 +273,8 @@ EOF;
Froxlor::updateToVersion('2.0.4'); Froxlor::updateToVersion('2.0.4');
} }
if (Froxlor::isFroxlorVersion('2.0.4')) {
Update::showUpdateStep("Updating from 2.0.4 to 2.0.5", false);
Froxlor::updateToVersion('2.0.5');
}

View File

@@ -90,7 +90,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
// validate whether the dbserver exists // validate whether the dbserver exists
$dbserver = Validate::validate($dbserver, html_entity_decode(lng('mysql.mysql_server')), '/^[0-9]+$/', '', 0, true); $dbserver = Validate::validate($dbserver, html_entity_decode(lng('mysql.mysql_server')), '/^[0-9]+$/', '', 0, true);
Database::needRoot(true, $dbserver); Database::needRoot(true, $dbserver, false);
Database::needSqlData(); Database::needSqlData();
$sql_root = Database::getSqlData(); $sql_root = Database::getSqlData();
Database::needRoot(false); Database::needRoot(false);
@@ -150,7 +150,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
$pma = Settings::Get('panel.phpmyadmin_url'); $pma = Settings::Get('panel.phpmyadmin_url');
} }
Database::needRoot(true, $dbserver); Database::needRoot(true, $dbserver, false);
Database::needSqlData(); Database::needSqlData();
$sql_root = Database::getSqlData(); $sql_root = Database::getSqlData();
Database::needRoot(false); Database::needRoot(false);
@@ -287,7 +287,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
} }
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
Database::needRoot(true, $result['dbserver']); Database::needRoot(true, $result['dbserver'], false);
$mbdata_stmt = Database::prepare(" $mbdata_stmt = Database::prepare("
SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
WHERE table_schema = :table_schema WHERE table_schema = :table_schema
@@ -364,7 +364,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
} }
// Begin root-session // Begin root-session
Database::needRoot(true, $result['dbserver']); Database::needRoot(true, $result['dbserver'], false);
$dbmgr = new DbManager($this->logger()); $dbmgr = new DbManager($this->logger());
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) { foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
$dbmgr->getManager()->grantPrivilegesTo($result['databasename'], $password, $mysql_access_host, false, true); $dbmgr->getManager()->grantPrivilegesTo($result['databasename'], $password, $mysql_access_host, false, true);
@@ -449,7 +449,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
'dbserver' => $_dbserver['dbserver'] 'dbserver' => $_dbserver['dbserver']
], $query_fields), true, true); ], $query_fields), true, true);
// Begin root-session // Begin root-session
Database::needRoot(true, $_dbserver['dbserver']); Database::needRoot(true, $_dbserver['dbserver'], false);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$mbdata_stmt = Database::prepare(" $mbdata_stmt = Database::prepare("
SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES
@@ -536,7 +536,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
$id = $result['id']; $id = $result['id'];
// Begin root-session // Begin root-session
Database::needRoot(true, $result['dbserver']); Database::needRoot(true, $result['dbserver'], false);
$dbm = new DbManager($this->logger()); $dbm = new DbManager($this->logger());
$dbm->getManager()->deleteDatabase($result['databasename']); $dbm->getManager()->deleteDatabase($result['databasename']);
Database::needRoot(false); Database::needRoot(false);

View File

@@ -146,6 +146,7 @@ class BackupCron extends FroxlorCron
FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir($tmpdir . '/mysql'))); FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir($tmpdir . '/mysql')));
// get all customer database-names // get all customer database-names
// @fixme respect multiple dbservers
$sel_stmt = Database::prepare("SELECT `databasename` FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid` = :cid"); $sel_stmt = Database::prepare("SELECT `databasename` FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid` = :cid");
Database::pexecute($sel_stmt, [ Database::pexecute($sel_stmt, [
'cid' => $data['customerid'] 'cid' => $data['customerid']

View File

@@ -127,7 +127,7 @@ class TrafficCron extends FroxlorCron
while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) { while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($last_dbserver != $row_database['dbserver']) { if ($last_dbserver != $row_database['dbserver']) {
Database::needRoot(true, $row_database['dbserver']); Database::needRoot(true, $row_database['dbserver'], true);
$last_dbserver = $row_database['dbserver']; $last_dbserver = $row_database['dbserver'];
$databases_list = []; $databases_list = [];

View File

@@ -79,6 +79,8 @@ class Database
private static $sqldata = null; private static $sqldata = null;
private static $need_dbname = true;
/** /**
* Wrapper for PDOStatement::execute so we can catch the PDOException * Wrapper for PDOStatement::execute so we can catch the PDOException
* and display the error nicely on the panel - also fetches the * and display the error nicely on the panel - also fetches the
@@ -341,12 +343,13 @@ class Database
* @param int $dbserver * @param int $dbserver
* optional * optional
*/ */
public static function needRoot($needroot = false, $dbserver = 0) public static function needRoot(bool $needroot = false, int $dbserver = 0, bool $need_db = true)
{ {
// force re-connecting to the db with corresponding user // force re-connecting to the db with corresponding user
// and set the $dbserver (mostly to 0 = default) // and set the $dbserver (mostly to 0 = default)
self::setServer($dbserver); self::setServer($dbserver);
self::$needroot = $needroot; self::$needroot = $needroot;
self::$need_dbname = $need_db;
} }
/** /**
@@ -465,10 +468,11 @@ class Database
'ATTR_ERRMODE' => 'ERRMODE_EXCEPTION' 'ATTR_ERRMODE' => 'ERRMODE_EXCEPTION'
]; ];
$dbconf["dsn"] = [ $dbconf["dsn"] = ['charset' => 'utf8'];
'dbname' => $sql["db"],
'charset' => 'utf8' if (self::$need_dbname) {
]; $dbconf["dsn"]['dbname'] = $sql["db"];
}
if ($socket != null) { if ($socket != null) {
$dbconf["dsn"]['unix_socket'] = FileDir::makeCorrectFile($socket); $dbconf["dsn"]['unix_socket'] = FileDir::makeCorrectFile($socket);

View File

@@ -96,7 +96,7 @@ class DbManager
$dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`"); $dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`");
while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) { while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) {
// require privileged access for target db-server // require privileged access for target db-server
Database::needRoot(true, $dbserver['dbserver']); Database::needRoot(true, $dbserver['dbserver'], false);
$dbm = new DbManager(FroxlorLogger::getInstanceOf()); $dbm = new DbManager(FroxlorLogger::getInstanceOf());
$users = $dbm->getManager()->getAllSqlUsers(false); $users = $dbm->getManager()->getAllSqlUsers(false);
@@ -144,7 +144,7 @@ class DbManager
*/ */
public function createDatabase($loginname = null, $password = null, int $dbserver = 0, $last_accnumber = 0) public function createDatabase($loginname = null, $password = null, int $dbserver = 0, $last_accnumber = 0)
{ {
Database::needRoot(true, $dbserver); Database::needRoot(true, $dbserver, false);
// check whether we shall create a random username // check whether we shall create a random username
if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'RANDOM') { if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'RANDOM') {
@@ -169,18 +169,17 @@ class DbManager
// now create the database itself // now create the database itself
$this->getManager()->createDatabase($username); $this->getManager()->createDatabase($username);
$this->log->logAction(FroxlorLogger::USR_ACTION, LOG_INFO, "created database '" . $username . "'");
// and give permission to the user on every access-host we have // and give permission to the user on every access-host we have
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) { foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
$this->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host); $this->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host);
$this->log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "grant all privileges for '" . $username . "'@'" . $mysql_access_host . "'");
} }
$this->getManager()->flushPrivileges(); $this->getManager()->flushPrivileges();
Database::needRoot(false); Database::needRoot(false);
$this->log->logAction(FroxlorLogger::USR_ACTION, LOG_INFO, "created database '" . $username . "'");
return $username; return $username;
} }

View File

@@ -31,7 +31,7 @@ final class Froxlor
{ {
// Main version variable // Main version variable
const VERSION = '2.0.4'; const VERSION = '2.0.5';
// Database version (YYYYMMDDC where C is a daily counter) // Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202212060'; const DBVERSION = '202212060';

View File

@@ -32,7 +32,7 @@ class Mysql
public static function dbserver(array $attributes): string public static function dbserver(array $attributes): string
{ {
// get sql-root access data // get sql-root access data
Database::needRoot(true, (int)$attributes['data']); Database::needRoot(true, (int)$attributes['data'], false);
Database::needSqlData(); Database::needSqlData();
$sql_root = Database::getSqlData(); $sql_root = Database::getSqlData();
Database::needRoot(false); Database::needRoot(false);

View File

@@ -33,10 +33,16 @@ return [
'value' => $result['databasename'] 'value' => $result['databasename']
], ],
'mysql_server' => [ 'mysql_server' => [
'visible' => count($mysql_servers) > 1,
'type' => 'hidden',
'value' => $result['dbserver'] ?? 0,
],
'mysql_server_info' => [
'visible' => count($mysql_servers) > 1, 'visible' => count($mysql_servers) > 1,
'label' => lng('mysql.mysql_server'), 'label' => lng('mysql.mysql_server'),
'type' => 'label', 'type' => 'label',
'value' => $mysql_servers[$result['dbserver']] ?? 'unknown db server' 'disabled' => true,
'value' => $mysql_servers[$result['dbserver']] ?? 'unknown db server',
], ],
'description' => [ 'description' => [
'label' => lng('mysql.databasedescription'), 'label' => lng('mysql.databasedescription'),

View File

@@ -197,7 +197,7 @@
{% if field.next_to is defined %} {% if field.next_to is defined %}
<div class="input-group"> <div class="input-group">
{% endif %} {% endif %}
<select {% if field.visible is defined and field.visible == false %} disabled {% endif %} class="form-select {% if field.valid is defined and field.valid == false %}is-invalid{% endif %}" name="{{ id }}{% if field.select_mode is defined and field.select_mode == 'multiple' %}[]{% endif %}" id="{{ id }}" {% if field.mandatory is defined and field.mandatory %} required {% endif %} {% if field.select_mode is defined and field.select_mode == 'multiple' %} multiple="multiple" {% endif %}> <select {% if field.visible is defined and field.visible == false %} disabled {% endif %} class="form-select {% if field.valid is defined and field.valid == false %}is-invalid{% endif %}" name="{{ id }}{% if field.select_mode is defined and field.select_mode == 'multiple' %}[]{% endif %}" id="{{ id }}" {% if field.mandatory is defined and field.mandatory %} required {% endif %} {% if field.select_mode is defined and field.select_mode == 'multiple' %} multiple="multiple" {% endif %}{% if field.readonly is defined and field.readonly %} readonly {% endif %}>
{% for val,txt in field.select_var %} {% for val,txt in field.select_var %}
<option value="{{ val }}" {% if field.selected is defined and ((field.selected is not iterable and field.selected == val) or (field.selected is iterable and val in field.selected|keys)) %} selected="selected" {% endif %}>{{ txt|raw }}</option> <option value="{{ val }}" {% if field.selected is defined and ((field.selected is not iterable and field.selected == val) or (field.selected is iterable and val in field.selected|keys)) %} selected="selected" {% endif %}>{{ txt|raw }}</option>
{% endfor %} {% endfor %}