diff --git a/doc/config.rst b/doc/config.rst index 33acceb21b..57c809bc80 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -3540,6 +3540,15 @@ Various display setting specify the amount of saved history items using :config:option:`$cfg['QueryHistoryMax']`. +.. config:option:: $cfg['AllowSharedBookmarks'] + + :type: boolean + :default: true + + .. versionadded:: 6.0.0 + + Allow users to create bookmarks that are available for all other users + .. config:option:: $cfg['BrowseMIME'] :type: boolean diff --git a/libraries/classes/Bookmark.php b/libraries/classes/Bookmark.php index 661942ea11..4912c58fff 100644 --- a/libraries/classes/Bookmark.php +++ b/libraries/classes/Bookmark.php @@ -175,7 +175,7 @@ class Bookmark /** * Creates a Bookmark object from the parameters * - * @param mixed[] $bkmFields the properties of the bookmark to add; here, $bkm_fields['bkm_sql_query'] is urlencoded + * @param mixed[] $bkmFields the properties of the bookmark to add; here, $bkmFields['bkm_sql_query'] is urlencoded * @param bool $allUsers whether to make the bookmark available for all users */ public static function createBookmark( @@ -191,6 +191,14 @@ class Bookmark return false; } + if (! $GLOBALS['cfg']['AllowSharedBookmarks']) { + $allUsers = false; + } + + if (! $allUsers && ! strlen((string) $bkmFields['bkm_user'])) { + return false; + } + $bookmark = new Bookmark($dbi, new Relation($dbi)); $bookmark->database = $bkmFields['bkm_database']; $bookmark->label = $bkmFields['bkm_label']; @@ -227,10 +235,17 @@ class Bookmark string $user, string|false $db = false, ): array { + $exactUserMatch = ! $GLOBALS['cfg']['AllowSharedBookmarks']; + $query = 'SELECT * FROM ' . Util::backquote($bookmarkFeature->database) . '.' . Util::backquote($bookmarkFeature->bookmark) - . " WHERE ( `user` = ''" - . ' OR `user` = ' . $dbi->quoteString($user) . ' )'; + . ' WHERE (`user` = ' . $dbi->quoteString($user); + if (! $exactUserMatch) { + $query .= " OR `user` = ''"; + } + + $query .= ')'; + if ($db !== false) { $query .= ' AND dbase = ' . $dbi->quoteString($db); } @@ -275,6 +290,10 @@ class Bookmark return null; } + if (! $GLOBALS['cfg']['AllowSharedBookmarks']) { + $exactUserMatch = true; + } + $query = 'SELECT * FROM ' . Util::backquote($bookmarkFeature->database) . '.' . Util::backquote($bookmarkFeature->bookmark) . ' WHERE dbase = ' . $dbi->quoteString($db->getName()); diff --git a/libraries/classes/Config/Descriptions.php b/libraries/classes/Config/Descriptions.php index 6f96216936..d34e64162b 100644 --- a/libraries/classes/Config/Descriptions.php +++ b/libraries/classes/Config/Descriptions.php @@ -329,6 +329,7 @@ class Descriptions . 'storage). If disabled, this utilizes JS-routines to display query history ' . '(lost by window close).', ), + 'AllowSharedBookmarks_desc' => __('Allow users to create bookmarks that are available for all other users'), 'Servers_SessionTimeZone_desc' => __( 'Sets the effective timezone; possibly different than the one from your database server', ), @@ -854,6 +855,7 @@ class Descriptions 'ProtectBinary_name' => __('Protect binary columns'), 'QueryHistoryDB_name' => __('Permanent query history'), 'QueryHistoryMax_name' => __('Query history length'), + 'AllowSharedBookmarks_name' => __('Allow shared bookmarks between users'), 'RecodingEngine_name' => __('Recoding engine'), 'RememberSorting_name' => __('Remember table\'s sorting'), 'TablePrimaryKeyOrder_name' => __('Primary key default sort order'), diff --git a/libraries/classes/Config/Forms/Setup/SqlForm.php b/libraries/classes/Config/Forms/Setup/SqlForm.php index f36f855daf..8138ea19b2 100644 --- a/libraries/classes/Config/Forms/Setup/SqlForm.php +++ b/libraries/classes/Config/Forms/Setup/SqlForm.php @@ -15,6 +15,7 @@ class SqlForm extends \PhpMyAdmin\Config\Forms\User\SqlForm $result = parent::getForms(); /* Following are not available to user */ $result['Sql_queries'][] = 'QueryHistoryDB'; + $result['Sql_queries'][] = 'AllowSharedBookmarks'; return $result; } diff --git a/libraries/classes/Config/Settings.php b/libraries/classes/Config/Settings.php index f2cf8d0575..aaf951e9c7 100644 --- a/libraries/classes/Config/Settings.php +++ b/libraries/classes/Config/Settings.php @@ -1925,6 +1925,17 @@ final class Settings */ public int $QueryHistoryMax; + /** + * Allow shared bookmarks between users + * + * ```php + * $cfg['AllowSharedBookmarks'] = true; + * ``` + * + * @link https://docs.phpmyadmin.net/en/latest/config.html#cfg_AllowSharedBookmarks + */ + public bool $AllowSharedBookmarks; + /** * Use MIME-Types (stored in column comments table) for * @@ -2565,6 +2576,7 @@ final class Settings $this->repeatCells = $this->setRepeatCells($settings); $this->QueryHistoryDB = $this->setQueryHistoryDB($settings); $this->QueryHistoryMax = $this->setQueryHistoryMax($settings); + $this->AllowSharedBookmarks = $this->setAllowSharedBookmarks($settings); $this->BrowseMIME = $this->setBrowseMIME($settings); $this->MaxExactCount = $this->setMaxExactCount($settings); $this->MaxExactCountViews = $this->setMaxExactCountViews($settings); @@ -2762,6 +2774,7 @@ final class Settings 'RepeatCells' => $this->repeatCells, 'QueryHistoryDB' => $this->QueryHistoryDB, 'QueryHistoryMax' => $this->QueryHistoryMax, + 'AllowSharedBookmarks' => $this->AllowSharedBookmarks, 'BrowseMIME' => $this->BrowseMIME, 'MaxExactCount' => $this->MaxExactCount, 'MaxExactCountViews' => $this->MaxExactCountViews, @@ -4796,6 +4809,16 @@ final class Settings return $queryHistoryMax >= 1 ? $queryHistoryMax : 25; } + /** @param array $settings */ + private function setAllowSharedBookmarks(array $settings): bool + { + if (! isset($settings['AllowSharedBookmarks'])) { + return true; + } + + return (bool) $settings['AllowSharedBookmarks']; + } + /** @param array $settings */ private function setBrowseMIME(array $settings): bool { diff --git a/libraries/classes/Sql.php b/libraries/classes/Sql.php index ae7dc332db..efdff6677f 100644 --- a/libraries/classes/Sql.php +++ b/libraries/classes/Sql.php @@ -1035,6 +1035,7 @@ class Sql ]), 'user' => $GLOBALS['cfg']['Server']['user'], 'sql_query' => $completeQuery ?? $sqlQuery, + 'allow_shared_bookmarks' => $GLOBALS['cfg']['AllowSharedBookmarks'], ]); } diff --git a/libraries/classes/SqlQueryForm.php b/libraries/classes/SqlQueryForm.php index b82a380e1f..cf3598d77a 100644 --- a/libraries/classes/SqlQueryForm.php +++ b/libraries/classes/SqlQueryForm.php @@ -116,6 +116,7 @@ class SqlQueryForm 'bookmarks' => $bookmarks, 'can_convert_kanji' => Encoding::canConvertKanji(), 'is_foreign_key_check' => ForeignKey::isCheckEnabled(), + 'allow_shared_bookmarks' => $GLOBALS['cfg']['AllowSharedBookmarks'], ]); } diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 938a0f4645..05ae6c4619 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -610,6 +610,7 @@ + diff --git a/psalm.xml b/psalm.xml index faa16ca854..3ff6eb4737 100644 --- a/psalm.xml +++ b/psalm.xml @@ -44,6 +44,7 @@ cached_affected_rows: int|numeric-string, cfg: array{ AllowArbitraryServer: bool, + AllowSharedBookmarks: bool, AllowThirdPartyFraming: bool|'sameorigin', ArbitraryServerRegexp: string, AvailableCharsets: string[], diff --git a/templates/sql/bookmark.twig b/templates/sql/bookmark.twig index 18f19ad49f..a9908323ed 100644 --- a/templates/sql/bookmark.twig +++ b/templates/sql/bookmark.twig @@ -15,10 +15,12 @@ -
- - -
+ {% if allow_shared_bookmarks %} +
+ + +
+ {% endif %} -
-
- - + {% if allow_shared_bookmarks %} +
+
+ + +
-
+ {% endif %}
diff --git a/test/classes/BookmarkTest.php b/test/classes/BookmarkTest.php index 7bfc578ffc..7eefa31ed2 100644 --- a/test/classes/BookmarkTest.php +++ b/test/classes/BookmarkTest.php @@ -43,7 +43,7 @@ class BookmarkTest extends AbstractTestCase public function testGetList(): void { $this->dummyDbi->addResult( - 'SELECT * FROM `phpmyadmin`.`pma_bookmark` WHERE ( `user` = \'\' OR `user` = \'root\' )' + 'SELECT * FROM `phpmyadmin`.`pma_bookmark` WHERE (`user` = \'root\' OR `user` = \'\')' . ' AND dbase = \'sakila\' ORDER BY label ASC', [['1', 'sakila', 'root', 'label', 'SELECT * FROM `actor` WHERE `actor_id` < 10;']], ['id', 'dbase', 'user', 'label', 'query'], diff --git a/test/classes/Config/SettingsTest.php b/test/classes/Config/SettingsTest.php index 8d2b00bb01..01c06dca77 100644 --- a/test/classes/Config/SettingsTest.php +++ b/test/classes/Config/SettingsTest.php @@ -197,6 +197,7 @@ class SettingsTest extends TestCase 'ShowPropertyComments' => true, 'QueryHistoryDB' => false, 'QueryHistoryMax' => 25, + 'AllowSharedBookmarks' => true, 'BrowseMIME' => true, 'MaxExactCount' => 50000, 'MaxExactCountViews' => 0, @@ -454,6 +455,7 @@ class SettingsTest extends TestCase ['ShowPropertyComments', null, true], ['QueryHistoryDB', null, false], ['QueryHistoryMax', null, 25], + ['AllowSharedBookmarks', null, true], ['BrowseMIME', null, true], ['MaxExactCount', null, 50000], ['MaxExactCountViews', null, 0], @@ -619,6 +621,7 @@ class SettingsTest extends TestCase ['ShowPropertyComments', false, false], ['QueryHistoryDB', true, true], ['QueryHistoryMax', 1, 1], + ['AllowSharedBookmarks', false, false], ['BrowseMIME', false, false], ['MaxExactCount', 1, 1], ['MaxExactCountViews', 0, 0], @@ -887,6 +890,7 @@ class SettingsTest extends TestCase ['ShowPropertyComments', 0, false], ['QueryHistoryDB', 1, true], ['QueryHistoryMax', '1', 1], + ['AllowSharedBookmarks', 0, false], ['BrowseMIME', 0, false], ['MaxExactCount', '1', 1], ['MaxExactCountViews', '1', 1],