From 1d1b148ca9eb601eb7945b3b14cea3fe3cb6301c Mon Sep 17 00:00:00 2001 From: Peter Dias Date: Wed, 9 Sep 2020 13:50:21 +0800 Subject: [PATCH] MDL-56310 restore: Confirm user has permission to change capabilities --- backup/moodle2/restore_stepslib.php | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 69fcf196b1d..67abb20db78 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -2121,14 +2121,29 @@ class restore_ras_and_caps_structure_step extends restore_structure_step { $data = (object)$data; // Check roleid is one of the mapped ones - $newroleid = $this->get_mappingid('role', $data->roleid); + $newrole = $this->get_mapping('role', $data->roleid); + $newroleid = $newrole->newitemid ?? false; + $userid = $this->task->get_userid(); + // If newroleid and context are valid assign it via API (it handles dupes and so on) if ($newroleid && $this->task->get_contextid()) { - if (!get_capability_info($data->capability)) { + if (!$capability = get_capability_info($data->capability)) { $this->log("Capability '{$data->capability}' was not found!", backup::LOG_WARNING); } else { - // TODO: assign_capability() needs one userid param to be able to specify our restore userid. - assign_capability($data->capability, $data->permission, $newroleid, $this->task->get_contextid()); + $context = context::instance_by_id($this->task->get_contextid()); + $overrideableroles = get_overridable_roles($context, ROLENAME_SHORT); + $safecapability = is_safe_capability($capability); + + // Check if the new role is an overrideable role AND if the user performing the restore has the + // capability to assign the capability. + if (in_array($newrole->info['shortname'], $overrideableroles) && + ($safecapability && has_capability('moodle/role:safeoverride', $context, $userid) || + !$safecapability && has_capability('moodle/role:override', $context, $userid)) + ) { + assign_capability($data->capability, $data->permission, $newroleid, $this->task->get_contextid()); + } else { + $this->log("Insufficient capability to assign capability '{$data->capability}' to role!", backup::LOG_WARNING); + } } } }