mirrored from git://git.moodle.org/moodle.git
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MDL-72265 backup: fix checking of override capabilites on restore
Thanks to Peter Dias <peter@moodle.com> for his help with the unit test.
- Loading branch information
Showing
6 changed files
with
216 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
<?php | ||
// This file is part of Moodle - http://moodle.org/ | ||
// | ||
// Moodle is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// Moodle is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
defined('MOODLE_INTERNAL') || die(); | ||
|
||
// Include all the needed stuff. | ||
global $CFG; | ||
require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); | ||
require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); | ||
|
||
|
||
/** | ||
* Unit tests for how backup and restore handles role-related things. | ||
* | ||
* @package core_backup | ||
* @copyright 2021 The Open University | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
class roles_backup_restore_test extends advanced_testcase { | ||
|
||
/** | ||
* Create a course where the (non-editing) Teacher role is overridden | ||
* to have 'moodle/user:loginas' and 'moodle/site:accessallgroups'. | ||
* | ||
* @return stdClass the new course. | ||
*/ | ||
protected function create_course_with_role_overrides(): stdClass { | ||
$generator = $this->getDataGenerator(); | ||
$course = $generator->create_course(); | ||
$teacher = $generator->create_user(); | ||
|
||
$context = context_course::instance($course->id); | ||
$generator->enrol_user($teacher->id, $course->id, 'teacher'); | ||
|
||
$editingteacherrole = $this->get_role('teacher'); | ||
role_change_permission($editingteacherrole->id, $context, 'moodle/user:loginas', CAP_ALLOW); | ||
role_change_permission($editingteacherrole->id, $context, 'moodle/site:accessallgroups', CAP_ALLOW); | ||
|
||
return $course; | ||
} | ||
|
||
/** | ||
* Get the role id from a shortname. | ||
* | ||
* @param string $shortname the role shortname. | ||
* @return stdClass the role from the DB. | ||
*/ | ||
protected function get_role(string $shortname): stdClass { | ||
global $DB; | ||
return $DB->get_record('role', ['shortname' => $shortname]); | ||
} | ||
|
||
/** | ||
* Get an array capability => CAP_... constant for all the orverrides set for a given role on a given context. | ||
* | ||
* @param string $shortname role shortname. | ||
* @param context $context context. | ||
* @return array the overrides set here. | ||
*/ | ||
protected function get_overrides_for_role_on_context(string $shortname, context $context): array { | ||
$overridedata = get_capabilities_from_role_on_context($this->get_role($shortname), $context); | ||
$overrides = []; | ||
foreach ($overridedata as $override) { | ||
$overrides[$override->capability] = $override->permission; | ||
} | ||
return $overrides; | ||
} | ||
|
||
/** | ||
* Makes a backup of the course. | ||
* | ||
* @param stdClass $course The course object. | ||
* @return string Unique identifier for this backup. | ||
*/ | ||
protected function backup_course(\stdClass $course): string { | ||
global $CFG, $USER; | ||
|
||
// Turn off file logging, otherwise it can't delete the file (Windows). | ||
$CFG->backup_file_logger_level = backup::LOG_NONE; | ||
|
||
// Do backup with default settings. MODE_IMPORT means it will just | ||
// create the directory and not zip it. | ||
$bc = new \backup_controller(backup::TYPE_1COURSE, $course->id, | ||
backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_IMPORT, | ||
$USER->id); | ||
$backupid = $bc->get_backupid(); | ||
$bc->execute_plan(); | ||
$bc->destroy(); | ||
|
||
return $backupid; | ||
} | ||
|
||
/** | ||
* Restores a backup that has been made earlier. | ||
* | ||
* @param string $backupid The unique identifier of the backup. | ||
* @param string $asroleshortname Which role in the new cousre the restorer should have. | ||
* @return int The new course id. | ||
*/ | ||
protected function restore_adding_to_course(string $backupid, string $asroleshortname): int { | ||
global $CFG, $USER; | ||
|
||
// Create course to restore into, and a user to do the restore. | ||
$generator = $this->getDataGenerator(); | ||
$course = $generator->create_course(); | ||
$restorer = $generator->create_user(); | ||
|
||
$generator->enrol_user($restorer->id, $course->id, $asroleshortname); | ||
$this->setUser($restorer); | ||
|
||
// Turn off file logging, otherwise it can't delete the file (Windows). | ||
$CFG->backup_file_logger_level = backup::LOG_NONE; | ||
|
||
// Do restore to new course with default settings. | ||
$rc = new \restore_controller($backupid, $course->id, | ||
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $USER->id, | ||
backup::TARGET_CURRENT_ADDING); | ||
|
||
$precheck = $rc->execute_precheck(); | ||
$this->assertTrue($precheck); | ||
$rc->get_plan()->get_setting('role_assignments')->set_value(true); | ||
$rc->get_plan()->get_setting('permissions')->set_value(true); | ||
$rc->execute_plan(); | ||
$rc->destroy(); | ||
|
||
return $course->id; | ||
} | ||
|
||
public function test_restore_role_overrides_as_manager(): void { | ||
$this->resetAfterTest(); | ||
$this->setAdminUser(); | ||
|
||
// Create a course and back it up. | ||
$course = $this->create_course_with_role_overrides(); | ||
$backupid = $this->backup_course($course); | ||
|
||
// When manager restores, both role overrides should be restored. | ||
$newcourseid = $this->restore_adding_to_course($backupid, 'manager'); | ||
|
||
// Verify. | ||
$overrides = $this->get_overrides_for_role_on_context('teacher', | ||
context_course::instance($newcourseid)); | ||
$this->assertArrayHasKey('moodle/user:loginas', $overrides); | ||
$this->assertEquals(CAP_ALLOW, $overrides['moodle/user:loginas']); | ||
$this->assertArrayHasKey('moodle/site:accessallgroups', $overrides); | ||
$this->assertEquals(CAP_ALLOW, $overrides['moodle/site:accessallgroups']); | ||
} | ||
|
||
public function test_restore_role_overrides_as_teacher(): void { | ||
$this->resetAfterTest(); | ||
$this->setAdminUser(); | ||
|
||
// Create a course and back it up. | ||
$course = $this->create_course_with_role_overrides(); | ||
$backupid = $this->backup_course($course); | ||
|
||
// When teacher restores, only the safe override should be restored. | ||
$newcourseid = $this->restore_adding_to_course($backupid, 'editingteacher'); | ||
|
||
// Verify. | ||
$overrides = $this->get_overrides_for_role_on_context('teacher', | ||
context_course::instance($newcourseid)); | ||
$this->assertArrayNotHasKey('moodle/user:loginas', $overrides); | ||
$this->assertArrayHasKey('moodle/site:accessallgroups', $overrides); | ||
$this->assertEquals(CAP_ALLOW, $overrides['moodle/site:accessallgroups']); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters