diff --git a/ChangeLog b/ChangeLog index 4cb58ed89d..b162bc360d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,8 @@ phpMyAdmin - ChangeLog + rfe #1490 Dynamic process list + rfe #1522 Drag and Drop SQL import + rfe #637 Custom Field Handlers ++ rfe #1488 User privilege tab not shown in all relevant cases ++ rfe #781 Privileges for non superuser 4.2.7.0 (not yet released) - bug Broken links on home page diff --git a/js/server_privileges.js b/js/server_privileges.js index c77cc521c7..b6587ad936 100644 --- a/js/server_privileges.js +++ b/js/server_privileges.js @@ -41,8 +41,10 @@ function checkAddUser(the_form) */ function appendNewUser(new_user_string, new_user_initial, new_user_initial_string) { + if (!$('#usersForm').length) { + return; + } //Append the newly retrieved user to the table now - //Calculate the index for the new row var $curr_last_row = $("#usersForm").find('tbody').find('tr:last'); var $curr_first_row = $("#usersForm").find('tbody').find('tr:first'); diff --git a/libraries/DatabaseInterface.class.php b/libraries/DatabaseInterface.class.php index af23846166..91accfecf2 100644 --- a/libraries/DatabaseInterface.class.php +++ b/libraries/DatabaseInterface.class.php @@ -1834,40 +1834,90 @@ class PMA_DatabaseInterface } /** - * Checks if current user is superuser while caching - * the result in session. + * gets the current user with host * - * @return bool Whether use is a superuser + * @return string the current user i.e. user@host + */ + public function getCurrentUser() + { + if (PMA_Util::cacheExists('mysql_cur_user')) { + return PMA_Util::cacheGet('mysql_cur_user'); + } + $user = $GLOBALS['dbi']->fetchValue('SELECT USER();'); + if ($user !== false) { + PMA_Util::cacheSet('mysql_cur_user', $user); + return PMA_Util::cacheGet('mysql_cur_user'); + } + return ''; + } + + /** + * Checks if current user is superuser + * + * @return bool Whether user is a superuser */ public function isSuperuser() { - if (PMA_Util::cacheExists('is_superuser')) { - return PMA_Util::cacheGet('is_superuser'); + return self::isUserType('super'); + } + + /** + * Checks if current user has global create user/grant privilege + * or is a superuser (i.e. SELECT on mysql.users) + * while caching the result in session. + * + * @param string $type type of user to check for + * i.e. 'create', 'grant', 'super' + * + * @return bool Whether user is a given type of user + */ + public function isUserType($type) + { + if (PMA_Util::cacheExists('is_' . $type . 'user')) { + return PMA_Util::cacheGet('is_' . $type . 'user'); + } + + // Prepare query for each user type check + $query = ''; + if ($type === 'super') { + $query = 'SELECT 1 FROM mysql.user LIMIT 1'; + } elseif ($type === 'create') { + $query = 'SELECT 1 FROM INFORMATION_SCHEMA.USER_PRIVILEGES ' + . 'WHERE PRIVILEGE_TYPE = \'CREATE USER\' LIMIT 1'; + } elseif ($type === 'grant') { + $query = 'SELECT 1 FROM INFORMATION_SCHEMA.USER_PRIVILEGES ' + . 'WHERE IS_GRANTABLE = \'YES\' LIMIT 1'; } // when connection failed we don't have a $userlink if (isset($GLOBALS['userlink'])) { + $is = false; if (PMA_DRIZZLE) { // Drizzle has no authorization by default, so when no plugin is // enabled everyone is a superuser // Known authorization libraries: regex_policy, simple_user_policy // Plugins limit object visibility (dbs, tables, processes), we can // safely assume we always deal with superuser - $result = true; + $is = true; } else { - // check access to mysql.user table - $result = (bool) $GLOBALS['dbi']->tryQuery( - 'SELECT COUNT(*) FROM mysql.user', + // Check information_schema.user_privileges table + // for global create user rights + $result = $GLOBALS['dbi']->tryQuery( + $query, $GLOBALS['userlink'], self::QUERY_STORE ); + if ($result) { + $is = (bool) $GLOBALS['dbi']->numRows($result); + } + $GLOBALS['dbi']->freeResult($result); } - PMA_Util::cacheSet('is_superuser', $result); + PMA_Util::cacheSet('is_' . $type . 'user', $is); } else { - PMA_Util::cacheSet('is_superuser', false); + PMA_Util::cacheSet('is_' . $type . 'user', false); } - return PMA_Util::cacheGet('is_superuser'); + return PMA_Util::cacheGet('is_' . $type . 'user'); } /** diff --git a/libraries/Menu.class.php b/libraries/Menu.class.php index 148ab6c491..98f0de7da8 100644 --- a/libraries/Menu.class.php +++ b/libraries/Menu.class.php @@ -288,6 +288,8 @@ class PMA_Menu $db_is_system_schema = $GLOBALS['dbi']->isSystemSchema($this->_db); $tbl_is_view = PMA_Table::isView($this->_db, $this->_table); $is_superuser = $GLOBALS['dbi']->isSuperuser(); + $isCreateOrGrantUser = $GLOBALS['dbi']->isUserType('grant') + || $GLOBALS['dbi']->isUserType('create'); $tabs = array(); @@ -331,7 +333,9 @@ class PMA_Menu $tabs['import']['link'] = 'tbl_import.php'; $tabs['import']['text'] = __('Import'); } - if ($is_superuser && ! PMA_DRIZZLE && ! $db_is_system_schema) { + if (($is_superuser || $isCreateOrGrantUser) + && ! PMA_DRIZZLE && ! $db_is_system_schema + ) { $tabs['privileges']['link'] = 'server_privileges.php'; $tabs['privileges']['args']['checkprivsdb'] = $this->_db; $tabs['privileges']['args']['checkprivstable'] = $this->_table; @@ -389,6 +393,8 @@ class PMA_Menu $db_is_system_schema = $GLOBALS['dbi']->isSystemSchema($this->_db); $num_tables = count($GLOBALS['dbi']->getTables($this->_db)); $is_superuser = $GLOBALS['dbi']->isSuperuser(); + $isCreateOrGrantUser = $GLOBALS['dbi']->isUserType('grant') + || $GLOBALS['dbi']->isUserType('create'); /** * Gets the relation settings @@ -435,7 +441,7 @@ class PMA_Menu $tabs['operation']['text'] = __('Operations'); $tabs['operation']['icon'] = 'b_tblops.png'; - if ($is_superuser && ! PMA_DRIZZLE) { + if (($is_superuser || $isCreateOrGrantUser) && ! PMA_DRIZZLE) { $tabs['privileges']['link'] = 'server_privileges.php'; $tabs['privileges']['args']['checkprivsdb'] = $this->_db; // stay on database view @@ -492,6 +498,8 @@ class PMA_Menu private function _getServerTabs() { $is_superuser = isset($GLOBALS['dbi']) && $GLOBALS['dbi']->isSuperuser(); + $isCreateOrGrantUser = $GLOBALS['dbi']->isUserType('grant') + || $GLOBALS['dbi']->isUserType('create'); $binary_logs = null; $notDrizzle = ! defined('PMA_DRIZZLE') || (defined('PMA_DRIZZLE') && ! PMA_DRIZZLE); @@ -529,7 +537,7 @@ class PMA_Menu ) ); - if ($is_superuser && ! PMA_DRIZZLE) { + if (($is_superuser || $isCreateOrGrantUser) && ! PMA_DRIZZLE) { $tabs['rights']['icon'] = 's_rights.png'; $tabs['rights']['link'] = 'server_privileges.php'; $tabs['rights']['text'] = __('Users'); diff --git a/libraries/Util.class.php b/libraries/Util.class.php index 5ac90734b1..5559a67e57 100644 --- a/libraries/Util.class.php +++ b/libraries/Util.class.php @@ -2796,6 +2796,8 @@ class PMA_Util public static function clearUserCache() { self::cacheUnset('is_superuser'); + self::cacheUnset('is_createuser'); + self::cacheUnset('is_grantuser'); } /** diff --git a/libraries/dbi/DBIDummy.class.php b/libraries/dbi/DBIDummy.class.php index f43d8ca198..4e456e3574 100644 --- a/libraries/dbi/DBIDummy.class.php +++ b/libraries/dbi/DBIDummy.class.php @@ -26,8 +26,18 @@ $GLOBALS['dummy_queries'] = array( 'result' => array(array('pma_test@localhost')), ), array( - 'query' => 'SELECT COUNT(*) FROM mysql.user', - 'result' => false, + 'query' => 'SELECT 1 FROM mysql.user LIMIT 1', + 'result' => array(array('1')), + ), + array( + 'query' => 'SELECT 1 FROM INFORMATION_SCHEMA.USER_PRIVILEGES ' + . 'WHERE PRIVILEGE_TYPE = \'CREATE USER\' LIMIT 1', + 'result' => array(array('1')), + ), + array( + 'query' => 'SELECT 1 FROM INFORMATION_SCHEMA.USER_PRIVILEGES ' + . 'WHERE IS_GRANTABLE = \'YES\' LIMIT 1', + 'result' => array(array('1')), ), array( 'query' => 'SHOW MASTER LOGS', diff --git a/libraries/server_common.inc.php b/libraries/server_common.inc.php index 4b1eb47398..b6372a65c6 100644 --- a/libraries/server_common.inc.php +++ b/libraries/server_common.inc.php @@ -32,10 +32,12 @@ $err_url = 'index.php' . $GLOBALS['url_query']; /** * @global boolean Checks for superuser privileges */ -$is_superuser = $GLOBALS['dbi']->isSuperuser(); +$GLOBALS['is_superuser'] = $GLOBALS['dbi']->isSuperuser(); +$GLOBALS['is_grantuser'] = $GLOBALS['dbi']->isUserType('grant'); +$GLOBALS['is_createuser'] = $GLOBALS['dbi']->isUserType('create'); // now, select the mysql db -if ($is_superuser && ! PMA_DRIZZLE) { +if ($GLOBALS['is_superuser'] && ! PMA_DRIZZLE) { $GLOBALS['dbi']->selectDb('mysql', $GLOBALS['userlink']); } diff --git a/libraries/server_privileges.lib.php b/libraries/server_privileges.lib.php index 1d63556f91..e2cc2f8eec 100644 --- a/libraries/server_privileges.lib.php +++ b/libraries/server_privileges.lib.php @@ -633,7 +633,7 @@ function PMA_getHtmlToDisplayPrivilegesTable($db = '*', $row = $GLOBALS['dbi']->fetchSingleRow($sql_query); } if (empty($row)) { - if ($table == '*') { + if ($table == '*' && $GLOBALS['is_superuser']) { if ($db == '*') { $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;'; } elseif ($table == '*') { @@ -648,6 +648,8 @@ function PMA_getHtmlToDisplayPrivilegesTable($db = '*', } } $GLOBALS['dbi']->freeResult($res); + } elseif ($table == '*') { + $row = array(); } else { $row = array('Table_priv' => ''); } @@ -722,7 +724,9 @@ function PMA_getHtmlForResourceLimits($row) . 'MAX QUERIES PER HOUR' . '' . "\n" . '' . "\n" . '' . "\n" . '' . "\n" . '' . "\n" @@ -1227,7 +1237,8 @@ function PMA_getHtmlForGlobalPrivTableWithCheckboxes( . ' name="' . $priv[0] . '_priv" ' . 'id="checkbox_' . $priv[0] . '_priv"' . ' value="Y" title="' . $priv[2] . '"' - . (($row[$priv[0] . '_priv'] == 'Y') + . ((isset($row[$priv[0] . '_priv']) + && $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '' ) @@ -1747,7 +1758,9 @@ function PMA_getHtmlForAddUser($dbname) } $html_output .= '' . "\n"; - $html_output .= PMA_getHtmlToDisplayPrivilegesTable('*', '*', false); + if ($GLOBALS['is_grantuser']) { + $html_output .= PMA_getHtmlToDisplayPrivilegesTable('*', '*', false); + } $html_output .= '