From cfc2fca94aeca587c60174cdcb65190975ec1f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mudr=C3=A1k?= Date: Mon, 27 Feb 2023 18:26:41 +0100 Subject: [PATCH] MDL-74586 rss: Make rss_get_userid_from_token() use table index Due to missing `AND k.script = 'rss'` condition, the query did not make use of the existing script-value compound index defined for the table. So it had to perform the full sequential scan for all rows when searching for the token. This had serious performance issues on sites with many users, especially in case on non-existing token / key. --- lib/rsslib.php | 13 +++++++++---- lib/tests/rsslib_test.php | 17 ++++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/rsslib.php b/lib/rsslib.php index 4f625d1c43a..3286d5df1d7 100644 --- a/lib/rsslib.php +++ b/lib/rsslib.php @@ -413,10 +413,15 @@ function rss_geterrorxmlfile($errortype = 'rsserror') { function rss_get_userid_from_token($token) { global $DB; - $sql = 'SELECT u.id FROM {user} u - JOIN {user_private_key} k ON u.id = k.userid - WHERE u.deleted = 0 AND u.confirmed = 1 - AND u.suspended = 0 AND k.value = ?'; + $sql = "SELECT u.id + FROM {user} u + JOIN {user_private_key} k ON u.id = k.userid + WHERE u.deleted = 0 + AND u.confirmed = 1 + AND u.suspended = 0 + AND k.script = 'rss' + AND k.value = ?"; + return $DB->get_field_sql($sql, array($token), IGNORE_MISSING); } diff --git a/lib/tests/rsslib_test.php b/lib/tests/rsslib_test.php index ff0674595b8..3585601018e 100644 --- a/lib/tests/rsslib_test.php +++ b/lib/tests/rsslib_test.php @@ -20,7 +20,7 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->libdir.'/simplepie/moodle_simplepie.php'); - +require_once($CFG->libdir . '/rsslib.php'); /** * These tests rely on the rsstest.xml file on download.moodle.org, @@ -140,4 +140,19 @@ EOD; $this->assertSame('Moodle News', $feed->get_title()); $this->assertSame('http://moodle.org/mod/forum/view.php?f=1', $feed->get_link()); } + + /** + * Test that we can get the right user ID based on the provided private key (token). + * + * @covers ::rss_get_userid_from_token + */ + public function test_rss_get_userid_from_token() { + global $USER; + + $this->resetAfterTest(); + $this->setGuestUser(); + + $key = rss_get_token($USER->id); + $this->assertSame(rss_get_userid_from_token($key), $USER->id); + } }