mirror of
https://github.com/moodle/moodle.git
synced 2025-01-29 19:50:14 +01:00
MDL-48391 tool_uploadcourse: access checks for configuring enrolments.
This commit is contained in:
parent
ee23a8cf25
commit
b9a09480b2
@ -770,7 +770,20 @@ class tool_uploadcourse_course {
|
||||
|
||||
// Saving data.
|
||||
$this->data = $coursedata;
|
||||
|
||||
// Get enrolment data. Where the course already exists, we can also perform validation.
|
||||
$this->enrolmentdata = tool_uploadcourse_helper::get_enrolment_data($this->rawdata);
|
||||
if ($exists) {
|
||||
$errors = $this->validate_enrolment_data($coursedata['id'], $this->enrolmentdata);
|
||||
|
||||
if (!empty($errors)) {
|
||||
foreach ($errors as $key => $message) {
|
||||
$this->error($key, $message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->rawdata['tags']) && strval($this->rawdata['tags']) !== '') {
|
||||
$this->data['tags'] = preg_split('/\s*,\s*/', trim($this->rawdata['tags']), -1, PREG_SPLIT_NO_EMPTY);
|
||||
@ -871,6 +884,71 @@ class tool_uploadcourse_course {
|
||||
$context->mark_dirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate passed enrolment data against an existing course
|
||||
*
|
||||
* @param int $courseid
|
||||
* @param array[] $enrolmentdata
|
||||
* @return lang_string[] Errors keyed on error code
|
||||
*/
|
||||
protected function validate_enrolment_data(int $courseid, array $enrolmentdata): array {
|
||||
// Nothing to validate.
|
||||
if (empty($enrolmentdata)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$errors = [];
|
||||
|
||||
$enrolmentplugins = tool_uploadcourse_helper::get_enrolment_plugins();
|
||||
$instances = enrol_get_instances($courseid, false);
|
||||
|
||||
foreach ($enrolmentdata as $method => $options) {
|
||||
$plugin = $enrolmentplugins[$method];
|
||||
|
||||
// Find matching instances by enrolment method.
|
||||
$methodinstances = array_filter($instances, static function(stdClass $instance) use ($method) {
|
||||
return (strcmp($instance->enrol, $method) == 0);
|
||||
});
|
||||
|
||||
if (!empty($options['delete'])) {
|
||||
// Ensure user is able to delete the instances.
|
||||
foreach ($methodinstances as $methodinstance) {
|
||||
if (!$plugin->can_delete_instance($methodinstance)) {
|
||||
$errors['errorcannotdeleteenrolment'] = new lang_string('errorcannotdeleteenrolment', 'tool_uploadcourse',
|
||||
$plugin->get_instance_name($methodinstance));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!empty($options['disable'])) {
|
||||
// Ensure user is able to toggle instance statuses.
|
||||
foreach ($methodinstances as $methodinstance) {
|
||||
if (!$plugin->can_hide_show_instance($methodinstance)) {
|
||||
$errors['errorcannotdisableenrolment'] =
|
||||
new lang_string('errorcannotdisableenrolment', 'tool_uploadcourse',
|
||||
$plugin->get_instance_name($methodinstance));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Ensure user is able to create/update instance.
|
||||
$methodinstance = empty($methodinstances) ? null : reset($methodinstances);
|
||||
if ((empty($methodinstance) && !$plugin->can_add_instance($courseid)) ||
|
||||
(!empty($methodinstance) && !$plugin->can_edit_instance($methodinstance))) {
|
||||
|
||||
$errors['errorcannotcreateorupdateenrolment'] =
|
||||
new lang_string('errorcannotcreateorupdateenrolment', 'tool_uploadcourse',
|
||||
$plugin->get_instance_name($methodinstance));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the enrolment data for the course.
|
||||
*
|
||||
@ -907,7 +985,16 @@ class tool_uploadcourse_course {
|
||||
foreach ($instances as $instance) {
|
||||
if ($instance->enrol == $enrolmethod) {
|
||||
$plugin = $enrolmentplugins[$instance->enrol];
|
||||
$plugin->delete_instance($instance);
|
||||
|
||||
// Ensure user is able to delete the instance.
|
||||
if ($plugin->can_delete_instance($instance)) {
|
||||
$plugin->delete_instance($instance);
|
||||
} else {
|
||||
$this->error('errorcannotdeleteenrolment',
|
||||
new lang_string('errorcannotdeleteenrolment', 'tool_uploadcourse',
|
||||
$plugin->get_instance_name($instance)));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -916,22 +1003,37 @@ class tool_uploadcourse_course {
|
||||
foreach ($instances as $instance) {
|
||||
if ($instance->enrol == $enrolmethod) {
|
||||
$plugin = $enrolmentplugins[$instance->enrol];
|
||||
$plugin->update_status($instance, ENROL_INSTANCE_DISABLED);
|
||||
$enrol_updated = true;
|
||||
|
||||
// Ensure user is able to toggle instance status.
|
||||
if ($plugin->can_hide_show_instance($instance)) {
|
||||
$plugin->update_status($instance, ENROL_INSTANCE_DISABLED);
|
||||
} else {
|
||||
$this->error('errorcannotdisableenrolment',
|
||||
new lang_string('errorcannotdisableenrolment', 'tool_uploadcourse',
|
||||
$plugin->get_instance_name($instance)));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$plugin = null;
|
||||
if (empty($instance)) {
|
||||
$plugin = $enrolmentplugins[$enrolmethod];
|
||||
// Create/update enrolment.
|
||||
$plugin = $enrolmentplugins[$enrolmethod];
|
||||
|
||||
// Ensure user is able to create/update instance.
|
||||
if (empty($instance) && $plugin->can_add_instance($course->id)) {
|
||||
$instance = new stdClass();
|
||||
$instance->id = $plugin->add_default_instance($course);
|
||||
$instance->roleid = $plugin->get_config('roleid');
|
||||
$instance->status = ENROL_INSTANCE_ENABLED;
|
||||
} else {
|
||||
$plugin = $enrolmentplugins[$instance->enrol];
|
||||
} else if (!empty($instance) && $plugin->can_edit_instance($instance)) {
|
||||
$plugin->update_status($instance, ENROL_INSTANCE_ENABLED);
|
||||
} else {
|
||||
$this->error('errorcannotcreateorupdateenrolment',
|
||||
new lang_string('errorcannotcreateorupdateenrolment', 'tool_uploadcourse',
|
||||
$plugin->get_instance_name($instance)));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Now update values.
|
||||
|
@ -175,7 +175,7 @@ class tool_uploadcourse_helper {
|
||||
*
|
||||
* The result is cached for faster execution.
|
||||
*
|
||||
* @return array
|
||||
* @return enrol_plugin[]
|
||||
*/
|
||||
public static function get_enrolment_plugins() {
|
||||
$cache = cache::make('tool_uploadcourse', 'helper');
|
||||
|
@ -78,6 +78,9 @@ $string['defaultvalues'] = 'Default course values';
|
||||
$string['defaultvaluescustomfieldcategory'] = 'Default values for \'{$a}\'';
|
||||
$string['encoding'] = 'Encoding';
|
||||
$string['encoding_help'] = 'Encoding of the CSV file.';
|
||||
$string['errorcannotcreateorupdateenrolment'] = 'Cannot create or update enrolment method \'{$a}\'';
|
||||
$string['errorcannotdeleteenrolment'] = 'Cannot delete enrolment method \'{$a}\'';
|
||||
$string['errorcannotdisableenrolment'] = 'Cannot disable enrolment method \'{$a}\'';
|
||||
$string['errorwhilerestoringcourse'] = 'Error while restoring the course';
|
||||
$string['errorwhiledeletingcourse'] = 'Error while deleting the course';
|
||||
$string['generatedshortnameinvalid'] = 'The generated shortname is invalid';
|
||||
|
@ -1055,6 +1055,9 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
|
||||
public function test_enrolment_data() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// We need to set the current user as one with the capability to edit manual enrolment instances in the new course.
|
||||
$this->setAdminUser();
|
||||
|
||||
$mode = tool_uploadcourse_processor::MODE_CREATE_NEW;
|
||||
$updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
|
||||
$data = array('shortname' => 'c1', 'summary' => 'S', 'fullname' => 'FN', 'category' => '1');
|
||||
@ -1081,6 +1084,123 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
|
||||
$this->assertEquals(strtotime('12th July 2013'), $enroldata['manual']->enrolenddate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testing enrolment errors
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function enrolment_uploaddata_error_provider(): array {
|
||||
return [
|
||||
['errorcannotcreateorupdateenrolment', [
|
||||
'shortname' => 'C1',
|
||||
'enrolment_1' => 'manual',
|
||||
]],
|
||||
['errorcannotdeleteenrolment', [
|
||||
'shortname' => 'C1',
|
||||
'enrolment_1' => 'manual',
|
||||
'enrolment_1_delete' => '1',
|
||||
]],
|
||||
['errorcannotdisableenrolment', [
|
||||
'shortname' => 'C1',
|
||||
'enrolment_1' => 'manual',
|
||||
'enrolment_1_disable' => '1',
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that user without permission, cannot modify enrolment instances when creating courses
|
||||
*
|
||||
* @param string $expectederror
|
||||
* @param array $uploaddata
|
||||
*
|
||||
* @dataProvider enrolment_uploaddata_error_provider
|
||||
*/
|
||||
public function test_enrolment_error_create_course(string $expectederror, array $uploaddata): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create category in which to create the new course.
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$categorycontext = context_coursecat::instance($category->id);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
// Assign the user as a manager of the category, disable ability to configure manual enrolment instances.
|
||||
$roleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
|
||||
role_assign($roleid, $user->id, $categorycontext);
|
||||
role_change_permission($roleid, $categorycontext, 'enrol/manual:config', CAP_PROHIBIT);
|
||||
|
||||
$mode = tool_uploadcourse_processor::MODE_CREATE_NEW;
|
||||
$updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
|
||||
|
||||
$upload = new tool_uploadcourse_course($mode, $updatemode, array_merge($uploaddata, [
|
||||
'category' => $category->id,
|
||||
'fullname' => 'My course',
|
||||
]));
|
||||
|
||||
// Enrolment validation isn't performed during 'prepare' for new courses.
|
||||
$this->assertTrue($upload->prepare());
|
||||
$upload->proceed();
|
||||
|
||||
$errors = $upload->get_errors();
|
||||
$this->assertArrayHasKey($expectederror, $errors);
|
||||
|
||||
$this->assertEquals(get_string($expectederror, 'tool_uploadcourse', 'Manual enrolments'),
|
||||
(string) $errors[$expectederror]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that user without permission, cannot modify enrolment instances when updating courses
|
||||
*
|
||||
* @param string $expectederror
|
||||
* @param array $uploaddata
|
||||
*
|
||||
* @dataProvider enrolment_uploaddata_error_provider
|
||||
*/
|
||||
public function test_enrolment_error_update_course(string $expectederror, array $uploaddata): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create category in which to create the new course.
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$categorycontext = context_coursecat::instance($category->id);
|
||||
|
||||
$course = $this->getDataGenerator()->create_course([
|
||||
'category' => $category->id,
|
||||
'shortname' => $uploaddata['shortname'],
|
||||
]);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
// Assign the user as a manager of the category, disable ability to configure manual enrolment instances.
|
||||
$roleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
|
||||
role_assign($roleid, $user->id, $categorycontext);
|
||||
role_change_permission($roleid, $categorycontext, 'enrol/manual:config', CAP_PROHIBIT);
|
||||
|
||||
// Sanity check.
|
||||
$instances = enrol_get_instances($course->id, true);
|
||||
$this->assertCount(1, $instances);
|
||||
$this->assertEquals('manual', reset($instances)->enrol);
|
||||
|
||||
$mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY;
|
||||
$updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
|
||||
|
||||
$upload = new tool_uploadcourse_course($mode, $updatemode, $uploaddata);
|
||||
|
||||
$this->assertFalse($upload->prepare());
|
||||
|
||||
$errors = $upload->get_errors();
|
||||
$this->assertArrayHasKey($expectederror, $errors);
|
||||
|
||||
$this->assertEquals(get_string($expectederror, 'tool_uploadcourse', 'Manual enrolments'),
|
||||
(string) $errors[$expectederror]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test upload processing of course custom fields
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user