From dd83e9c50f5a1ef77c892e783a9095e89832d222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Tue, 5 Nov 2024 14:59:24 -0300 Subject: [PATCH 1/2] Backport DatabaseInterface factory for tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - aa829af98c0eeec32037d5ddf9acc34b7337bd04 - a9de97939719889579cf41e3f6d3328d178b9b95 Signed-off-by: MaurĂ­cio Meneghini Fauth --- test/classes/AbstractTestCase.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/classes/AbstractTestCase.php b/test/classes/AbstractTestCase.php index e273025dcf..d8df780a3f 100644 --- a/test/classes/AbstractTestCase.php +++ b/test/classes/AbstractTestCase.php @@ -8,6 +8,7 @@ use PhpMyAdmin\Cache; use PhpMyAdmin\Config; use PhpMyAdmin\Core; use PhpMyAdmin\DatabaseInterface; +use PhpMyAdmin\Dbal\DbiExtension; use PhpMyAdmin\LanguageManager; use PhpMyAdmin\SqlParser\Translator; use PhpMyAdmin\Tests\Stubs\DbiDummy; @@ -101,6 +102,16 @@ abstract class AbstractTestCase extends TestCase Cache::purge(); } + protected function createDatabaseInterface(?DbiExtension $extension = null): DatabaseInterface + { + return new DatabaseInterface($extension ?? $this->createDbiDummy()); + } + + protected function createDbiDummy(): DbiDummy + { + return new DbiDummy(); + } + protected function assertAllQueriesConsumed(): void { $unUsedQueries = $this->dummyDbi->getUnUsedQueries(); From f6ce16929006fb4e7b628252e80f5a6b565528d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Tue, 5 Nov 2024 15:09:21 -0300 Subject: [PATCH 2/2] Fix issue when updating privs for various databases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sql_query global variable should be a string, and it can be a string in this case, which will cause an error as the string will not be converted to array. Signed-off-by: MaurĂ­cio Meneghini Fauth --- .../Server/PrivilegesController.php | 5 +- libraries/classes/Server/Privileges.php | 3 +- .../Server/PrivilegesControllerTest.php | 65 +++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 test/classes/Controllers/Server/PrivilegesControllerTest.php diff --git a/libraries/classes/Controllers/Server/PrivilegesController.php b/libraries/classes/Controllers/Server/PrivilegesController.php index eb0bf43a52..866f6403da 100644 --- a/libraries/classes/Controllers/Server/PrivilegesController.php +++ b/libraries/classes/Controllers/Server/PrivilegesController.php @@ -234,8 +234,9 @@ class PrivilegesController extends AbstractController */ if (! empty($_POST['update_privs'])) { if (is_array($dbname)) { + $statements = []; foreach ($dbname as $key => $db_name) { - [$sql_query[$key], $message] = $serverPrivileges->updatePrivileges( + [$statements[$key], $message] = $serverPrivileges->updatePrivileges( ($username ?? ''), ($hostname ?? ''), ($tablename ?? ($routinename ?? '')), @@ -244,7 +245,7 @@ class PrivilegesController extends AbstractController ); } - $sql_query = implode("\n", $sql_query); + $sql_query = implode("\n", $statements); } else { [$sql_query, $message] = $serverPrivileges->updatePrivileges( ($username ?? ''), diff --git a/libraries/classes/Server/Privileges.php b/libraries/classes/Server/Privileges.php index 1e33c37dde..67c7cca9c0 100644 --- a/libraries/classes/Server/Privileges.php +++ b/libraries/classes/Server/Privileges.php @@ -2539,7 +2539,7 @@ class Privileges $message = null; $queries = null; $queriesForDisplay = null; - $sqlQuery = null; + $sqlQuery = ''; if (! isset($_POST['adduser_submit']) && ! isset($_POST['change_copy'])) { return [ @@ -2551,7 +2551,6 @@ class Privileges ]; } - $sqlQuery = ''; // Some reports where sent to the error reporting server with phpMyAdmin 5.1.0 // pred_username was reported to be not defined $predUsername = $_POST['pred_username'] ?? ''; diff --git a/test/classes/Controllers/Server/PrivilegesControllerTest.php b/test/classes/Controllers/Server/PrivilegesControllerTest.php new file mode 100644 index 0000000000..540945ef1b --- /dev/null +++ b/test/classes/Controllers/Server/PrivilegesControllerTest.php @@ -0,0 +1,65 @@ +createDbiDummy(); + $dbiDummy->addSelectDb('mysql'); + // phpcs:disable Generic.Files.LineLength.TooLong + $dbiDummy->addResult('SHOW GRANTS FOR CURRENT_USER();', [['GRANT ALL PRIVILEGES ON *.* TO `pma_test`@`localhost` WITH GRANT OPTION']], ['Grants for pma_test@localhost']); + $dbiDummy->addResult('SHOW GRANTS FOR CURRENT_USER();', [['GRANT ALL PRIVILEGES ON *.* TO `pma_test`@`localhost` WITH GRANT OPTION']], ['Grants for pma_test@localhost']); + $dbiDummy->addResult("REVOKE ALL PRIVILEGES ON `test_db_1`.* FROM 'pma_test'@'localhost';", []); + $dbiDummy->addResult("REVOKE GRANT OPTION ON `test_db_1`.* FROM 'pma_test'@'localhost';", []); + $dbiDummy->addResult("GRANT SELECT ON `test_db_1`.* TO 'pma_test'@'localhost';", []); + $dbiDummy->addResult("REVOKE ALL PRIVILEGES ON `test_db_2`.* FROM 'pma_test'@'localhost';", []); + $dbiDummy->addResult("REVOKE GRANT OPTION ON `test_db_2`.* FROM 'pma_test'@'localhost';", []); + $dbiDummy->addResult("GRANT SELECT ON `test_db_2`.* TO 'pma_test'@'localhost';", []); + $dbiDummy->addResult("SELECT '1' FROM `mysql`.`user` WHERE `User` = 'pma_test' AND `Host` = 'localhost';", [['1']]); + $dbiDummy->addResult("SELECT * FROM `mysql`.`db` WHERE `User` = 'pma_test' AND `Host` = 'localhost' AND `Db` = 'test_db_1'", []); + $dbiDummy->addResult('SHOW COLUMNS FROM `mysql`.`db`;', [['Host', 'char(255)', 'NO', 'PRI', '', ''], ['Db', 'char(64)', 'NO', 'PRI', '', ''], ['User', 'char(128)', 'NO', 'PRI', '', ''], ['Select_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Insert_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Update_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Delete_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Create_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Drop_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Grant_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['References_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Index_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Alter_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Create_tmp_table_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Lock_tables_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Create_view_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Show_view_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Create_routine_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Alter_routine_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Execute_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Event_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Trigger_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Delete_history_priv', "enum('N','Y')", 'NO', '', 'N', ''], ['Show_create_routine_priv', "enum('N','Y')", 'NO', '', 'N', '']], ['Field', 'Type', 'Null', 'Key', 'Default', 'Extra']); + // phpcs:enable + + $GLOBALS['dbi'] = $dbi = $this->createDatabaseInterface($dbiDummy); + $responseRenderer = new ResponseRenderer(); + + $GLOBALS['dblist'] = (object) ['databases' => ['test_db_1', 'test_db_2']]; + + $controller = new PrivilegesController($responseRenderer, new Template(), new Relation($dbi), $dbi); + $controller(); + + $output = $responseRenderer->getHTMLResult(); + self::assertStringContainsString("You have updated the privileges for 'pma_test'@'localhost'.", $output); + + // phpcs:disable Generic.Files.LineLength.TooLong + $expectedSql = '
' . "\n"
+            . "REVOKE ALL PRIVILEGES ON  `test_db_1`.* FROM 'pma_test'@'localhost'; REVOKE GRANT OPTION ON  `test_db_1`.* FROM 'pma_test'@'localhost'; GRANT SELECT ON  `test_db_1`.* TO 'pma_test'@'localhost'; \n"
+            . "REVOKE ALL PRIVILEGES ON  `test_db_2`.* FROM 'pma_test'@'localhost'; REVOKE GRANT OPTION ON  `test_db_2`.* FROM 'pma_test'@'localhost'; GRANT SELECT ON  `test_db_2`.* TO 'pma_test'@'localhost'; \n"
+            . '
'; + // phpcs:enable + self::assertStringContainsString($expectedSql, $output); + + $this->assertAllSelectsConsumed(); + $this->assertAllQueriesConsumed(); + } +}