From bf8f0c19a26819f3bd8b4fffaeed2530b15c8008 Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Tue, 23 Jul 2024 22:37:36 +0100 Subject: [PATCH] MDL-82502 courseformat: align module action capability checks. The "Hide/Show/Duplicate" actions should be considered self-contained, and not also require "manageactivities" capability (per existing docs) in addition to the specific capability that controls the action itself. Also ensure the "Duplicate" capability checks are in the course context. --- course/format/classes/stateactions.php | 28 +++++++++++++++++++------- course/mod.php | 4 ++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/course/format/classes/stateactions.php b/course/format/classes/stateactions.php index ba93a2e778a..28da968c87f 100644 --- a/course/format/classes/stateactions.php +++ b/course/format/classes/stateactions.php @@ -521,7 +521,7 @@ class stateactions { $course, $ids, __FUNCTION__, - ['moodle/course:manageactivities', 'moodle/course:activityvisibility'] + ['moodle/course:activityvisibility'] ); $format = course_get_format($course->id); @@ -577,7 +577,8 @@ class stateactions { $course, $ids, __FUNCTION__, - ['moodle/course:manageactivities', 'moodle/backup:backuptargetimport', 'moodle/restore:restoretargetimport'] + ['moodle/backup:backuptargetimport', 'moodle/restore:restoretargetimport'], + false ); $modinfo = get_fast_modinfo($course); @@ -1141,10 +1142,17 @@ class stateactions { * @param stdClass $course The course where given $cmids belong. * @param array $cmids List of course module ids to validate. * @param string $info additional information in case of error. - * @param array $capabilities optional capabilities checks per each cm context. + * @param array $capabilities optional capabilities checks to require. + * @param bool $usemodcontext whether to use each module context, or the course context * @throws moodle_exception if any id is not valid */ - protected function validate_cms(stdClass $course, array $cmids, ?string $info = null, array $capabilities = []): void { + protected function validate_cms( + stdClass $course, + array $cmids, + ?string $info = null, + array $capabilities = [], + bool $usemodcontext = true, + ): void { if (empty($cmids)) { throw new moodle_exception('emptycmids', 'core', null, $info); @@ -1155,10 +1163,16 @@ class stateactions { if (count($cmids) != count($intersect)) { throw new moodle_exception('unexistingcmid', 'core', null, $info); } + if (!empty($capabilities)) { - foreach ($cmids as $cmid) { - $modcontext = context_module::instance($cmid); - require_all_capabilities($capabilities, $modcontext); + if ($usemodcontext) { + foreach ($cmids as $cmid) { + $modcontext = context_module::instance($cmid); + require_all_capabilities($capabilities, $modcontext); + } + } else { + $coursecontext = context_course::instance($course->id); + require_all_capabilities($capabilities, $coursecontext); } } } diff --git a/course/mod.php b/course/mod.php index dd433c8da0d..c365002524e 100644 --- a/course/mod.php +++ b/course/mod.php @@ -122,8 +122,8 @@ if (!empty($add)) { $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); require_login($course, false, $cm); - $modcontext = context_module::instance($cm->id); - require_capability('moodle/course:manageactivities', $modcontext); + $coursecontext = context_course::instance($course->id); + require_all_capabilities(['moodle/backup:backuptargetimport', 'moodle/restore:restoretargetimport'], $coursecontext); // Duplicate the module. $newcm = duplicate_module($course, $cm);