diff --git a/db_operations.php b/db_operations.php
index 7099be344e..12b2e1d5d3 100644
--- a/db_operations.php
+++ b/db_operations.php
@@ -21,6 +21,7 @@ require_once 'libraries/mysql_charsets.inc.php';
/**
* functions implementation for this script
*/
+require_once 'libraries/check_user_privileges.lib.php';
require_once 'libraries/operations.lib.php';
// add a javascript file for jQuery functions to handle Ajax actions
diff --git a/db_routines.php b/db_routines.php
index c273b7b291..be7791c649 100644
--- a/db_routines.php
+++ b/db_routines.php
@@ -16,6 +16,7 @@ require_once 'libraries/mysql_charsets.inc.php';
/**
* Include all other files
*/
+require_once 'libraries/check_user_privileges.lib.php';
require_once 'libraries/rte/rte_routines.lib.php';
/**
diff --git a/doc/faq.rst b/doc/faq.rst
index 48649158d9..5909f6807f 100644
--- a/doc/faq.rst
+++ b/doc/faq.rst
@@ -2065,6 +2065,13 @@ Notes:
*column-related privileges* for the columns inside the table are also adjusted
to the table's new name.
+* While adjusting privileges, the user performing the operation **must** have the following
+ privileges:
+
+ * SELECT, INSERT, UPDATE, DELETE privileges on following tables:
+ `mysql`.`db`, `mysql`.`columns_priv`, `mysql`.`tables_priv`, `mysql`.`procs_priv`
+ * FLUSH privilege (GLOBAL)
+
Thus, if you want to replicate the database/table/column/procedure as it is
while renaming/copying/moving these objects, make sure you have checked this option.
diff --git a/libraries/check_user_privileges.lib.php b/libraries/check_user_privileges.lib.php
index aa118617e2..d03bb34c31 100644
--- a/libraries/check_user_privileges.lib.php
+++ b/libraries/check_user_privileges.lib.php
@@ -14,6 +14,208 @@ if (! defined('PHPMYADMIN')) {
*/
$GLOBALS['is_superuser'] = $GLOBALS['dbi']->isSuperuser();
+/**
+ * Check if user has required privileges for
+ * performing 'FLUSH PRIVILEGES' operation
+ *
+ * @return void
+ */
+function PMA_checkRequiredPrivilegesForFlushing()
+{
+
+ $res = $GLOBALS['dbi']->tryQuery(
+ 'FLUSH PRIVILEGES'
+ );
+
+ // Save the value
+ $GLOBALS['flush_priv'] = $res;
+}
+
+/**
+ * Check if user has required privileges for
+ * performing 'Adjust Privileges' operations
+ *
+ * @return void
+ */
+function PMA_checkRequiredPrivilgesForAdjust()
+{
+ $privs_available = true;
+ // FOR DB PRIVS
+ $select_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'SELECT * FROM `mysql`.`db` LIMIT 1'
+ );
+
+ $privs_available = $select_privs_available && $privs_available;
+
+ if ($privs_available) {
+ $delete_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`db` WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" LIMIT 1;'
+ );
+ $privs_available = $delete_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $insert_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'INSERT INTO `mysql`.`db`(`host`, `Db`, `User`) VALUES("pma_test_host", '
+ . '"mysql", "pma_test_user");'
+ );
+ // If successful test insert, delete the test row
+ if ($insert_privs_available) {
+ $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`db` WHERE host = "pma_test_host" AND '
+ . 'Db = "mysql" AND User = "pma_test_user" LIMIT 1;'
+ );
+ }
+ $privs_available = $insert_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $update_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'UPDATE `mysql`.`db` SET `host` = "" WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" LIMIT 1;'
+ );
+ $privs_available = $update_privs_available && $privs_available;
+ }
+ // save the value
+ $GLOBALS['db_priv'] = $privs_available;
+ // reset the value
+ $privs_available = true;
+
+ // FOR COLUMNS_PRIV
+ $select_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'SELECT * FROM `mysql`.`columns_priv` LIMIT 1'
+ );
+
+ $privs_available = $select_privs_available && $privs_available;
+
+ if ($privs_available) {
+ $delete_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`columns_priv` WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" LIMIT 1;'
+ );
+ $privs_available = $delete_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $insert_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'INSERT INTO `mysql`.`columns_priv`(`host`, `Db`, `User`, `Table_name`,'
+ . ' `Column_name`) VALUES("pma_test_host", '
+ . '"mysql", "pma_test_user", "", "")'
+ );
+ // If successful test insert, delete the test row
+ if ($insert_privs_available) {
+ $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`columns_priv` WHERE host = "pma_test_host" AND '
+ . 'Db = "mysql" AND User = "pma_test_user" AND Table_name = ""'
+ . ' AND Column_name = "" LIMIT 1;'
+ );
+ }
+ $privs_available = $insert_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $update_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'UPDATE `mysql`.`columns_priv` SET `host` = "" WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND Column_name = "" AND Table_name = "" LIMIT 1;'
+ );
+ $privs_available = $update_privs_available && $privs_available;
+
+ }
+ // Save the value
+ $GLOBALS['col_priv'] = $privs_available;
+ // Reset the value
+ $privs_available = true;
+
+ // FOR TABLES_PRIV
+ $select_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'SELECT * FROM `mysql`.`tables_priv` LIMIT 1'
+ );
+
+ $privs_available = $select_privs_available && $privs_available;
+
+ if ($privs_available) {
+ $delete_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`tables_priv` WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND Table_name = "" LIMIT 1;'
+ );
+ $privs_available = $delete_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $insert_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'INSERT INTO `mysql`.`tables_priv`(`host`, `Db`, `User`, `Table_name`'
+ . ') VALUES("pma_test_host", '
+ . '"mysql", "pma_test_user", "")'
+ );
+ // If successful test insert, delete the test row
+ if ($insert_privs_available) {
+ $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`tables_priv` WHERE host = "pma_test_host" AND '
+ . 'Db = "mysql" AND User = "pma_test_user" AND Table_name = "" LIMIT 1;'
+ );
+ }
+ $privs_available = $insert_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $update_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'UPDATE `mysql`.`tables_priv` SET `host` = "" WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND Table_name = "" LIMIT 1;'
+ );
+ $privs_available = $update_privs_available && $privs_available;
+
+ }
+ // Save the value
+ $GLOBALS['table_priv'] = $privs_available;
+ // Reset the value
+ $privs_available = true;
+
+ // FOR PROCS_PRIV
+ $select_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'SELECT * FROM `mysql`.`procs_priv` LIMIT 1'
+ );
+
+ $privs_available = $select_privs_available && $privs_available;
+
+ if ($privs_available) {
+ $delete_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`procs_priv` WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND `Routine_name` = ""'
+ . ' AND `Routine_type` = "" LIMIT 1;'
+ );
+ $privs_available = $delete_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $insert_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'INSERT INTO `mysql`.`procs_priv`(`host`, `Db`, `User`, `Routine_name`,'
+ . ' `Routine_type`) VALUES("pma_test_host", '
+ . '"mysql", "pma_test_user", "", "PROCEDURE")'
+ );
+ // If successful test insert, delete the test row
+ if ($insert_privs_available) {
+ $GLOBALS['dbi']->tryQuery(
+ 'DELETE FROM `mysql`.`procs_priv` WHERE `host` = "pma_test_host" AND '
+ . '`Db` = "mysql" AND `User` = "pma_test_user" AND `Routine_name` = ""'
+ . ' AND `Routine_type` = "PROCEDURE" LIMIT 1;'
+ );
+ }
+ $privs_available = $insert_privs_available && $privs_available;
+ }
+
+ if ($privs_available) {
+ $update_privs_available = $GLOBALS['dbi']->tryQuery(
+ 'UPDATE `mysql`.`procs_priv` SET `host` = "" WHERE `host` = "" AND '
+ . '`Db` = "" AND `User` = "" AND `Routine_name` = "" LIMIT 1;'
+ );
+ $privs_available = $update_privs_available && $privs_available;
+ }
+ // Save the value
+ $GLOBALS['proc_priv'] = $privs_available;
+
+}
+
/**
* sets privilege information extracted from SHOW GRANTS result
*
@@ -185,6 +387,13 @@ if (!PMA_DRIZZLE) {
} else {
PMA_analyseShowGrant();
}
+
+ // Check if privileges to 'mysql'.col_privs, 'mysql'.db,
+ // 'mysql'.table_privs, 'mysql'.proc_privs and privileges for
+ // flushing the privileges are available
+ PMA_checkRequiredPrivilegesForFlushing();
+ PMA_checkRequiredPrivilgesForAdjust();
+
} else {
// todo: for simple_user_policy only database with user's login can be created
// (unless logged in as root)
diff --git a/libraries/dbi/DBIDummy.class.php b/libraries/dbi/DBIDummy.class.php
index 10323afe6d..7ac4c44155 100644
--- a/libraries/dbi/DBIDummy.class.php
+++ b/libraries/dbi/DBIDummy.class.php
@@ -559,6 +559,26 @@ $GLOBALS['dummy_queries'] = array(
array(
'query' => "SHOW EVENTS FROM `default`",
'result' => array()
+ ),
+ array(
+ 'query' => "FLUSH PRIVILEGES",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT * FROM `mysql`.`db` LIMIT 1",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT * FROM `mysql`.`columns_priv` LIMIT 1",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT * FROM `mysql`.`tables_priv` LIMIT 1",
+ 'result' => array()
+ ),
+ array(
+ 'query' => "SELECT * FROM `mysql`.`procs_priv` LIMIT 1",
+ 'result' => array()
)
);
/**
diff --git a/libraries/operations.lib.php b/libraries/operations.lib.php
index 9b938e3c48..306e770755 100644
--- a/libraries/operations.lib.php
+++ b/libraries/operations.lib.php
@@ -77,11 +77,26 @@ function PMA_getHtmlForRenameDatabase($db)
$html_output .= '';
- $html_output .= '';
+
+ if (isset($GLOBALS['db_priv']) && $GLOBALS['db_priv']
+ && isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
+ ) {
+ $html_output .= '';
+ } else {
+ $html_output .= '';
+ }
+
$html_output .= '
';
+ . __('Adjust Privileges') . PMA_Util::showDocu('faq', 'faq6-39')
+ . '
';
+
$html_output .= ''
. ''
. '