diff --git a/.upgradenotes/MDL-87034-2025102912420312.yml b/.upgradenotes/MDL-87034-2025102912420312.yml new file mode 100644 index 00000000000..f43bce675b2 --- /dev/null +++ b/.upgradenotes/MDL-87034-2025102912420312.yml @@ -0,0 +1,9 @@ +issueNumber: MDL-87034 +notes: + core_webservice: + - message: >- + The WebService core_webservice_get_site_info now returns three new fields: + "usercanviewconfig" indicating whether the current user can see the + administration tree, "usercanchangeconfig" indicating whether the + current user can change the site configuration, and site secret. + type: changed diff --git a/public/lib/classes/hub/registration.php b/public/lib/classes/hub/registration.php index 6d9904d8646..b99c8b912fc 100644 --- a/public/lib/classes/hub/registration.php +++ b/public/lib/classes/hub/registration.php @@ -961,4 +961,11 @@ class registration { $size = $size / (1024 * 1024); return round($size, 3); } + + /** + * Resets the static caches for unit tests. + */ + public static function reset_caches(): void { + self::$registration = null; + } } diff --git a/public/lib/phpunit/classes/util.php b/public/lib/phpunit/classes/util.php index fc295db0d33..c6b2e3c1ccf 100644 --- a/public/lib/phpunit/classes/util.php +++ b/public/lib/phpunit/classes/util.php @@ -245,6 +245,9 @@ class phpunit_util extends testing_util { core_calendar\local\event\container::reset_caches(); } + // Reset hub registration caches. + \core\hub\registration::reset_caches(); + // TODO MDL-25290: add more resets here and probably refactor them to new core function. // Reset course and module caches. diff --git a/public/mod/forum/tests/mail_test.php b/public/mod/forum/tests/mail_test.php index fda0e8f5e42..90a9e98b5c2 100644 --- a/public/mod/forum/tests/mail_test.php +++ b/public/mod/forum/tests/mail_test.php @@ -1043,7 +1043,7 @@ final class mail_test extends \advanced_testcase { $htmlbase['user']['mailformat'] = 1; $htmlbase['expectations'][0]['contents'] = array( '~{\$a', - '~&(amp|lt|gt|quot|\#039);(?!course|lang|version|iosappid|androidappid)', + '~&(amp|lt|gt|quot|\#039);(?!course|lang|version|iosappid|androidappid|siteurl)', '
( *\n *)?\n.*Hello Moodle', '>Moodle Forum', '>Welcome.*Moodle', '>Love Moodle', '>1\d1'); $htmlcases['HTML mail without ampersands, quotes or lt/gt'] = array('data' => $htmlbase); @@ -1072,7 +1072,7 @@ final class mail_test extends \advanced_testcase { $newcase['expectations'][0]['subject'] = '.*101.*HTML text and image'; $newcase['expectations'][0]['contents'] = array( '~{\$a', - '~&(amp|lt|gt|quot|\#039);(?!course|lang|version|iosappid|androidappid)', + '~&(amp|lt|gt|quot|\#039);(?!course|lang|version|iosappid|androidappid|siteurl)', '
( *\n *)?\n.*HTML text and image', '>Moodle Forum', '

Welcome to Moodle, ' diff --git a/public/webservice/externallib.php b/public/webservice/externallib.php index e944b04e644..d758ca15576 100644 --- a/public/webservice/externallib.php +++ b/public/webservice/externallib.php @@ -220,6 +220,13 @@ class core_webservice_external extends \core_external\external_api { } $siteinfo['policyagreed'] = $USER->policyagreed; + $siteinfo['usercanchangeconfig'] = has_capability('moodle/site:config', $systemcontext); + $siteinfo['usercanviewconfig'] = has_capability('moodle/site:configview', $systemcontext); + + if ($siteinfo['usercanchangeconfig']) { + $sitesecret = \core\hub\registration::get_secret(); + $siteinfo['sitesecret'] = $sitesecret ?? null; + } return $siteinfo; } @@ -296,6 +303,21 @@ class core_webservice_external extends \core_external\external_api { 'usersessionscount' => new external_value(PARAM_INT, 'Number of active sessions for current user. Only returned when limitconcurrentlogins is used.', VALUE_OPTIONAL), 'policyagreed' => new external_value(PARAM_INT, 'Whether user accepted all the policies.', VALUE_OPTIONAL), + 'usercanchangeconfig' => new external_value( + PARAM_BOOL, + 'Whether the user can change the site configuration.', + VALUE_OPTIONAL + ), + 'usercanviewconfig' => new external_value( + PARAM_BOOL, + 'Whether the user can view the site administration tree.', + VALUE_OPTIONAL + ), + 'sitesecret' => new external_value( + PARAM_RAW, + 'The site secret, only returned to users with moodle/site:config capability (usually admins).', + VALUE_OPTIONAL + ), ) ); } diff --git a/public/webservice/tests/externallib_test.php b/public/webservice/tests/externallib_test.php index 1fea9cb6416..e6897e7d774 100644 --- a/public/webservice/tests/externallib_test.php +++ b/public/webservice/tests/externallib_test.php @@ -92,6 +92,16 @@ final class externallib_test extends \core_external\tests\externallib_testcase { $externaltoken->name = \core_external\util::generate_token_name(); $DB->insert_record('external_tokens', $externaltoken); + // Add fake registration. + $hub = new \stdClass(); + $hub->token = get_site_identifier() . date('Ymdhis'); + $hub->secret = $hub->token; + $hub->huburl = HUB_MOODLEORGHUBURL; + $hub->hubname = 'moodle'; + $hub->confirmed = 1; + $hub->timemodified = time(); + $hub->id = $DB->insert_record('registration_hubs', $hub); + $siteinfo = \core_webservice_external::get_site_info(); // We need to execute the return values cleaning process to simulate the web service server. @@ -149,6 +159,9 @@ final class externallib_test extends \core_external\tests\externallib_testcase { $this->assertEquals($CFG->calendartype, $siteinfo['sitecalendartype']); $this->assertEquals($user['theme'], $siteinfo['theme']); $this->assertEquals($USER->policyagreed, $siteinfo['policyagreed']); + $this->assertFalse($siteinfo['usercanchangeconfig']); + $this->assertFalse($siteinfo['usercanviewconfig']); + $this->assertArrayNotHasKey('sitesecret', $siteinfo); // Now as admin. $this->setAdminUser(); @@ -201,6 +214,11 @@ final class externallib_test extends \core_external\tests\externallib_testcase { $siteinfo = external_api::clean_returnvalue(\core_webservice_external::get_site_info_returns(), $siteinfo); $this->assertEquals($CFG->limitconcurrentlogins, $siteinfo['limitconcurrentlogins']); $this->assertEquals(1, $siteinfo['usersessionscount']); + $this->assertTrue($siteinfo['usercanchangeconfig']); + $this->assertTrue($siteinfo['usercanviewconfig']); + $this->assertArrayHasKey('sitesecret', $siteinfo); + $this->assertNotEmpty($siteinfo['sitesecret']); + $this->assertEquals($hub->secret, $siteinfo['sitesecret']); } /**