From 85564013873f7c3545ca6607d778e5658934928f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Su=C3=A1rez?= Date: Fri, 12 Apr 2024 15:43:08 -0600 Subject: [PATCH] Extra validatons on Schema Check --- pandora_console/extensions/db_status.php | 280 ++++++++++++++++++++--- 1 file changed, 252 insertions(+), 28 deletions(-) diff --git a/pandora_console/extensions/db_status.php b/pandora_console/extensions/db_status.php index 07d367f3ab..ad7fa4cfc3 100755 --- a/pandora_console/extensions/db_status.php +++ b/pandora_console/extensions/db_status.php @@ -50,10 +50,14 @@ function extension_db_status() } ui_print_info_message( - __('This extension checks the DB is correct. Because sometimes the old DB from a migration has not some fields in the tables or the data is changed.') - ); - ui_print_info_message( - __('At the moment the checks is for MySQL/MariaDB.') + " - " . + __('This extension checks the DB is correct. Because sometimes the old DB from a migration has not some fields in the tables or the data is changed.') . + "
" . + " - " . + __('At the moment the checks is for MySQL/MariaDB.') . + "
" . + " - " . + __('User must have Select, Drop, Create and References privileges.') ); echo "
"; @@ -164,6 +168,16 @@ function extension_db_status_execute_checks($db_user, $db_password, $db_host, $d $db_name = explode(' ', $db_name); $db_name = $db_name[0]; + if (!$db_host) { + ui_print_error_message(__('A host must be provided')); + return; + } + + if (!$db_name) { + ui_print_error_message(__('A DB name must be provided')); + return; + } + try { if ($config['mysqli']) { $connection_test = mysqli_connect($db_host, $db_user, $db_password); @@ -196,6 +210,10 @@ function extension_db_status_execute_checks($db_user, $db_password, $db_host, $d return; } + if (check_drop_privileges($connection_test) == 0) { + return; + } + try { if ($config['mysqli']) { $create_db = mysqli_query($connection_test, "CREATE DATABASE `$db_name`"); @@ -211,10 +229,28 @@ function extension_db_status_execute_checks($db_user, $db_password, $db_host, $d return; } - if ($config['mysqli'] === true) { - mysqli_select_db($connection_test, $db_name); - } else { - mysql_select_db($db_name, $connection_test); + if (check_ref_privileges($connection_test) == 0) { + drop_database($connection_test, $db_name); + ui_print_error_message(__("Unable to create references with the provided user please check its privileges")); + return; + } + + if (check_explain_privileges($connection_test) == 0) { + drop_database($connection_test, $db_name); + ui_print_error_message(__("Unable to explain with the provided user please check its privileges")); + return; + } + + try { + if ($config['mysqli'] === true) { + mysqli_select_db($connection_test, $db_name); + } else { + mysql_select_db($db_name, $connection_test); + } + } catch (Exception $e) { + drop_database($connection_test, $db_name); + ui_print_error_message(__('There was an error selecting the DB')); + return; } $install_tables = extension_db_status_execute_sql_file( @@ -234,14 +270,7 @@ function extension_db_status_execute_checks($db_user, $db_password, $db_host, $d $config['dbname'] ); - - if ($config['mysqli'] === true) { - mysqli_select_db($connection_test, $db_name); - mysqli_query($connection_test, "DROP DATABASE IF EXISTS `$db_name`"); - } else { - mysql_select_db($db_name, $connection_test); - mysql_query("DROP DATABASE IF EXISTS `$db_name`", $connection_test); - } + drop_database($connection_test, $db_name); } @@ -512,19 +541,15 @@ function extension_db_status_execute_sql_file($url, $connection) $query .= $sql_line; if (preg_match("/;[\040]*\$/", $sql_line)) { if ($config['mysqli'] === true) { - if (!$result = mysqli_query($connection, $query)) { - echo mysqli_error(); - // Uncomment for debug - echo "
$query
"; - return 0; - } + $result = mysqli_query($connection, $query); } else { - if (!$result = mysql_query($query, $connection)) { - echo mysql_error(); - // Uncomment for debug - echo "
$query
"; - return 0; - } + $result = mysql_query($query, $connection); + } + if (!$result) { + echo mysqli_error($connection); + // Uncomment for debug + echo "
$query
"; + return 0; } $query = ''; @@ -539,5 +564,204 @@ function extension_db_status_execute_sql_file($url, $connection) } +function check_explain_privileges($connection) +{ + global $config; + $has_privileges = 1; + + $explain_check= "EXPLAIN tb1"; + + $create_tb1= "CREATE TABLE tb1 ( + id INT AUTO_INCREMENT PRIMARY KEY + )"; + + drop_database($connection, 'pandora_tmp_privilege_check'); + + try { + if ($config['mysqli']) { + mysqli_query($connection, "CREATE DATABASE `pandora_tmp_privilege_check`"); + } else { + mysql_query("CREATE DATABASE `pandora_tmp_privilege_check`", $connection); + } + } catch (Exception $e) { + ui_print_error_message(__('There was an error creating the DB during reference check')); + return 0; + } + + try { + if ($config['mysqli'] === true) { + mysqli_select_db($connection, "pandora_tmp_privilege_check"); + } else { + mysql_select_db("reference_check", $connection); + } + } catch (Exception $e) { + ui_print_error_message(__('There was an error selecting the DB during reference check')); + return 0; + } + + try { + if ($config['mysqli'] === true) { + $result = mysqli_query($connection, $create_tb1); + } else { + $result = mysql_query($create_tb1, $connection); + } + + if(!$result){ + throw new Exception("Error on explain check: " . $connection->error); + } + + if ($config['mysqli'] === true) { + $result = mysqli_query($connection, $explain_check); + } else { + $result = mysql_query($explain_check, $connection); + } + + if(!$result){ + throw new Exception("Error on explain check: " . $connection->error); + } + + } catch (Exception $e) { + $has_privileges = 0; + } finally { + drop_database($connection, 'pandora_tmp_privilege_check'); + return $has_privileges; + } +} + + +function check_drop_privileges($connection) +{ + global $config; + $has_privileges = 1; + + try { + if ($config['mysqli']) { + $create_db = mysqli_query($connection, "CREATE DATABASE IF NOT EXISTS`pandora_tmp_privilege_check`"); + } else { + $create_db = mysql_query("CREATE DATABASE IF NOT EXISTS `pandora_tmp_privilege_check`", $connection); + } + } catch (Exception $e) { + $error_message = $e->getMessage(); + } + + if (!$create_db) { + if (stripos($error_message, "access denied for user") !== false) { + preg_match("/'.+?'\@'.+?'/", $error_message, $error_user); + $error_user = $error_user[0]; + ui_print_error_message(__("Unable to create databases with the provided user please check its privileges")); + return 0; + } + + ui_print_error_message(__('There was an error creating the DB during drop check')); + return 0; + } + + try { + if ($config['mysqli'] === true) { + mysqli_select_db($connection, "pandora_tmp_privilege_check"); + } else { + mysql_select_db("reference_check", $connection); + } + } catch (Exception $e) { + ui_print_error_message(__('There was an error selecting the DB during drop check')); + return 0; + } + + try { + drop_database($connection, 'pandora_tmp_privilege_check'); + } catch (Exception $e) { + $has_privileges = 0; + ui_print_error_message( + __("Unable to drop databases with the provided user please check its privileges.") . + "
" . + __("Test databases may have been left over due to lack of drop privileges.") + ); + } finally { + return $has_privileges; + } +} + + +function check_ref_privileges($connection) +{ + global $config; + $has_privileges = 1; + + drop_database($connection, 'pandora_tmp_privilege_check'); + + $create_tb1= "CREATE TABLE tb1 ( + id INT AUTO_INCREMENT PRIMARY KEY + )"; + + $create_tb2 = "CREATE TABLE tb2 ( + id INT AUTO_INCREMENT PRIMARY KEY, + id_tb1 INT, + FOREIGN KEY (id_tb1) REFERENCES tb2(id) + )"; + + try { + if ($config['mysqli']) { + mysqli_query($connection, "CREATE DATABASE `pandora_tmp_privilege_check`"); + } else { + mysql_query("CREATE DATABASE `pandora_tmp_privilege_check`", $connection); + } + } catch (Exception $e) { + ui_print_error_message(__('There was an error creating the DB during reference check')); + return 0; + } + + try { + if ($config['mysqli'] === true) { + mysqli_select_db($connection, "pandora_tmp_privilege_check"); + } else { + mysql_select_db("reference_check", $connection); + } + } catch (Exception $e) { + ui_print_error_message(__('There was an error selecting the DB during reference check')); + return 0; + } + + try { + if ($config['mysqli'] === true) { + $result = mysqli_query($connection, $create_tb1); + } else { + $result = mysql_query($create_tb1, $connection); + } + + if(!$result){ + throw new Exception("Error on reference check: " . $connection->error); + } + + if ($config['mysqli'] === true) { + $result = mysqli_query($connection, $create_tb2); + } else { + $result = mysql_query($create_tb2, $connection); + } + + if(!$result){ + throw new Exception("Error on reference check: " . $connection->error); + } + + } catch (Exception $e) { + $has_privileges = 0; + } finally { + drop_database($connection, 'pandora_tmp_privilege_check'); + return $has_privileges; + } +} + + +function drop_database($connection, $database) +{ + global $config; + + if ($config['mysqli'] === true) { + mysqli_query($connection, "DROP DATABASE IF EXISTS `$database`"); + } else { + mysql_query("DROP DATABASE IF EXISTS `$database`", $connection); + } +} + + extensions_add_godmode_function('extension_db_status'); extensions_add_godmode_menu_option(__('DB Schema check'), 'DM', 'gextensions', null, 'v1r1', 'gdbman');