diff --git a/admin/tool/dataprivacy/classes/task/process_data_request_task.php b/admin/tool/dataprivacy/classes/task/process_data_request_task.php index 7b9fad33b0d..fe3652f3539 100644 --- a/admin/tool/dataprivacy/classes/task/process_data_request_task.php +++ b/admin/tool/dataprivacy/classes/task/process_data_request_task.php @@ -127,13 +127,17 @@ class process_data_request_task extends adhoc_task { $thing = $fs->create_file_from_pathname($filerecord, $exportedcontent); $completestatus = api::DATAREQUEST_STATUS_DOWNLOAD_READY; } else if ($request->type == api::DATAREQUEST_TYPE_DELETE) { - // Delete the data. - $manager = new \core_privacy\manager(); - $manager->set_observer(new \tool_dataprivacy\manager_observer()); + // Delete the data for users other than the primary admin, which is rejected. + if (is_primary_admin($foruser->id)) { + $completestatus = api::DATAREQUEST_STATUS_REJECTED; + } else { + $manager = new \core_privacy\manager(); + $manager->set_observer(new \tool_dataprivacy\manager_observer()); - $manager->delete_data_for_user($approvedclcollection); - $completestatus = api::DATAREQUEST_STATUS_DELETED; - $deleteuser = !$foruser->deleted; + $manager->delete_data_for_user($approvedclcollection); + $completestatus = api::DATAREQUEST_STATUS_DELETED; + $deleteuser = !$foruser->deleted; + } } // When the preparation of the metadata finishes, update the request status to awaiting approval. diff --git a/admin/tool/dataprivacy/createdatarequest_form.php b/admin/tool/dataprivacy/createdatarequest_form.php index 4c94a8a2a39..63b132d7eb5 100644 --- a/admin/tool/dataprivacy/createdatarequest_form.php +++ b/admin/tool/dataprivacy/createdatarequest_form.php @@ -134,6 +134,10 @@ class tool_dataprivacy_data_request_form extends moodleform { $errors['type'] = get_string('errorrequestalreadyexists', 'tool_dataprivacy'); } + if ($data['type'] == api::DATAREQUEST_TYPE_DELETE && is_primary_admin($data['userid'])) { + $errors['type'] = get_string('errorcannotdeleteadmin', 'tool_dataprivacy'); + } + return $errors; } } diff --git a/admin/tool/dataprivacy/lang/en/tool_dataprivacy.php b/admin/tool/dataprivacy/lang/en/tool_dataprivacy.php index bb3fa709533..881bc953415 100644 --- a/admin/tool/dataprivacy/lang/en/tool_dataprivacy.php +++ b/admin/tool/dataprivacy/lang/en/tool_dataprivacy.php @@ -124,6 +124,7 @@ $string['editpurposes'] = 'Edit purposes'; $string['effectiveretentionperiodcourse'] = '{$a} (after the course end date)'; $string['effectiveretentionperioduser'] = '{$a} (since the last time the user accessed the site)'; $string['emailsalutation'] = 'Dear {$a},'; +$string['errorcannotdeleteadmin'] = 'Cannot create deletion request for the primary site admin'; $string['errorinvalidrequestcreationmethod'] = 'Invalid request creation method!'; $string['errorinvalidrequeststatus'] = 'Invalid request status!'; $string['errorinvalidrequesttype'] = 'Invalid request type!'; diff --git a/admin/tool/dataprivacy/lib.php b/admin/tool/dataprivacy/lib.php index 8655f1ca194..4ff26e966ab 100644 --- a/admin/tool/dataprivacy/lib.php +++ b/admin/tool/dataprivacy/lib.php @@ -78,7 +78,7 @@ function tool_dataprivacy_myprofile_navigation(tree $tree, $user, $iscurrentuser // Check if the user has an ongoing data deletion request. $hasdeleterequest = \tool_dataprivacy\api::has_ongoing_request($user->id, \tool_dataprivacy\api::DATAREQUEST_TYPE_DELETE); // Show data deletion link only if the user doesn't have an ongoing data deletion request. - if (!$hasdeleterequest) { + if (!$hasdeleterequest && !is_primary_admin($user->id)) { $deleteparams = ['type' => \tool_dataprivacy\api::DATAREQUEST_TYPE_DELETE]; $deleteurl = new moodle_url('/admin/tool/dataprivacy/createdatarequest.php', $deleteparams); $deletenode = new core_user\output\myprofile\node('privacyandpolicies', 'requestdatadeletion', diff --git a/admin/tool/dataprivacy/tests/api_test.php b/admin/tool/dataprivacy/tests/api_test.php index 8e60223b96e..080878f9539 100644 --- a/admin/tool/dataprivacy/tests/api_test.php +++ b/admin/tool/dataprivacy/tests/api_test.php @@ -303,6 +303,29 @@ class tool_dataprivacy_api_testcase extends advanced_testcase { $requestid = $datarequest->get('id'); } + /** + * Test that deletion requests for the primary admin are rejected + */ + public function test_reject_data_deletion_request_primary_admin() { + $this->resetAfterTest(); + $this->setAdminUser(); + + $datarequest = api::create_data_request(get_admin()->id, api::DATAREQUEST_TYPE_DELETE); + + // Approve the request and execute the ad-hoc process task. + ob_start(); + api::approve_data_request($datarequest->get('id')); + $this->runAdhocTasks('\tool_dataprivacy\task\process_data_request_task'); + ob_end_clean(); + + $request = api::get_request($datarequest->get('id')); + $this->assertEquals(api::DATAREQUEST_STATUS_REJECTED, $request->get('status')); + + // Confirm they weren't deleted. + $user = core_user::get_user($request->get('userid')); + core_user::require_active_user($user); + } + /** * Test for api::can_contact_dpo() */ diff --git a/admin/tool/dataprivacy/tests/behat/datadelete.feature b/admin/tool/dataprivacy/tests/behat/datadelete.feature index e6c7fde6196..671c1e3e6c1 100644 --- a/admin/tool/dataprivacy/tests/behat/datadelete.feature +++ b/admin/tool/dataprivacy/tests/behat/datadelete.feature @@ -88,6 +88,12 @@ Feature: Data delete from the privacy API And I navigate to "Users > Privacy and policies > Data requests" in site administration And I should see "Deleted" + @javascript + Scenario: As a primary admin, the link to create a data deletion request should not be shown. + Given I log in as "admin" + When I follow "Profile" in the user menu + Then I should not see "Delete my account" + @javascript Scenario: As a parent, request account and data deletion for my child Given I log in as "parent"