From 449897039c1ebc31ef8ad92c9e91c1bc30ce6063 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Fri, 29 Apr 2022 16:53:01 +0200 Subject: [PATCH] add testing for mysql-server/customer-update of allowed_mysqlserver; beautify config-command/file details Signed-off-by: Michael Kaufmann --- .github/workflows/build-mariadb.yml | 2 +- .github/workflows/build-mysql.yml | 2 +- lib/Froxlor/Api/ApiCommand.php | 2 +- lib/Froxlor/Api/Commands/Customers.php | 16 ++++++++- lib/Froxlor/Api/Commands/MysqlServer.php | 26 +++++++++++++++ lib/Froxlor/Api/Commands/SubDomains.php | 2 +- lng/de.lng.php | 1 + lng/en.lng.php | 1 + .../Froxlor/settings/conf/command.html.twig | 2 +- .../Froxlor/settings/conf/file.html.twig | 4 +-- .../Froxlor/settings/conf/fileblock.html.twig | 2 +- tests/Mysqls/MysqlsTest.php | 33 +++++++++++++++++++ 12 files changed, 84 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-mariadb.yml b/.github/workflows/build-mariadb.yml index 4c13b709..de584685 100644 --- a/.github/workflows/build-mariadb.yml +++ b/.github/workflows/build-mariadb.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['7.4', '8.0'] + php-versions: ['7.4', '8.1'] mariadb-version: [10.5, 10.4] steps: - name: Checkout diff --git a/.github/workflows/build-mysql.yml b/.github/workflows/build-mysql.yml index 7e3f4fe9..d23e452c 100644 --- a/.github/workflows/build-mysql.yml +++ b/.github/workflows/build-mysql.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['7.4', '8.0'] + php-versions: ['7.4', '8.1'] mysql-version: [8.0, 5.7] steps: - name: Checkout diff --git a/lib/Froxlor/Api/ApiCommand.php b/lib/Froxlor/Api/ApiCommand.php index 5ee3f2c6..680ce36f 100644 --- a/lib/Froxlor/Api/ApiCommand.php +++ b/lib/Froxlor/Api/ApiCommand.php @@ -479,7 +479,7 @@ abstract class ApiCommand extends ApiParameter { $customer_ids = []; if ($this->isAdmin()) { - // if we're an admin, list all ftp-users of all the admins customers + // if we're an admin, list all of the admins customers // or optionally for one specific customer identified by id or loginname $customerid = $this->getParam('customerid', true, 0); $loginname = $this->getParam('loginname', true, ''); diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index de71e514..edf8fb36 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -1117,7 +1117,21 @@ class Customers extends ApiCommand implements ResourceEntity } // validate allowed_mysqls whether the customer has databases on a removed, now disallowed db-server and abort if true - // @todo + $former_allowed_mysqlserver = json_decode($result['allowed_mysqlserver'], true); + if ($allowed_mysqlserver != $former_allowed_mysqlserver) { + $to_remove_mysqlserver = array_diff($former_allowed_mysqlserver, $allowed_mysqlserver); + if (count($to_remove_mysqlserver) > 0) { + foreach ($to_remove_mysqlserver as $mysqlserver_check) { + $result_ms = $this->apiCall('MysqlServer.databasesOnServer', [ + 'mysql_server' => $mysqlserver_check, + 'customerid' => $id + ]); + if ($result_ms['count'] > 0) { + Response::standardError('mysqlserverstillhasdbs', '', true); + } + } + } + } if ($email == '') { Response::standardError([ diff --git a/lib/Froxlor/Api/Commands/MysqlServer.php b/lib/Froxlor/Api/Commands/MysqlServer.php index c070f4b5..60885e48 100644 --- a/lib/Froxlor/Api/Commands/MysqlServer.php +++ b/lib/Froxlor/Api/Commands/MysqlServer.php @@ -31,6 +31,7 @@ use PDOException; use Froxlor\Froxlor; use Froxlor\Api\ApiCommand; use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; use Froxlor\Validate\Validate; class MysqlServer extends ApiCommand implements ResourceEntity @@ -274,6 +275,31 @@ class MysqlServer extends ApiCommand implements ResourceEntity throw new Exception('@TODO Later', 303); } + /** + * check whether a given customer / current user (as customer) has + * databases on the given dbserver + * + * @param int mysql_server + * @param int $customerid + * optional, admin-only, select ftp-users of a specific customer by id + * @param string $loginname + * optional, admin-only, select ftp-users of a specific customer by loginname + * + * @access admin, customer + * @return string json-encoded array count + */ + public function databasesOnServer() + { + $dbserver = $this->getParam('mysql_server'); + $customer_ids = $this->getAllowedCustomerIds(); + + $result_stmt = Database::prepare(" + SELECT COUNT(*) num_dbs FROM `" . TABLE_PANEL_DATABASES . "` + WHERE `customerid` IN (" . implode(", ", $customer_ids) . ") AND `dbserver` = :dbserver"); + $result = Database::pexecute_first($result_stmt, ['dbserver' => $dbserver], true, true); + return $this->response(['count' => $result['num_dbs']]); + } + private function generateNewUserData(array $sql, array $sql_root) { $content = 'isAdmin()) { - // if we're an admin, list all databases of all the admins customers + // if we're an admin, list all subdomains of all the admins customers // or optionally for one specific customer identified by id or loginname $customerid = $this->getParam('customerid', true, 0); $loginname = $this->getParam('loginname', true, ''); diff --git a/lng/de.lng.php b/lng/de.lng.php index 9ee02658..3a089de4 100644 --- a/lng/de.lng.php +++ b/lng/de.lng.php @@ -874,6 +874,7 @@ return [ 'invaliddnsforletsencrypt' => 'Die DNS-Einträge der Domain enhalten keine der gewählten IP Adressen. Let\'s Encrypt Zertifikats-Erstellung ist nicht möglich.', 'notallowedphpconfigused' => 'Nutzung einer PHP-Konfiguration welche nicht dem Kunden zugeordnet ist', 'pathmustberelative' => 'Der Benutzer hat nicht die benötigten Berechtigungen, um Pfade außerhalb des Kunden-Heimatverzeichnisses anzugeben. Bitte einen relativen Pfad angeben (kein führendes /).', + 'mysqlserverstillhasdbs' => 'Datenbank-Server kann für den Kunden nicht entfernt werden, da sich dort noch Datenbanken befinden.', ], 'extras' => [ 'description' => 'Hier können Sie zusätzliche Extras einrichten, wie zum Beispiel einen Verzeichnisschutz.
Die Änderungen sind erst nach einer kurzen Zeit wirksam.', diff --git a/lng/en.lng.php b/lng/en.lng.php index d8ef16d3..ca642f2d 100644 --- a/lng/en.lng.php +++ b/lng/en.lng.php @@ -1171,6 +1171,7 @@ return [ 'invaliddnsforletsencrypt' => 'The domains DNS does not include any of the chosen IP addresses. Let\'s Encrypt certificate generation not possible.', 'notallowedphpconfigused' => 'Trying to use php-config which is not assigned to customer', 'pathmustberelative' => 'The user does not have the permission to specify directories outside the customers home-directory. Please specify a relative path (no leading /).', + 'mysqlserverstillhasdbs' => 'Cannot remove database server from customers allow-list as there are still databases on it.', ], 'extras' => [ 'description' => 'Here you can add some extras, for example directory protection.
The system will need some time to apply the new settings after every change.', diff --git a/templates/Froxlor/settings/conf/command.html.twig b/templates/Froxlor/settings/conf/command.html.twig index 97514312..20f9aecb 100644 --- a/templates/Froxlor/settings/conf/command.html.twig +++ b/templates/Froxlor/settings/conf/command.html.twig @@ -1 +1 @@ - + diff --git a/templates/Froxlor/settings/conf/file.html.twig b/templates/Froxlor/settings/conf/file.html.twig index ce850874..36077b46 100644 --- a/templates/Froxlor/settings/conf/file.html.twig +++ b/templates/Froxlor/settings/conf/file.html.twig @@ -1,2 +1,2 @@ - - + + diff --git a/templates/Froxlor/settings/conf/fileblock.html.twig b/templates/Froxlor/settings/conf/fileblock.html.twig index 6efa0bb7..2fc45e0f 100644 --- a/templates/Froxlor/settings/conf/fileblock.html.twig +++ b/templates/Froxlor/settings/conf/fileblock.html.twig @@ -1,5 +1,5 @@
- {{ realname }} + {# {{ realname }} #} {{ commands_pre|raw }} {{ commands_file|raw }} {{ commands_post|raw }} diff --git a/tests/Mysqls/MysqlsTest.php b/tests/Mysqls/MysqlsTest.php index 10a31bcf..e2800d27 100644 --- a/tests/Mysqls/MysqlsTest.php +++ b/tests/Mysqls/MysqlsTest.php @@ -5,6 +5,7 @@ use Froxlor\Settings; use Froxlor\Api\Commands\Admins; use Froxlor\Api\Commands\Customers; use Froxlor\Api\Commands\Mysqls; +use Froxlor\Api\Commands\MysqlServer; use Froxlor\Database\Database; use Froxlor\Settings\Store; @@ -13,6 +14,7 @@ use Froxlor\Settings\Store; * @covers \Froxlor\Api\ApiCommand * @covers \Froxlor\Api\ApiParameter * @covers \Froxlor\Api\Commands\Mysqls + * @covers \Froxlor\Api\Commands\MysqlServer * @covers \Froxlor\Api\Commands\Customers * @covers \Froxlor\Api\Commands\Admins * @covers \Froxlor\Database\DbManager @@ -212,6 +214,36 @@ class MysqlsTest extends TestCase $json_result = Mysqls::getLocal($customer_userdata)->listingCount(); $result = json_decode($json_result, true)['data']; $this->assertEquals(2, $result); + + $data = [ + 'mysql_server' => '0' + ]; + $json_result = MysqlServer::getLocal($admin_userdata, $data)->databasesOnServer(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals('2', $result['count']); + + $data = [ + 'mysql_server' => '1' + ]; + $json_result = MysqlServer::getLocal($admin_userdata, $data)->databasesOnServer(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals('0', $result['count']); + } + + /** + * @depends testCustomerMysqlsList + */ + public function testUpdateCustomerAllowedMysqlWithExistingDbs() + { + global $admin_userdata; + + $this->expectExceptionMessage("Cannot remove database server from customers allow-list as there are still databases on it."); + // reactivate customer + // get customer + Customers::getLocal($admin_userdata, array( + 'loginname' => 'test1', + 'allowed_mysqls' => [1] + ))->update(); } /** @@ -315,4 +347,5 @@ class MysqlsTest extends TestCase $this->assertEquals($testdata['password'], $passwd); } } + }