require_login($course, false, $cm);
require_capability('moodle/restore:uploadfile', $context);
+if ($filearea == 'automated' && !can_download_from_backup_filearea($filearea, $context)) {
+ throw new required_capability_exception($context, 'moodle/backup:downloadfile', 'nopermissions', '');
+}
$PAGE->set_url($url);
$PAGE->set_context($context);
$params['contextid'] = $viewer->currentcontext->id;
$params['itemid'] = $file->get_itemid();
$restoreurl = new moodle_url('/backup/restorefile.php', $params);
+ $restorelink = html_writer::link($restoreurl, get_string('restore'));
+ $downloadlink = html_writer::link($fileurl, get_string('download'));
+
+ // Conditional display of the restore and download links, initially only for the 'automated' filearea.
+ if ($params['filearea'] == 'automated') {
+ if (!has_capability('moodle/restore:viewautomatedfilearea', $viewer->currentcontext)) {
+ $restorelink = '';
+ }
+ if (!can_download_from_backup_filearea($params['filearea'], $viewer->currentcontext)) {
+ $downloadlink = '';
+ }
+ }
$table->data[] = array(
$file->get_filename(),
userdate($file->get_timemodified()),
display_size($file->get_filesize()),
- html_writer::link($fileurl, get_string('download')),
- html_writer::link($restoreurl, get_string('restore')),
+ $downloadlink,
+ $restorelink,
);
}
$html = html_writer::table($table);
- $html .= $this->output->single_button(
- new moodle_url('/backup/backupfilesedit.php', array(
- 'currentcontext' => $viewer->currentcontext->id,
- 'contextid' => $viewer->filecontext->id,
- 'filearea' => $viewer->filearea,
- 'component' => $viewer->component,
- 'returnurl' => $this->page->url->out())
- ),
- get_string('managefiles', 'backup'),
- 'post'
- );
+
+ // For automated backups, the ability to manage backup files is controlled by the ability to download them.
+ // All files must be from the same file area in a backup_files_viewer.
+ $canmanagebackups = true;
+ if ($viewer->filearea == 'automated') {
+ if (!can_download_from_backup_filearea($viewer->filearea, $viewer->currentcontext)) {
+ $canmanagebackups = false;
+ }
+ }
+
+ if ($canmanagebackups) {
+ $html .= $this->output->single_button(
+ new moodle_url('/backup/backupfilesedit.php', array(
+ 'currentcontext' => $viewer->currentcontext->id,
+ 'contextid' => $viewer->filecontext->id,
+ 'filearea' => $viewer->filearea,
+ 'component' => $viewer->component,
+ 'returnurl' => $this->page->url->out())
+ ),
+ get_string('managefiles', 'backup'),
+ 'post'
+ );
+ }
return $html;
}
throw new required_capability_exception($context, $viewparticipantscap, 'nopermissions', '');
}
}
+
+/**
+ * Return whether the user can download from the specified backup file area in the given context.
+ *
+ * @param string $filearea the backup file area. E.g. 'course', 'backup' or 'automated'.
+ * @param \context $context
+ * @param stdClass $user the user object. If not provided, the current user will be checked.
+ * @return bool true if the user is allowed to download in the context, false otherwise.
+ */
+function can_download_from_backup_filearea($filearea, \context $context, stdClass $user = null) {
+ $candownload = false;
+ switch ($filearea) {
+ case 'course':
+ case 'backup':
+ $candownload = has_capability('moodle/backup:downloadfile', $context, $user);
+ break;
+ case 'automated':
+ // Given the automated backups may contain userinfo, we restrict access such that only users who are able to
+ // restore with userinfo are able to download the file. Users can't create these backups, so checking 'backup:userinfo'
+ // doesn't make sense here.
+ $candownload = has_capability('moodle/backup:downloadfile', $context, $user) &&
+ has_capability('moodle/restore:userinfo', $context, $user);
+ break;
+ default:
+ break;
+
+ }
+ return $candownload;
+}
$this->expectException('required_capability_exception');
course_require_view_participants(context_system::instance());
}
+
+ /**
+ * Testing the can_download_from_backup_filearea fn.
+ */
+ public function test_can_download_from_backup_filearea() {
+ global $DB;
+ $this->resetAfterTest();
+ $course = $this->getDataGenerator()->create_course();
+ $context = context_course::instance($course->id);
+ $user = $this->getDataGenerator()->create_user();
+ $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
+ $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
+
+ // The 'automated' backup area. Downloading from this area requires two capabilities.
+ // If the user has only the 'backup:downloadfile' capability.
+ unassign_capability('moodle/restore:userinfo', $teacherrole->id, $context);
+ assign_capability('moodle/backup:downloadfile', CAP_ALLOW, $teacherrole->id, $context);
+ $this->assertFalse(can_download_from_backup_filearea('automated', $context, $user));
+
+ // If the user has only the 'restore:userinfo' capability.
+ unassign_capability('moodle/backup:downloadfile', $teacherrole->id, $context);
+ assign_capability('moodle/restore:userinfo', CAP_ALLOW, $teacherrole->id, $context);
+ $this->assertFalse(can_download_from_backup_filearea('automated', $context, $user));
+
+ // If the user has both capabilities.
+ assign_capability('moodle/backup:downloadfile', CAP_ALLOW, $teacherrole->id, $context);
+ assign_capability('moodle/restore:userinfo', CAP_ALLOW, $teacherrole->id, $context);
+ $this->assertTrue(can_download_from_backup_filearea('automated', $context, $user));
+
+ // Is the user has neither of the capabilities.
+ unassign_capability('moodle/backup:downloadfile', $teacherrole->id, $context);
+ unassign_capability('moodle/restore:userinfo', $teacherrole->id, $context);
+ $this->assertFalse(can_download_from_backup_filearea('automated', $context, $user));
+
+ // The 'course ' and 'backup' backup file areas. These are governed by the same download capability.
+ // User has the capability.
+ unassign_capability('moodle/restore:userinfo', $teacherrole->id, $context);
+ assign_capability('moodle/backup:downloadfile', CAP_ALLOW, $teacherrole->id, $context);
+ $this->assertTrue(can_download_from_backup_filearea('course', $context, $user));
+ $this->assertTrue(can_download_from_backup_filearea('backup', $context, $user));
+
+ // User doesn't have the capability.
+ unassign_capability('moodle/backup:downloadfile', $teacherrole->id, $context);
+ $this->assertFalse(can_download_from_backup_filearea('course', $context, $user));
+ $this->assertFalse(can_download_from_backup_filearea('backup', $context, $user));
+
+ // A file area that doesn't exist. No permissions, regardless of capabilities.
+ assign_capability('moodle/backup:downloadfile', CAP_ALLOW, $teacherrole->id, $context);
+ $this->assertFalse(can_download_from_backup_filearea('testing', $context, $user));
+ }
}