Merge branch 'MDL-64030-34' of git://github.com/andrewnicols/moodle into MOODLE_34_STABLE

This commit is contained in:
Jun Pataleta
2018-11-23 11:15:20 +08:00
5 changed files with 119 additions and 7 deletions
+12 -3
View File
@@ -1075,6 +1075,7 @@ class api {
public static function add_request_contexts_with_status(contextlist_collection $clcollection, int $requestid, int $status) {
$request = new data_request($requestid);
$user = \core_user::get_user($request->get('userid'));
$isconfigured = data_registry::defaults_set();
foreach ($clcollection as $contextlist) {
// Convert the \core_privacy\local\request\contextlist into a contextlist persistent and store it.
$clp = \tool_dataprivacy\contextlist::from_contextlist($contextlist);
@@ -1083,7 +1084,11 @@ class api {
// Store the associated contexts in the contextlist.
foreach ($contextlist->get_contextids() as $contextid) {
if ($request->get('type') == static::DATAREQUEST_TYPE_DELETE) {
if ($isconfigured && self::DATAREQUEST_TYPE_DELETE == $request->get('type')) {
// Data can only be deleted from it if the context is either expired, or unprotected.
// Note: We can only check whether a context is expired or unprotected if the site is configured and
// defaults are set appropriately. If they are not, we treat all contexts as though they are
// unprotected.
$context = \context::instance_by_id($contextid);
$purpose = static::get_effective_context_purpose($context);
@@ -1163,10 +1168,11 @@ class api {
* @return contextlist_collection the collection of approved_contextlist objects.
*/
public static function get_approved_contextlist_collection_for_request(data_request $request) : contextlist_collection {
global $DB;
$foruser = core_user::get_user($request->get('userid'));
$isconfigured = data_registry::defaults_set();
// Fetch all approved contextlists and create the core_privacy\local\request\contextlist objects here.
global $DB;
$sql = "SELECT cl.component, ctx.contextid
FROM {" . request_contextlist::TABLE . "} rcl
JOIN {" . contextlist::TABLE . "} cl ON rcl.contextlistid = cl.id
@@ -1190,10 +1196,13 @@ class api {
$contexts = [];
}
if ($request->get('type') == static::DATAREQUEST_TYPE_DELETE) {
if ($isconfigured && $request->get('type') == static::DATAREQUEST_TYPE_DELETE) {
$context = \context::instance_by_id($record->contextid);
$purpose = static::get_effective_context_purpose($context);
// Data can only be deleted from it if the context is either expired, or unprotected.
// Note: We can only check whether a context is expired or unprotected if the site is configured and
// defaults are set appropriately. If they are not, we treat all contexts as though they are
// unprotected.
if (!expired_contexts_manager::is_context_expired_or_unprotected_for_user($context, $foruser)) {
continue;
}
@@ -74,11 +74,9 @@ class process_data_request_task extends adhoc_task {
return;
}
// If no site purpose is defined, reject requests since they cannot be processed.
if (!\tool_dataprivacy\data_registry::defaults_set()) {
api::update_request_status($requestid, api::DATAREQUEST_STATUS_REJECTED);
mtrace('No site purpose defined. Request ' . $requestid . ' rejected.');
return;
// Warn if no site purpose is defined.
mtrace('Warning: No purpose is defined at the system level. Deletion will delete all.');
}
// Get the user details now. We might not be able to retrieve it later if it's a deletion processing.
+4
View File
@@ -38,6 +38,10 @@ $title = get_string('datarequests', 'tool_dataprivacy');
echo $OUTPUT->header();
echo $OUTPUT->heading($title);
if (!\tool_dataprivacy\data_registry::defaults_set()) {
\core\notification::error(get_string('systemconfignotsetwarning', 'tool_dataprivacy'));
}
if (\tool_dataprivacy\api::is_site_dpo($USER->id)) {
$filtersapplied = optional_param_array('request-filters', [-1], PARAM_NOTAGS);
$filterscleared = optional_param('filters-cleared', 0, PARAM_INT);
@@ -308,6 +308,7 @@ $string['statusrejected'] = 'Rejected';
$string['subjectscope'] = 'Subject scope';
$string['subjectscope_help'] = 'The subject scope lists the roles which may be assigned in this context.';
$string['summary'] = 'Registry configuration summary';
$string['systemconfignotsetwarning'] = 'A site purpose and category have not been defined. When these are not defined, all data will be removed when processing deletion requests.';
$string['user'] = 'User';
$string['userlistnoncompliant'] = 'Userlist provider missing';
$string['userlistexplanation'] = 'This plugin has the base provider but should also implement the userlist provider for full support of privacy functionality.';
+100
View File
@@ -1711,6 +1711,48 @@ class tool_dataprivacy_api_testcase extends advanced_testcase {
$this->assertEquals($data->contexts->used, $contextids, '', 0.0, 10, true);
}
/**
* Test that delete requests do not filter out protected purpose contexts if the the site is properly configured.
*/
public function test_add_request_contexts_with_status_delete_course_no_site_config() {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course(['startdate' => time() - YEARSECS, 'enddate' => time() - YEARSECS]);
$coursecontext = \context_course::instance($course->id);
$forum = $this->getDataGenerator()->create_module('forum', ['course' => $course->id]);
list(, $forumcm) = get_course_and_cm_from_instance($forum->id, 'forum');
$contextforum = \context_module::instance($forumcm->id);
$this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
// Create the initial contextlist.
$initialcollection = new \core_privacy\local\request\contextlist_collection($user->id);
$contextlist = new \core_privacy\local\request\contextlist();
$contextlist->add_from_sql('SELECT id FROM {context} WHERE id = :contextid', ['contextid' => $coursecontext->id]);
$contextlist->set_component('tool_dataprivacy');
$initialcollection->add_contextlist($contextlist);
$contextlist = new \core_privacy\local\request\contextlist();
$contextlist->add_from_sql('SELECT id FROM {context} WHERE id = :contextid', ['contextid' => $contextforum->id]);
$contextlist->set_component('mod_forum');
$initialcollection->add_contextlist($contextlist);
$request = api::create_data_request($user->id, api::DATAREQUEST_TYPE_DELETE);
api::add_request_contexts_with_status(
$initialcollection, $request->get('id'), contextlist_context::STATUS_APPROVED);
$newcollection = \tool_dataprivacy\request_contextlist::get_records();
$this->assertCount(2, $newcollection);
foreach ($newcollection as $contextlist) {
$requests = contextlist_context::get_records(['contextlistid' => $contextlist->get('contextlistid')]);
$this->assertCount(1, $requests);
}
}
/**
* Test that delete requests do not filter out protected purpose contexts if they are already expired.
*/
@@ -1807,6 +1849,64 @@ class tool_dataprivacy_api_testcase extends advanced_testcase {
$this->assertCount(1, $requests);
}
/**
* Test that delete requests do not filter out protected purpose contexts if the the site is properly configured.
*/
public function test_get_approved_contextlist_collection_for_request_delete_course_no_config() {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course(['startdate' => time() - YEARSECS, 'enddate' => time() - YEARSECS]);
$coursecontext = \context_course::instance($course->id);
$forum = $this->getDataGenerator()->create_module('forum', ['course' => $course->id]);
list(, $forumcm) = get_course_and_cm_from_instance($forum->id, 'forum');
$contextforum = \context_module::instance($forumcm->id);
$this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
// Create the initial contextlist.
$request = api::create_data_request($user->id, api::DATAREQUEST_TYPE_DELETE);
$initialcollection = new \core_privacy\local\request\contextlist_collection($user->id);
$contextlist = new \tool_dataprivacy\contextlist(0, (object) ['component' => 'tool_dataprivacy']);
$contextlist->save();
$clcontext = new \tool_dataprivacy\contextlist_context(0, (object) [
'contextid' => $coursecontext->id,
'status' => contextlist_context::STATUS_APPROVED,
'contextlistid' => $contextlist->get('id'),
]);
$clcontext->save();
$rcl = new \tool_dataprivacy\request_contextlist(0, (object) [
'requestid' => $request->get('id'),
'contextlistid' => $contextlist->get('id'),
]);
$rcl->save();
$contextlist = new \tool_dataprivacy\contextlist(0, (object) ['component' => 'mod_forum']);
$contextlist->save();
$clcontext = new \tool_dataprivacy\contextlist_context(0, (object) [
'contextid' => $contextforum->id,
'status' => contextlist_context::STATUS_APPROVED,
'contextlistid' => $contextlist->get('id'),
]);
$clcontext->save();
$rcl = new \tool_dataprivacy\request_contextlist(0, (object) [
'requestid' => $request->get('id'),
'contextlistid' => $contextlist->get('id'),
]);
$rcl->save();
$collection = api::get_approved_contextlist_collection_for_request($request);
$this->assertCount(2, $collection);
$list = $collection->get_contextlist_for_component('tool_dataprivacy');
$this->assertCount(1, $list);
$list = $collection->get_contextlist_for_component('mod_forum');
$this->assertCount(1, $list);
}
/**
* Test that delete requests do not filter out protected purpose contexts if they are already expired.
*/