fix unit-tests with new language-class; fix language access in standard_error/standard_success; add MysqlServer API command and possibility to allow/disallow customers available mysql-servers
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
@@ -26,7 +26,8 @@
|
|||||||
const AREA = 'customer';
|
const AREA = 'customer';
|
||||||
require __DIR__ . '/lib/init.php';
|
require __DIR__ . '/lib/init.php';
|
||||||
|
|
||||||
use Froxlor\Api\Commands\Mysqls as Mysqls;
|
use Froxlor\Api\Commands\Mysqls;
|
||||||
|
use Froxlor\Api\Commands\MysqlServer;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
@@ -139,15 +140,16 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
'page' => $page
|
'page' => $page
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
$dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`");
|
|
||||||
$mysql_servers = [];
|
$mysql_servers = [];
|
||||||
while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) {
|
try {
|
||||||
Database::needRoot(true, $dbserver['dbserver']);
|
$result_json = MysqlServer::getLocal($userinfo)->listing();
|
||||||
Database::needSqlData();
|
$result_decoded = json_decode($result_json, true)['data']['list'];
|
||||||
$sql_root = Database::getSqlData();
|
foreach ($result_decoded as $dbserver => $dbdata) {
|
||||||
$mysql_servers[$dbserver['dbserver']] = $sql_root['caption'];
|
$mysql_servers[$dbserver] = $dbdata['caption'];
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
/* just none */
|
||||||
}
|
}
|
||||||
Database::needRoot(false);
|
|
||||||
|
|
||||||
$mysql_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/mysql/formfield.mysql_add.php';
|
$mysql_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/mysql/formfield.mysql_add.php';
|
||||||
|
|
||||||
@@ -178,14 +180,16 @@ if ($page == 'overview' || $page == 'mysqls') {
|
|||||||
'page' => $page
|
'page' => $page
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
$dbservers_stmt = Database::query("SELECT COUNT(DISTINCT `dbserver`) as numservers FROM `" . TABLE_PANEL_DATABASES . "`");
|
$mysql_servers = [];
|
||||||
$dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC);
|
try {
|
||||||
$count_mysql_servers = $dbserver['numservers'];
|
$result_json = MysqlServer::getLocal($userinfo)->listing();
|
||||||
|
$result_decoded = json_decode($result_json, true)['data']['list'];
|
||||||
Database::needRoot(true, $result['dbserver']);
|
foreach ($result_decoded as $dbserver => $dbdata) {
|
||||||
Database::needSqlData();
|
$mysql_servers[$dbserver] = $dbdata['caption'] . ' (' . $dbdata['host'] . (isset($dbdata['port']) && !empty($dbdata['port']) ? ':' . $dbdata['port'] : '').')';
|
||||||
$sql_root = Database::getSqlData();
|
}
|
||||||
Database::needRoot(false);
|
} catch (Exception $e) {
|
||||||
|
/* just none */
|
||||||
|
}
|
||||||
|
|
||||||
$mysql_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/mysql/formfield.mysql_edit.php';
|
$mysql_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/mysql/formfield.mysql_edit.php';
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ CREATE TABLE `panel_customers` (
|
|||||||
`data_2fa` varchar(25) NOT NULL default '',
|
`data_2fa` varchar(25) NOT NULL default '',
|
||||||
`api_allowed` tinyint(1) NOT NULL default '1',
|
`api_allowed` tinyint(1) NOT NULL default '1',
|
||||||
`logviewenabled` tinyint(1) NOT NULL default '0',
|
`logviewenabled` tinyint(1) NOT NULL default '0',
|
||||||
|
`allowed_mysqlserver` varchar(500) NOT NULL default '[0]',
|
||||||
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;
|
||||||
|
|||||||
@@ -62,6 +62,24 @@ if (Froxlor::isFroxlorVersion('0.10.99')) {
|
|||||||
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);
|
||||||
|
// new customer allowed_mysqlserver field
|
||||||
|
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `allowed_mysqlserver` varchar(500) NOT NULL default '[0]';");
|
||||||
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
Update::showUpdateStep("Checking for multiple mysql-servers to allow acccess to customers for existing databases");
|
||||||
|
$dbservers_stmt = Database::query("
|
||||||
|
SELECT `customerid`,
|
||||||
|
GROUP_CONCAT(DISTINCT `dbserver` SEPARATOR ',') as allowed_mysqlserver
|
||||||
|
FROM `" . TABLE_PANEL_DATABASES . "`
|
||||||
|
GROUP BY `customerid`;
|
||||||
|
");
|
||||||
|
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `allowed_mysqlserver` = :allowed_mysqlserver WHERE `customerid` = :customerid");
|
||||||
|
while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
if (isset($dbserver['allowed_mysqlserver']) && !empt($dbserver['allowed_mysqlserver'])) {
|
||||||
|
$allowed_mysqlserver = json_encode(explode(",", $dbserver['allowed_mysqlserver']));
|
||||||
|
Database::pexecute($upd_stmt, ['allowed_mysql_server' => $allowed_mysqlserver, 'customerid' => $dbserver['customerid']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,9 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* @param int $hosting_plan_id
|
* @param int $hosting_plan_id
|
||||||
* optional, specify a hosting-plan to set certain resource-values from the plan
|
* optional, specify a hosting-plan to set certain resource-values from the plan
|
||||||
* instead of specifying them
|
* instead of specifying them
|
||||||
|
* @param array $allowed_mysqlserver
|
||||||
|
* optional, array of IDs of defined mysql-servers the customer is allowed to use,
|
||||||
|
* default is to allow the default dbserver (id=0)
|
||||||
*
|
*
|
||||||
* @access admin
|
* @access admin
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
@@ -349,6 +352,13 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$logviewenabled = $this->getBoolParam('logviewenabled', true, 0);
|
$logviewenabled = $this->getBoolParam('logviewenabled', true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($mysqls == -1 || $mysqls > 0) {
|
||||||
|
$p_allowed_mysqlserver = $this->getParam('allowed_mysqlserver', true, [0]);
|
||||||
|
} else {
|
||||||
|
// mysql not allowed, so no mysql available for customer
|
||||||
|
$p_allowed_mysqlserver = [];
|
||||||
|
}
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
$name = Validate::validate($name, 'name', '', '', [], true);
|
$name = Validate::validate($name, 'name', '', '', [], true);
|
||||||
$firstname = Validate::validate($firstname, 'first name', '', '', [], true);
|
$firstname = Validate::validate($firstname, 'first name', '', '', [], true);
|
||||||
@@ -389,6 +399,15 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
}
|
}
|
||||||
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
|
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
|
||||||
|
|
||||||
|
$allowed_mysqlserver = array();
|
||||||
|
if (! empty($p_allowed_mysqlserver) && is_array($p_allowed_mysqlserver)) {
|
||||||
|
foreach ($p_allowed_mysqlserver as $allowed_ms) {
|
||||||
|
$allowed_ms = intval($allowed_ms);
|
||||||
|
$allowed_mysqlserver[] = $allowed_ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$allowed_mysqlserver = array_map('intval', $allowed_mysqlserver);
|
||||||
|
|
||||||
$diskspace = $diskspace * 1024;
|
$diskspace = $diskspace * 1024;
|
||||||
$traffic = $traffic * 1024 * 1024;
|
$traffic = $traffic * 1024 * 1024;
|
||||||
|
|
||||||
@@ -496,7 +515,8 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
'logviewenabled' => $logviewenabled,
|
'logviewenabled' => $logviewenabled,
|
||||||
'theme' => $_theme,
|
'theme' => $_theme,
|
||||||
'custom_notes' => $custom_notes,
|
'custom_notes' => $custom_notes,
|
||||||
'custom_notes_show' => $custom_notes_show
|
'custom_notes_show' => $custom_notes_show,
|
||||||
|
'allowed_mysqlserver' => empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver)
|
||||||
];
|
];
|
||||||
|
|
||||||
$ins_stmt = Database::prepare("
|
$ins_stmt = Database::prepare("
|
||||||
@@ -538,7 +558,8 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
`logviewenabled` = :logviewenabled,
|
`logviewenabled` = :logviewenabled,
|
||||||
`theme` = :theme,
|
`theme` = :theme,
|
||||||
`custom_notes` = :custom_notes,
|
`custom_notes` = :custom_notes,
|
||||||
`custom_notes_show` = :custom_notes_show
|
`custom_notes_show` = :custom_notes_show,
|
||||||
|
`allowed_mysqlserver`= :allowed_mysqlserver
|
||||||
");
|
");
|
||||||
Database::pexecute($ins_stmt, $ins_data, true, true);
|
Database::pexecute($ins_stmt, $ins_data, true, true);
|
||||||
|
|
||||||
@@ -717,8 +738,8 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
'USERNAME' => $loginname,
|
'USERNAME' => $loginname,
|
||||||
'PASSWORD' => $password,
|
'PASSWORD' => $password,
|
||||||
'SERVER_HOSTNAME' => $srv_hostname,
|
'SERVER_HOSTNAME' => $srv_hostname,
|
||||||
'SERVER_IP' => isset($srv_ip['ip']) ? $srv_ip['ip'] : '',
|
'SERVER_IP' => $srv_ip['ip'] ?? '',
|
||||||
'SERVER_PORT' => isset($srv_ip['port']) ? $srv_ip['port'] : '',
|
'SERVER_PORT' => $srv_ip['port'] ?? '',
|
||||||
'DOMAINNAME' => $_stdsubdomain
|
'DOMAINNAME' => $_stdsubdomain
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -726,12 +747,12 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$mail_subject = $this->getMailTemplate([
|
$mail_subject = $this->getMailTemplate([
|
||||||
'adminid' => $this->getUserDetail('adminid'),
|
'adminid' => $this->getUserDetail('adminid'),
|
||||||
'def_language' => $def_language
|
'def_language' => $def_language
|
||||||
], 'mails', 'createcustomer_subject', $replace_arr, $this->lng['mails']['createcustomer']['subject']);
|
], 'mails', 'createcustomer_subject', $replace_arr, lng('mails.createcustomer.subject'));
|
||||||
// get template for mail body
|
// get template for mail body
|
||||||
$mail_body = $this->getMailTemplate([
|
$mail_body = $this->getMailTemplate([
|
||||||
'adminid' => $this->getUserDetail('adminid'),
|
'adminid' => $this->getUserDetail('adminid'),
|
||||||
'def_language' => $def_language
|
'def_language' => $def_language
|
||||||
], 'mails', 'createcustomer_mailbody', $replace_arr, $this->lng['mails']['createcustomer']['mailbody']);
|
], 'mails', 'createcustomer_mailbody', $replace_arr, lng('mails.createcustomer.mailbody'));
|
||||||
|
|
||||||
$_mailerror = false;
|
$_mailerror = false;
|
||||||
$mailerr_msg = "";
|
$mailerr_msg = "";
|
||||||
@@ -984,6 +1005,9 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
* optional, whether to allow access to webserver access/error-logs, default 0 (false)
|
* optional, whether to allow access to webserver access/error-logs, default 0 (false)
|
||||||
* @param string $theme
|
* @param string $theme
|
||||||
* optional, change theme
|
* optional, change theme
|
||||||
|
* @param array $allowed_mysqlserver
|
||||||
|
* optional, array of IDs of defined mysql-servers the customer is allowed to use,
|
||||||
|
* default is to allow the default dbserver (id=0)
|
||||||
*
|
*
|
||||||
* @access admin, customer
|
* @access admin, customer
|
||||||
* @return string json-encoded array
|
* @return string json-encoded array
|
||||||
@@ -1044,6 +1068,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
$logviewenabled = $this->getBoolParam('logviewenabled', true, $result['logviewenabled']);
|
$logviewenabled = $this->getBoolParam('logviewenabled', true, $result['logviewenabled']);
|
||||||
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
|
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
|
||||||
$theme = $this->getParam('theme', true, $result['theme']);
|
$theme = $this->getParam('theme', true, $result['theme']);
|
||||||
|
$allowed_mysqlserver = $this->getParam('allowed_mysqlserver', true, json_decode($result['allowed_mysqlserver'], true));
|
||||||
} else {
|
} else {
|
||||||
// allowed parameters
|
// allowed parameters
|
||||||
$def_language = $this->getParam('def_language', true, $result['def_language']);
|
$def_language = $this->getParam('def_language', true, $result['def_language']);
|
||||||
@@ -1068,6 +1093,9 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
if (!empty($allowed_phpconfigs)) {
|
if (!empty($allowed_phpconfigs)) {
|
||||||
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
|
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
|
||||||
}
|
}
|
||||||
|
if (! empty($allowed_mysqlserver)) {
|
||||||
|
$allowed_mysqlserver = array_map('intval', $allowed_mysqlserver);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$def_language = Validate::validate($def_language, 'default language', '', '', [], true);
|
$def_language = Validate::validate($def_language, 'default language', '', '', [], true);
|
||||||
$theme = Validate::validate($theme, 'theme', '', '', [], true);
|
$theme = Validate::validate($theme, 'theme', '', '', [], true);
|
||||||
@@ -1088,6 +1116,9 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
Response::standardError('youcantallocatemorethanyouhave', '', true);
|
Response::standardError('youcantallocatemorethanyouhave', '', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate allowed_mysqls whether the customer has databases on a removed, now disallowed db-server and abort if true
|
||||||
|
// @todo
|
||||||
|
|
||||||
if ($email == '') {
|
if ($email == '') {
|
||||||
Response::standardError([
|
Response::standardError([
|
||||||
'stringisempty',
|
'stringisempty',
|
||||||
@@ -1305,7 +1336,8 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
'logviewenabled' => $logviewenabled,
|
'logviewenabled' => $logviewenabled,
|
||||||
'custom_notes' => $custom_notes,
|
'custom_notes' => $custom_notes,
|
||||||
'custom_notes_show' => $custom_notes_show,
|
'custom_notes_show' => $custom_notes_show,
|
||||||
'api_allowed' => $api_allowed
|
'api_allowed' => $api_allowed,
|
||||||
|
'allowed_mysqlserver' => empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver)
|
||||||
];
|
];
|
||||||
$upd_data = $upd_data + $admin_upd_data;
|
$upd_data = $upd_data + $admin_upd_data;
|
||||||
}
|
}
|
||||||
@@ -1347,7 +1379,8 @@ class Customers extends ApiCommand implements ResourceEntity
|
|||||||
`logviewenabled` = :logviewenabled,
|
`logviewenabled` = :logviewenabled,
|
||||||
`custom_notes` = :custom_notes,
|
`custom_notes` = :custom_notes,
|
||||||
`custom_notes_show` = :custom_notes_show,
|
`custom_notes_show` = :custom_notes_show,
|
||||||
`api_allowed` = :api_allowed";
|
`api_allowed` = :api_allowed,
|
||||||
|
`allowed_mysqlserver` = :allowed_mysqlserver";
|
||||||
$upd_query .= $admin_upd_query;
|
$upd_query .= $admin_upd_query;
|
||||||
}
|
}
|
||||||
$upd_query .= " WHERE `customerid` = :customerid";
|
$upd_query .= " WHERE `customerid` = :customerid";
|
||||||
|
|||||||
312
lib/Froxlor/Api/Commands/MysqlServer.php
Normal file
312
lib/Froxlor/Api/Commands/MysqlServer.php
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is part of the Froxlor project.
|
||||||
|
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you can also view it online at
|
||||||
|
* https://files.froxlor.org/misc/COPYING.txt
|
||||||
|
*
|
||||||
|
* @copyright the authors
|
||||||
|
* @author Froxlor team <team@froxlor.org>
|
||||||
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Froxlor\Api\Commands;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PDO;
|
||||||
|
use PDOException;
|
||||||
|
use Froxlor\Froxlor;
|
||||||
|
use Froxlor\Api\ApiCommand;
|
||||||
|
use Froxlor\Api\ResourceEntity;
|
||||||
|
use Froxlor\Validate\Validate;
|
||||||
|
|
||||||
|
class MysqlServer extends ApiCommand implements ResourceEntity
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check whether the user is allowed
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function validateAccess()
|
||||||
|
{
|
||||||
|
if ($this->isAdmin() == false || ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 0)) {
|
||||||
|
throw new Exception("You cannot access this resource", 405);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add a new mysql-server
|
||||||
|
*
|
||||||
|
* @param string $mysql_host
|
||||||
|
* ip/hostname of mysql-server
|
||||||
|
* @param string $mysql_port
|
||||||
|
* optional, port to connect to
|
||||||
|
* @param string $mysql_ca
|
||||||
|
* optional, path to certificate file
|
||||||
|
* @param string $mysql_verifycert
|
||||||
|
* optional, verify server certificate
|
||||||
|
* @param string $privileged_user
|
||||||
|
* privileged user on the mysql-server (must have GRANT privileges)
|
||||||
|
* @param string $privileged_password
|
||||||
|
* password of privileged user
|
||||||
|
* @param string $description
|
||||||
|
* optional, description for server
|
||||||
|
* @param bool $allow_all_customers
|
||||||
|
* optional add this configuration to the list of every existing customer's allowed-fpm-config list, default is false (no)
|
||||||
|
*
|
||||||
|
* @access admin
|
||||||
|
* @throws Exception
|
||||||
|
* @return string json-encoded array
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
$this->validateAccess();
|
||||||
|
|
||||||
|
$mysql_host = $this->getParam('mysql_host');
|
||||||
|
$mysql_port = $this->getParam('mysql_port', true, 3306);
|
||||||
|
$mysql_ca = $this->getParam('mysql_ca', true, '');
|
||||||
|
$mysql_verifycert = $this->getBoolParam('mysql_verifycert', true, 0);
|
||||||
|
$privileged_user = $this->getParam('privileged_user');
|
||||||
|
$privileged_password = $this->getParam('privileged_password');
|
||||||
|
$description = $this->getParam('description', true, '');
|
||||||
|
|
||||||
|
// validation
|
||||||
|
$mysql_host = Validate::validate_ip2($mysql_host, true, 'invalidip', true, true, false);
|
||||||
|
if ($mysql_host === false) {
|
||||||
|
$mysql_host = Validate::validateLocalHostname($mysql_host);
|
||||||
|
if ($mysql_host === false) {
|
||||||
|
$mysql_host = Validate::validateDomain($mysql_host);
|
||||||
|
if ($mysql_host === false) {
|
||||||
|
throw new Exception("Invalid mysql server ip/hostname", 406);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$mysql_port = Validate::validate($mysql_port, 'port', Validate::REGEX_PORT, '', [3306], true);
|
||||||
|
$privileged_password = Validate::validate($privileged_password, 'password', '', '', [], true);
|
||||||
|
$description = Validate::validate(trim($description), 'description', Validate::REGEX_DESC_TEXT, '', [], true);
|
||||||
|
|
||||||
|
// testing connection with given credentials
|
||||||
|
$options = array(
|
||||||
|
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET names utf8'
|
||||||
|
);
|
||||||
|
if (!empty($mysql_ca)) {
|
||||||
|
$options[PDO::MYSQL_ATTR_SSL_CA] = $mysql_ca;
|
||||||
|
$options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = (bool) $mysql_verifycert;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dsn = "mysql:host=" . $mysql_host . ";port=" . $mysql_port . ";";
|
||||||
|
try {
|
||||||
|
$db_test = new \PDO($dsn, $privileged_user, $privileged_password, $options);
|
||||||
|
unset($db_test);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
throw new Exception("Connection to given mysql database could not be established. Error-message: " . $e->getMessage(), $e->getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all data from lib/userdata
|
||||||
|
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||||
|
|
||||||
|
// le format
|
||||||
|
if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) {
|
||||||
|
$sql_root = array(
|
||||||
|
0 => array(
|
||||||
|
'caption' => 'Default',
|
||||||
|
'host' => $sql['host'],
|
||||||
|
'socket' => (isset($sql['socket']) ? $sql['socket'] : null),
|
||||||
|
'user' => $sql['root_user'],
|
||||||
|
'password' => $sql['root_password']
|
||||||
|
)
|
||||||
|
);
|
||||||
|
unset($sql['root_user']);
|
||||||
|
unset($sql['root_password']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add new values to sql_root array
|
||||||
|
$sql_root[] = [
|
||||||
|
'caption' => $description,
|
||||||
|
'host' => $mysql_host,
|
||||||
|
'port' => $mysql_port,
|
||||||
|
'user' => $privileged_user,
|
||||||
|
'password' => $privileged_password,
|
||||||
|
'ssl' => [
|
||||||
|
'caFile' => $mysql_ca ?? "",
|
||||||
|
'verifyServerCertificate' => $mysql_verifycert ?? false
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->generateNewUserData($sql, $sql_root);
|
||||||
|
return $this->response(['true']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove a mysql-server
|
||||||
|
*
|
||||||
|
* @param int $dbserver number of the mysql server
|
||||||
|
*
|
||||||
|
* @access admin
|
||||||
|
* @throws Exception
|
||||||
|
* @return string json-encoded array
|
||||||
|
*/
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
$this->validateAccess();
|
||||||
|
|
||||||
|
$dbserver = (int) $this->getParam('dbserver');
|
||||||
|
|
||||||
|
if ($dbserver == 0) {
|
||||||
|
throw new Exception('Cannot delete first/default mysql-server');
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo check whether the server is in use by any customer
|
||||||
|
|
||||||
|
// get all data from lib/userdata
|
||||||
|
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||||
|
|
||||||
|
if (!isset($sql_root[$dbserver])) {
|
||||||
|
throw new Exception('Mysql server not found', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($sql_root[$dbserver]);
|
||||||
|
|
||||||
|
$this->generateNewUserData($sql, $sql_root);
|
||||||
|
return $this->response(['true']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list available mysql-server
|
||||||
|
*
|
||||||
|
* @access admin, customer
|
||||||
|
* @return string json-encoded array
|
||||||
|
*/
|
||||||
|
public function listing()
|
||||||
|
{
|
||||||
|
// get all data from lib/userdata
|
||||||
|
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||||
|
|
||||||
|
// limit customer to its allowed servers
|
||||||
|
$allowed_mysqls = [];
|
||||||
|
if ($this->isAdmin() == false) {
|
||||||
|
$allowed_mysqls = json_decode($this->getUserDetail('allowed_mysqlserver'), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($sql_root as $index => $sqlrootdata) {
|
||||||
|
if ($this->isAdmin() == false) {
|
||||||
|
if ($allowed_mysqls === false || empty($allowed_mysqls)) {
|
||||||
|
break;
|
||||||
|
} elseif (!in_array($index, $allowed_mysqls)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// passwords will not be returned in any case for security reasons
|
||||||
|
unset($sqlrootdata['password']);
|
||||||
|
$result[$index] = $sqlrootdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->response(['list' => $result, 'count' => count($result)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the total number of mysql servers
|
||||||
|
*
|
||||||
|
* @access admin, customer
|
||||||
|
* @return string json-encoded array
|
||||||
|
*/
|
||||||
|
public function listingCount()
|
||||||
|
{
|
||||||
|
if ($this->isAdmin() == false) {
|
||||||
|
$allowed_mysqls = json_decode($this->getUserDetail('allowed_mysqlserver'), true);
|
||||||
|
if ($allowed_mysqls) {
|
||||||
|
return $this->response(count($allowed_mysqls));
|
||||||
|
}
|
||||||
|
return $this->response(0);
|
||||||
|
}
|
||||||
|
// get all data from lib/userdata
|
||||||
|
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||||
|
return $this->response(count($sql_root));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return info about a specific mysql-server
|
||||||
|
*
|
||||||
|
* @param int $dbserver
|
||||||
|
* index of the mysql-server
|
||||||
|
*
|
||||||
|
* @access admin
|
||||||
|
* @throws Exception
|
||||||
|
* @return string json-encoded array
|
||||||
|
*/
|
||||||
|
public function get()
|
||||||
|
{
|
||||||
|
$this->validateAccess();
|
||||||
|
|
||||||
|
$dbserver = (int) $this->getParam('dbserver');
|
||||||
|
|
||||||
|
// get all data from lib/userdata
|
||||||
|
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||||
|
|
||||||
|
if (!isset($sql_root[$dbserver])) {
|
||||||
|
throw new Exception('Mysql server not found', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($sql_root[$dbserver]['password']);
|
||||||
|
return $this->response($sql_root[$dbserver]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @TODO implement me
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
throw new Exception('@TODO Later', 303);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateNewUserData(array $sql, array $sql_root)
|
||||||
|
{
|
||||||
|
$content = '<?php' . PHP_EOL;
|
||||||
|
$content .= '//automatically generated userdata.inc.php for Froxlor' . PHP_EOL;
|
||||||
|
$content .= '$sql[\'host\']=\'' . $sql['host'] . '\';' . PHP_EOL;
|
||||||
|
$content .= '$sql[\'user\']=\'' . $sql['user'] . '\';' . PHP_EOL;
|
||||||
|
$content .= '$sql[\'password\']=\'' . $sql['password'] . '\';' . PHP_EOL;
|
||||||
|
$content .= '$sql[\'db\']=\'' . $sql['db'] . '\';' . PHP_EOL;
|
||||||
|
foreach ($sql_root as $index => $sqlroot_data) {
|
||||||
|
$content .= '// database server #' . ($index + 1) . PHP_EOL;
|
||||||
|
foreach ($sqlroot_data as $field => $value) {
|
||||||
|
// ssl-fields
|
||||||
|
if (is_array($value)) {
|
||||||
|
foreach ($value as $vfield => $vvalue) {
|
||||||
|
if ($vfield == 'verifyServerCertificate') {
|
||||||
|
$content .= '$sql_root[' . (int)$index . '][\'' . $field . '\'][\'' . $vfield . '\'] = ' . ($vvalue ? 'true' : 'false') . ';' . PHP_EOL;
|
||||||
|
} else {
|
||||||
|
$content .= '$sql_root[' . (int)$index . '][\'' . $field . '\'][\'' . $vfield . '\'] = \'' . $vvalue . '\';' . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($field == 'password') {
|
||||||
|
$content .= '$sql_root[' . (int)$index . '][\'' . $field . '\'] = <<<EOP
|
||||||
|
' . $value . '
|
||||||
|
EOP;' . PHP_EOL;
|
||||||
|
} else {
|
||||||
|
$content .= '$sql_root[' . (int)$index . '][\'' . $field . '\'] = \'' . $value . '\';' . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$content .= '$sql[\'debug\']=' . ($sql['debug'] ? 'true' : 'false') . ';' . PHP_EOL;
|
||||||
|
$content .= '?>' . PHP_EOL;
|
||||||
|
file_put_contents(Froxlor::getInstallDir() . "/lib/userdata.inc.php", $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -82,7 +82,7 @@ class DbManagerMySQL
|
|||||||
if (!$update) {
|
if (!$update) {
|
||||||
// create user
|
// create user
|
||||||
if ($p_encrypted) {
|
if ($p_encrypted) {
|
||||||
if (version_compare(Database::getAttribute(PDO::ATTR_SERVER_VERSION), '5.7.0', '<')) {
|
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.0', '<') || version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '10.0.0', '>=')) {
|
||||||
$stmt = Database::prepare("
|
$stmt = Database::prepare("
|
||||||
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY PASSWORD :password
|
CREATE USER '" . $username . "'@'" . $access_host . "' IDENTIFIED BY PASSWORD :password
|
||||||
");
|
");
|
||||||
@@ -109,7 +109,7 @@ class DbManagerMySQL
|
|||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
// set password
|
// set password
|
||||||
if (version_compare(Database::getAttribute(PDO::ATTR_SERVER_VERSION), '5.7.6', '<')) {
|
if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.6', '<') || version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '10.0.0', '>=')) {
|
||||||
if ($p_encrypted) {
|
if ($p_encrypted) {
|
||||||
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password");
|
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class Language
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load fallback from browser if nothing requested
|
// load fallback from browser if nothing requested
|
||||||
$iso = trim(substr(strtok(strtok($_SERVER['HTTP_ACCEPT_LANGUAGE'], ','), ';'), 0, 5));
|
$iso = trim(substr(strtok(strtok(($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en'), ','), ';'), 0, 5));
|
||||||
if (!self::$requestedLanguage && strlen($iso) == 2 && $iso !== self::$defaultLanguage) {
|
if (!self::$requestedLanguage && strlen($iso) == 2 && $iso !== self::$defaultLanguage) {
|
||||||
self::$lng = array_merge(self::$lng, self::loadLanguage($iso));
|
self::$lng = array_merge(self::$lng, self::loadLanguage($iso));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,16 +116,7 @@ class Response
|
|||||||
|
|
||||||
$error = '';
|
$error = '';
|
||||||
foreach ($errors as $single_error) {
|
foreach ($errors as $single_error) {
|
||||||
if (isset($lng['error'][$single_error])) {
|
$single_error = lng('error.'.$single_error, [htmlentities($replacer)]);
|
||||||
$single_error = $lng['error'][$single_error];
|
|
||||||
$single_error = strtr($single_error, [
|
|
||||||
'%s' => $replacer
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
$error = 'Unknown Error (' . $single_error . '): ' . $replacer;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($error)) {
|
if (empty($error)) {
|
||||||
$error = $single_error;
|
$error = $single_error;
|
||||||
} else {
|
} else {
|
||||||
@@ -181,11 +172,7 @@ class Response
|
|||||||
{
|
{
|
||||||
global $lng;
|
global $lng;
|
||||||
|
|
||||||
if (isset($lng['success'][$success_message])) {
|
$success_message = lng('success.'.$success_message, [htmlentities($replacer)]);
|
||||||
$success_message = strtr($lng['success'][$success_message], [
|
|
||||||
'%s' => htmlentities($replacer)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($throw_exception) {
|
if ($throw_exception) {
|
||||||
throw new Exception(strip_tags($success_message), 200);
|
throw new Exception(strip_tags($success_message), 200);
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ return [
|
|||||||
'type' => 'label',
|
'type' => 'label',
|
||||||
'value' => $result['databasename']
|
'value' => $result['databasename']
|
||||||
],
|
],
|
||||||
|
'mysql_server' => [
|
||||||
|
'visible' => count($mysql_servers) > 1,
|
||||||
|
'label' => lng('mysql.mysql_server'),
|
||||||
|
'type' => 'label',
|
||||||
|
'value' => $mysql_servers[$result['dbserver']] ?? 'unknown db server'
|
||||||
|
],
|
||||||
'description' => [
|
'description' => [
|
||||||
'label' => lng('mysql.databasedescription'),
|
'label' => lng('mysql.databasedescription'),
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'value' => $result['description']
|
'value' => $result['description']
|
||||||
],
|
],
|
||||||
'mysql_server' => [
|
|
||||||
'visible' => $count_mysql_servers > 1,
|
|
||||||
'label' => lng('mysql.mysql_server'),
|
|
||||||
'type' => 'label',
|
|
||||||
'value' => $sql_root['caption']
|
|
||||||
],
|
|
||||||
'mysql_password' => [
|
'mysql_password' => [
|
||||||
'label' => lng('changepassword.new_password_ifnotempty'),
|
'label' => lng('changepassword.new_password_ifnotempty'),
|
||||||
'type' => 'password',
|
'type' => 'password',
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ class MysqlsTest extends TestCase
|
|||||||
$dbm = new \Froxlor\Database\DbManager(\Froxlor\FroxlorLogger::getInstanceOf());
|
$dbm = new \Froxlor\Database\DbManager(\Froxlor\FroxlorLogger::getInstanceOf());
|
||||||
$users = $dbm->getManager()->getAllSqlUsers(false);
|
$users = $dbm->getManager()->getAllSqlUsers(false);
|
||||||
foreach ($users as $user => $data) {
|
foreach ($users as $user => $data) {
|
||||||
if (TRAVIS_CI == 1 && strtolower($user) == 'mariadb.sys') {
|
if (strtolower($user) == 'mariadb.sys') {
|
||||||
// travis seems to have a user for mariadb on version 10.4
|
// travis seems to have a user for mariadb on version 10.4
|
||||||
// we do not want to test that one
|
// we do not want to test that one
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ class FpmDaemonsTest extends TestCase
|
|||||||
global $admin_userdata;
|
global $admin_userdata;
|
||||||
$data = [
|
$data = [
|
||||||
'description' => 'test2 fpm',
|
'description' => 'test2 fpm',
|
||||||
'reload_cmd' => 'service php7.4-fpm reload',
|
'reload_cmd' => 'service php8.1-fpm reload',
|
||||||
'config_dir' => '/etc/php/7.4/fpm/pool.d',
|
'config_dir' => '/etc/php/8.1/fpm/pool.d',
|
||||||
'limit_extensions' => ''
|
'limit_extensions' => ''
|
||||||
];
|
];
|
||||||
$json_result = FpmDaemons::getLocal($admin_userdata, $data)->add();
|
$json_result = FpmDaemons::getLocal($admin_userdata, $data)->add();
|
||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
$this->assertEquals('/etc/php/7.4/fpm/pool.d/', $result['config_dir']);
|
$this->assertEquals('/etc/php/8.1/fpm/pool.d/', $result['config_dir']);
|
||||||
$this->assertEquals('dynamic', $result['pm']);
|
$this->assertEquals('dynamic', $result['pm']);
|
||||||
$this->assertEquals(5, $result['max_children']);
|
$this->assertEquals(5, $result['max_children']);
|
||||||
$this->assertEquals('.php', $result['limit_extensions']);
|
$this->assertEquals('.php', $result['limit_extensions']);
|
||||||
@@ -77,7 +77,7 @@ class FpmDaemonsTest extends TestCase
|
|||||||
];
|
];
|
||||||
$json_result = FpmDaemons::getLocal($admin_userdata, $data)->update();
|
$json_result = FpmDaemons::getLocal($admin_userdata, $data)->update();
|
||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
$this->assertEquals('/etc/php/7.4/fpm/pool.d/', $result['config_dir']);
|
$this->assertEquals('/etc/php/8.1/fpm/pool.d/', $result['config_dir']);
|
||||||
$this->assertEquals(10, $result['max_children']);
|
$this->assertEquals(10, $result['max_children']);
|
||||||
$this->assertEquals('.php .php.xml', $result['limit_extensions']);
|
$this->assertEquals('.php .php.xml', $result['limit_extensions']);
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ class FpmDaemonsTest extends TestCase
|
|||||||
];
|
];
|
||||||
$json_result = FpmDaemons::getLocal($admin_userdata, $data)->delete();
|
$json_result = FpmDaemons::getLocal($admin_userdata, $data)->delete();
|
||||||
$result = json_decode($json_result, true)['data'];
|
$result = json_decode($json_result, true)['data'];
|
||||||
$this->assertEquals('/etc/php/7.4/fpm/pool.d/', $result['config_dir']);
|
$this->assertEquals('/etc/php/8.1/fpm/pool.d/', $result['config_dir']);
|
||||||
$this->assertEquals(10, $result['max_children']);
|
$this->assertEquals(10, $result['max_children']);
|
||||||
$this->assertEquals('.php', $result['limit_extensions']);
|
$this->assertEquals('.php', $result['limit_extensions']);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ file_put_contents($userdata, $userdata_content);
|
|||||||
|
|
||||||
// include autoloader / api / etc
|
// include autoloader / api / etc
|
||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
// include functions
|
||||||
|
require dirname(__DIR__) . '/lib/functions.php';
|
||||||
// include table definitions
|
// include table definitions
|
||||||
require dirname(__DIR__) . '/lib/tables.inc.php';
|
require dirname(__DIR__) . '/lib/tables.inc.php';
|
||||||
|
|
||||||
@@ -50,7 +51,9 @@ if (TRAVIS_CI == 0) {
|
|||||||
Database::needRoot(true);
|
Database::needRoot(true);
|
||||||
Database::query("DROP DATABASE IF EXISTS `froxlor010`;");
|
Database::query("DROP DATABASE IF EXISTS `froxlor010`;");
|
||||||
Database::query("CREATE DATABASE `froxlor010`;");
|
Database::query("CREATE DATABASE `froxlor010`;");
|
||||||
exec("mysql -u root -p" . $rpwd . " froxlor010 < " . dirname(__DIR__) . "/install/froxlor.sql");
|
$sql = include(dirname(__DIR__) . "/install/froxlor.sql.php");
|
||||||
|
file_put_contents("/tmp/froxlor.sql", $sql);
|
||||||
|
exec("mysql -u root -p" . $rpwd . " froxlor010 < /tmp/froxlor.sql");
|
||||||
Database::query("DROP USER IF EXISTS 'test1sql1'@'localhost';");
|
Database::query("DROP USER IF EXISTS 'test1sql1'@'localhost';");
|
||||||
Database::query("DROP USER IF EXISTS 'test1sql1'@'127.0.0.1';");
|
Database::query("DROP USER IF EXISTS 'test1sql1'@'127.0.0.1';");
|
||||||
Database::query("DROP USER IF EXISTS 'test1sql1'@'172.17.0.1';");
|
Database::query("DROP USER IF EXISTS 'test1sql1'@'172.17.0.1';");
|
||||||
|
|||||||
Reference in New Issue
Block a user