mirror of
https://github.com/moodle/moodle.git
synced 2025-08-11 20:06:46 +02:00
Merge branch 'MDL-61652-35' of git://github.com/mihailges/moodle into MOODLE_35_STABLE
This commit is contained in:
commit
ab9f7ab790
10 changed files with 289 additions and 30 deletions
|
@ -608,6 +608,54 @@ class api {
|
||||||
return has_capability('tool/dataprivacy:makedatarequestsforchildren', $usercontext, $requester);
|
return has_capability('tool/dataprivacy:makedatarequestsforchildren', $usercontext, $requester);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a user can download a data request.
|
||||||
|
*
|
||||||
|
* @param int $userid Target user id (subject of data request)
|
||||||
|
* @param int $requesterid Requester user id (person who requsted it)
|
||||||
|
* @param int|null $downloaderid Person who wants to download user id (default current)
|
||||||
|
* @return bool
|
||||||
|
* @throws coding_exception
|
||||||
|
*/
|
||||||
|
public static function can_download_data_request_for_user($userid, $requesterid, $downloaderid = null) {
|
||||||
|
global $USER;
|
||||||
|
|
||||||
|
if (!$downloaderid) {
|
||||||
|
$downloaderid = $USER->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$usercontext = \context_user::instance($userid);
|
||||||
|
// If it's your own and you have the right capability, you can download it.
|
||||||
|
if ($userid == $downloaderid && has_capability('tool/dataprivacy:downloadownrequest', $usercontext, $downloaderid)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If you can download anyone's in that context, you can download it.
|
||||||
|
if (has_capability('tool/dataprivacy:downloadallrequests', $usercontext, $downloaderid)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If you can have the 'child access' ability to request in that context, and you are the one
|
||||||
|
// who requested it, then you can download it.
|
||||||
|
if ($requesterid == $downloaderid && self::can_create_data_request_for_user($userid, $requesterid)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an action menu link to download a data request.
|
||||||
|
*
|
||||||
|
* @param \context_user $usercontext User context (of user who the data is for)
|
||||||
|
* @param int $requestid Request id
|
||||||
|
* @return \action_menu_link_secondary Action menu link
|
||||||
|
* @throws coding_exception
|
||||||
|
*/
|
||||||
|
public static function get_download_link(\context_user $usercontext, $requestid) {
|
||||||
|
$downloadurl = moodle_url::make_pluginfile_url($usercontext->id,
|
||||||
|
'tool_dataprivacy', 'export', $requestid, '/', 'export.zip', true);
|
||||||
|
$downloadtext = get_string('download', 'tool_dataprivacy');
|
||||||
|
return new \action_menu_link_secondary($downloadurl, null, $downloadtext);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new data purpose.
|
* Creates a new data purpose.
|
||||||
*
|
*
|
||||||
|
|
|
@ -208,6 +208,14 @@ class data_requests_table extends table_sql {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($status == api::DATAREQUEST_STATUS_COMPLETE) {
|
||||||
|
$userid = $data->foruser->id;
|
||||||
|
$usercontext = \context_user::instance($userid, IGNORE_MISSING);
|
||||||
|
if ($usercontext && api::can_download_data_request_for_user($userid, $data->requestedbyuser->id)) {
|
||||||
|
$actions[] = api::get_download_link($usercontext, $requestid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$actionsmenu = new action_menu($actions);
|
$actionsmenu = new action_menu($actions);
|
||||||
$actionsmenu->set_menu_trigger(get_string('actions'));
|
$actionsmenu->set_menu_trigger(get_string('actions'));
|
||||||
$actionsmenu->set_owner_selector('request-actions-' . $requestid);
|
$actionsmenu->set_owner_selector('request-actions-' . $requestid);
|
||||||
|
|
|
@ -95,7 +95,8 @@ class my_data_requests_page implements renderable, templatable {
|
||||||
$requestexporter = new data_request_exporter($request, ['context' => $outputcontext]);
|
$requestexporter = new data_request_exporter($request, ['context' => $outputcontext]);
|
||||||
$item = $requestexporter->export($output);
|
$item = $requestexporter->export($output);
|
||||||
|
|
||||||
if ($request->get('userid') != $USER->id) {
|
$self = $request->get('userid') == $USER->id;
|
||||||
|
if (!$self) {
|
||||||
// Append user name if it differs from $USER.
|
// Append user name if it differs from $USER.
|
||||||
$a = (object)['typename' => $item->typename, 'user' => $item->foruser->fullname];
|
$a = (object)['typename' => $item->typename, 'user' => $item->foruser->fullname];
|
||||||
$item->typename = get_string('requesttypeuser', 'tool_dataprivacy', $a);
|
$item->typename = get_string('requesttypeuser', 'tool_dataprivacy', $a);
|
||||||
|
@ -110,6 +111,10 @@ class my_data_requests_page implements renderable, templatable {
|
||||||
$cancancel = false;
|
$cancancel = false;
|
||||||
// Show download links only for export-type data requests.
|
// Show download links only for export-type data requests.
|
||||||
$candownload = $type == api::DATAREQUEST_TYPE_EXPORT;
|
$candownload = $type == api::DATAREQUEST_TYPE_EXPORT;
|
||||||
|
if ($usercontext) {
|
||||||
|
$candownload = api::can_download_data_request_for_user(
|
||||||
|
$request->get('userid'), $request->get('requestedby'));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case api::DATAREQUEST_STATUS_CANCELLED:
|
case api::DATAREQUEST_STATUS_CANCELLED:
|
||||||
case api::DATAREQUEST_STATUS_REJECTED:
|
case api::DATAREQUEST_STATUS_REJECTED:
|
||||||
|
@ -126,10 +131,7 @@ class my_data_requests_page implements renderable, templatable {
|
||||||
$actions[] = new action_menu_link_secondary($cancelurl, null, $canceltext, $canceldata);
|
$actions[] = new action_menu_link_secondary($cancelurl, null, $canceltext, $canceldata);
|
||||||
}
|
}
|
||||||
if ($candownload && $usercontext) {
|
if ($candownload && $usercontext) {
|
||||||
$downloadurl = moodle_url::make_pluginfile_url($usercontext->id, 'tool_dataprivacy', 'export', $requestid, '/',
|
$actions[] = api::get_download_link($usercontext, $requestid);
|
||||||
'export.zip', true);
|
|
||||||
$downloadtext = get_string('download', 'tool_dataprivacy');
|
|
||||||
$actions[] = new action_menu_link_secondary($downloadurl, null, $downloadtext);
|
|
||||||
}
|
}
|
||||||
if (!empty($actions)) {
|
if (!empty($actions)) {
|
||||||
$actionsmenu = new action_menu($actions);
|
$actionsmenu = new action_menu($actions);
|
||||||
|
|
|
@ -139,8 +139,17 @@ class process_data_request_task extends adhoc_task {
|
||||||
|
|
||||||
$output = $PAGE->get_renderer('tool_dataprivacy');
|
$output = $PAGE->get_renderer('tool_dataprivacy');
|
||||||
$emailonly = false;
|
$emailonly = false;
|
||||||
|
$notifyuser = true;
|
||||||
switch ($request->type) {
|
switch ($request->type) {
|
||||||
case api::DATAREQUEST_TYPE_EXPORT:
|
case api::DATAREQUEST_TYPE_EXPORT:
|
||||||
|
// Check if the user is allowed to download their own export. (This is for
|
||||||
|
// institutions which centrally co-ordinate subject access request across many
|
||||||
|
// systems, not just one Moodle instance, so we don't want every instance emailing
|
||||||
|
// the user.)
|
||||||
|
if (!api::can_download_data_request_for_user($request->userid, $request->requestedby, $request->userid)) {
|
||||||
|
$notifyuser = false;
|
||||||
|
}
|
||||||
|
|
||||||
$typetext = get_string('requesttypeexport', 'tool_dataprivacy');
|
$typetext = get_string('requesttypeexport', 'tool_dataprivacy');
|
||||||
// We want to notify the user in Moodle about the processing results.
|
// We want to notify the user in Moodle about the processing results.
|
||||||
$message->notification = 1;
|
$message->notification = 1;
|
||||||
|
@ -179,18 +188,40 @@ class process_data_request_task extends adhoc_task {
|
||||||
$message->fullmessagehtml = $messagehtml;
|
$message->fullmessagehtml = $messagehtml;
|
||||||
|
|
||||||
// Send message to the user involved.
|
// Send message to the user involved.
|
||||||
|
if ($notifyuser) {
|
||||||
if ($emailonly) {
|
if ($emailonly) {
|
||||||
email_to_user($foruser, $dpo, $subject, $message->fullmessage, $messagehtml);
|
email_to_user($foruser, $dpo, $subject, $message->fullmessage, $messagehtml);
|
||||||
} else {
|
} else {
|
||||||
message_send($message);
|
message_send($message);
|
||||||
}
|
}
|
||||||
mtrace('Message sent to user: ' . $messagetextdata['username']);
|
mtrace('Message sent to user: ' . $messagetextdata['username']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send to requester as well in some circumstances.
|
||||||
|
if ($foruser->id != $request->requestedby) {
|
||||||
|
$sendtorequester = false;
|
||||||
|
switch ($request->type) {
|
||||||
|
case api::DATAREQUEST_TYPE_EXPORT:
|
||||||
|
// Send to the requester as well if they can download it, unless they are the
|
||||||
|
// DPO. If we didn't notify the user themselves (because they can't download)
|
||||||
|
// then send to requester even if it is the DPO, as in that case the requester
|
||||||
|
// needs to take some action.
|
||||||
|
if (api::can_download_data_request_for_user($request->userid, $request->requestedby, $request->requestedby)) {
|
||||||
|
$sendtorequester = !$notifyuser || !api::is_site_dpo($request->requestedby);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case api::DATAREQUEST_TYPE_DELETE:
|
||||||
|
// Send to the requester if they are not the DPO and if they are allowed to
|
||||||
|
// create data requests for the user (e.g. Parent).
|
||||||
|
$sendtorequester = !api::is_site_dpo($request->requestedby) &&
|
||||||
|
api::can_create_data_request_for_user($request->userid, $request->requestedby);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new moodle_exception('errorinvalidrequesttype', 'tool_dataprivacy');
|
||||||
|
}
|
||||||
|
|
||||||
// Send to requester as well if this request was made on behalf of another user who's not a DPO,
|
|
||||||
// and has the capability to make data requests for the user (e.g. Parent).
|
|
||||||
if (!api::is_site_dpo($request->requestedby) && $foruser->id != $request->requestedby) {
|
|
||||||
// Ensure the requester has the capability to make data requests for this user.
|
// Ensure the requester has the capability to make data requests for this user.
|
||||||
if (api::can_create_data_request_for_user($request->userid, $request->requestedby)) {
|
if ($sendtorequester) {
|
||||||
$requestedby = core_user::get_user($request->requestedby);
|
$requestedby = core_user::get_user($request->requestedby);
|
||||||
$message->userto = $requestedby;
|
$message->userto = $requestedby;
|
||||||
$messagetextdata['username'] = fullname($requestedby);
|
$messagetextdata['username'] = fullname($requestedby);
|
||||||
|
|
|
@ -49,4 +49,22 @@ $capabilities = [
|
||||||
'contextlevel' => CONTEXT_USER,
|
'contextlevel' => CONTEXT_USER,
|
||||||
'archetypes' => []
|
'archetypes' => []
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// Capability for users to download the results of their own data request.
|
||||||
|
'tool/dataprivacy:downloadownrequest' => [
|
||||||
|
'riskbitmask' => 0,
|
||||||
|
'captype' => 'read',
|
||||||
|
'contextlevel' => CONTEXT_USER,
|
||||||
|
'archetypes' => [
|
||||||
|
'user' => CAP_ALLOW
|
||||||
|
]
|
||||||
|
],
|
||||||
|
|
||||||
|
// Capability for administrators to download other people's data requests.
|
||||||
|
'tool/dataprivacy:downloadallrequests' => [
|
||||||
|
'riskbitmask' => RISK_PERSONAL,
|
||||||
|
'captype' => 'read',
|
||||||
|
'contextlevel' => CONTEXT_USER,
|
||||||
|
'archetypes' => []
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -66,6 +66,8 @@ $string['datadeletionpagehelp'] = 'Data for which the retention period has expir
|
||||||
$string['dataprivacy:makedatarequestsforchildren'] = 'Make data requests for minors';
|
$string['dataprivacy:makedatarequestsforchildren'] = 'Make data requests for minors';
|
||||||
$string['dataprivacy:managedatarequests'] = 'Manage data requests';
|
$string['dataprivacy:managedatarequests'] = 'Manage data requests';
|
||||||
$string['dataprivacy:managedataregistry'] = 'Manage data registry';
|
$string['dataprivacy:managedataregistry'] = 'Manage data registry';
|
||||||
|
$string['dataprivacy:downloadownrequest'] = 'Download your own exported data';
|
||||||
|
$string['dataprivacy:downloadallrequests'] = 'Download exported data for everyone';
|
||||||
$string['dataregistry'] = 'Data registry';
|
$string['dataregistry'] = 'Data registry';
|
||||||
$string['dataregistryinfo'] = 'The data registry enables categories (types of data) and purposes (the reasons for processing data) to be set for all content on the site - from users and courses down to activities and blocks. For each purpose, a retention period may be set. When a retention period has expired, the data is flagged and listed for deletion, awaiting admin confirmation.';
|
$string['dataregistryinfo'] = 'The data registry enables categories (types of data) and purposes (the reasons for processing data) to be set for all content on the site - from users and courses down to activities and blocks. For each purpose, a retention period may be set. When a retention period has expired, the data is flagged and listed for deletion, awaiting admin confirmation.';
|
||||||
$string['datarequestcreatedforuser'] = 'Data request created for {$a}';
|
$string['datarequestcreatedforuser'] = 'Data request created for {$a}';
|
||||||
|
|
|
@ -185,27 +185,19 @@ function tool_dataprivacy_output_fragment_contextlevel_form($args) {
|
||||||
* @return bool Returns false if we don't find a file.
|
* @return bool Returns false if we don't find a file.
|
||||||
*/
|
*/
|
||||||
function tool_dataprivacy_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
|
function tool_dataprivacy_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
|
||||||
global $USER;
|
|
||||||
|
|
||||||
if ($context->contextlevel == CONTEXT_USER) {
|
if ($context->contextlevel == CONTEXT_USER) {
|
||||||
// Make sure the user is logged in.
|
// Make sure the user is logged in.
|
||||||
require_login(null, false);
|
require_login(null, false);
|
||||||
|
|
||||||
// Validate the user downloading this archive.
|
|
||||||
$usercontext = context_user::instance($USER->id);
|
|
||||||
// The user downloading this is not the user the archive has been prepared for. Check if it's the requester (e.g. parent).
|
|
||||||
if ($usercontext->instanceid !== $context->instanceid) {
|
|
||||||
// Get the data request ID. This should be the first element of the $args array.
|
// Get the data request ID. This should be the first element of the $args array.
|
||||||
$itemid = $args[0];
|
$itemid = $args[0];
|
||||||
// Fetch the data request object. An invalid ID will throw an exception.
|
// Fetch the data request object. An invalid ID will throw an exception.
|
||||||
$datarequest = new \tool_dataprivacy\data_request($itemid);
|
$datarequest = new \tool_dataprivacy\data_request($itemid);
|
||||||
|
|
||||||
// Check if the user is the requester and has the capability to make data requests for the target user.
|
// Check if user is allowed to download it.
|
||||||
$candownloadforuser = has_capability('tool/dataprivacy:makedatarequestsforchildren', $context);
|
if (!\tool_dataprivacy\api::can_download_data_request_for_user($context->instanceid, $datarequest->get('requestedby'))) {
|
||||||
if ($USER->id != $datarequest->get('requestedby') || !$candownloadforuser) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// All good. Serve the exported data.
|
// All good. Serve the exported data.
|
||||||
$fs = get_file_storage();
|
$fs = get_file_storage();
|
||||||
|
|
|
@ -276,6 +276,57 @@ class tool_dataprivacy_api_testcase extends advanced_testcase {
|
||||||
$this->assertFalse(api::can_manage_data_requests($nondpoincapable->id));
|
$this->assertFalse(api::can_manage_data_requests($nondpoincapable->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for api::can_download_data_request_for_user()
|
||||||
|
*/
|
||||||
|
public function test_can_download_data_request_for_user() {
|
||||||
|
$generator = $this->getDataGenerator();
|
||||||
|
|
||||||
|
// Three victims.
|
||||||
|
$victim1 = $generator->create_user();
|
||||||
|
$victim2 = $generator->create_user();
|
||||||
|
$victim3 = $generator->create_user();
|
||||||
|
|
||||||
|
// Assign a user as victim 1's parent.
|
||||||
|
$systemcontext = \context_system::instance();
|
||||||
|
$parentrole = $generator->create_role();
|
||||||
|
assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext);
|
||||||
|
$parent = $generator->create_user();
|
||||||
|
role_assign($parentrole, $parent->id, \context_user::instance($victim1->id));
|
||||||
|
|
||||||
|
// Assign another user as data access wonder woman.
|
||||||
|
$wonderrole = $generator->create_role();
|
||||||
|
assign_capability('tool/dataprivacy:downloadallrequests', CAP_ALLOW, $wonderrole, $systemcontext);
|
||||||
|
$staff = $generator->create_user();
|
||||||
|
role_assign($wonderrole, $staff->id, $systemcontext);
|
||||||
|
|
||||||
|
// Finally, victim 3 has been naughty; stop them accessing their own data.
|
||||||
|
$naughtyrole = $generator->create_role();
|
||||||
|
assign_capability('tool/dataprivacy:downloadownrequest', CAP_PROHIBIT, $naughtyrole, $systemcontext);
|
||||||
|
role_assign($naughtyrole, $victim3->id, $systemcontext);
|
||||||
|
|
||||||
|
// Victims 1 and 2 can access their own data, regardless of who requested it.
|
||||||
|
$this->assertTrue(api::can_download_data_request_for_user($victim1->id, $victim1->id, $victim1->id));
|
||||||
|
$this->assertTrue(api::can_download_data_request_for_user($victim2->id, $staff->id, $victim2->id));
|
||||||
|
|
||||||
|
// Victim 3 cannot access his own data.
|
||||||
|
$this->assertFalse(api::can_download_data_request_for_user($victim3->id, $victim3->id, $victim3->id));
|
||||||
|
|
||||||
|
// Victims 1 and 2 cannot access another victim's data.
|
||||||
|
$this->assertFalse(api::can_download_data_request_for_user($victim2->id, $victim1->id, $victim1->id));
|
||||||
|
$this->assertFalse(api::can_download_data_request_for_user($victim1->id, $staff->id, $victim2->id));
|
||||||
|
|
||||||
|
// Staff can access everyone's data.
|
||||||
|
$this->assertTrue(api::can_download_data_request_for_user($victim1->id, $victim1->id, $staff->id));
|
||||||
|
$this->assertTrue(api::can_download_data_request_for_user($victim2->id, $staff->id, $staff->id));
|
||||||
|
$this->assertTrue(api::can_download_data_request_for_user($victim3->id, $staff->id, $staff->id));
|
||||||
|
|
||||||
|
// Parent can access victim 1's data only if they requested it.
|
||||||
|
$this->assertTrue(api::can_download_data_request_for_user($victim1->id, $parent->id, $parent->id));
|
||||||
|
$this->assertFalse(api::can_download_data_request_for_user($victim1->id, $staff->id, $parent->id));
|
||||||
|
$this->assertFalse(api::can_download_data_request_for_user($victim2->id, $parent->id, $parent->id));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for api::create_data_request()
|
* Test for api::create_data_request()
|
||||||
*/
|
*/
|
||||||
|
|
107
admin/tool/dataprivacy/tests/behat/dataexport.feature
Normal file
107
admin/tool/dataprivacy/tests/behat/dataexport.feature
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
@tool @tool_dataprivacy
|
||||||
|
Feature: Data export from the privacy API
|
||||||
|
In order to export data for users and meet legal requirements
|
||||||
|
As an admin, user, or parent
|
||||||
|
I need to be able to export data for a user
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the following "users" exist:
|
||||||
|
| username | firstname | lastname |
|
||||||
|
| victim | Victim User | 1 |
|
||||||
|
| parent | Long-suffering | Parent |
|
||||||
|
And the following "roles" exist:
|
||||||
|
| shortname | name | archetype |
|
||||||
|
| tired | Tired | |
|
||||||
|
And the following "permission overrides" exist:
|
||||||
|
| capability | permission | role | contextlevel | reference |
|
||||||
|
| tool/dataprivacy:makedatarequestsforchildren | Allow | tired | System | |
|
||||||
|
And the following "role assigns" exist:
|
||||||
|
| user | role | contextlevel | reference |
|
||||||
|
| parent | tired | User | victim |
|
||||||
|
And the following config values are set as admin:
|
||||||
|
| contactdataprotectionofficer | 1 | tool_dataprivacy |
|
||||||
|
|
||||||
|
@javascript
|
||||||
|
Scenario: As admin, export data for a user and download it
|
||||||
|
Given I log in as "admin"
|
||||||
|
And I navigate to "Users > Privacy and policies > Data requests" in site administration
|
||||||
|
And I follow "New request"
|
||||||
|
And I set the field "Requesting for" to "Victim User 1"
|
||||||
|
And I press "Save changes"
|
||||||
|
Then I should see "Victim User 1"
|
||||||
|
And I should see "Pending" in the "Victim User 1" "table_row"
|
||||||
|
And I run all adhoc tasks
|
||||||
|
And I reload the page
|
||||||
|
And I should see "Awaiting approval" in the "Victim User 1" "table_row"
|
||||||
|
And I follow "Actions"
|
||||||
|
And I follow "Approve request"
|
||||||
|
And I press "Approve request"
|
||||||
|
And I should see "Approved" in the "Victim User 1" "table_row"
|
||||||
|
And I run all adhoc tasks
|
||||||
|
And I reload the page
|
||||||
|
And I should see "Complete" in the "Victim User 1" "table_row"
|
||||||
|
And I follow "Actions"
|
||||||
|
And following "Download" should download between "1" and "100000" bytes
|
||||||
|
|
||||||
|
@javascript
|
||||||
|
Scenario: As a student, request data export and then download it when approved
|
||||||
|
Given I log in as "victim"
|
||||||
|
And I follow "Profile" in the user menu
|
||||||
|
And I follow "Data requests"
|
||||||
|
And I follow "New request"
|
||||||
|
And I press "Save changes"
|
||||||
|
Then I should see "Export all of my personal data"
|
||||||
|
And I should see "Pending" in the "Export all of my personal data" "table_row"
|
||||||
|
And I run all adhoc tasks
|
||||||
|
And I reload the page
|
||||||
|
And I should see "Awaiting approval" in the "Export all of my personal data" "table_row"
|
||||||
|
|
||||||
|
And I log out
|
||||||
|
And I log in as "admin"
|
||||||
|
And I navigate to "Users > Privacy and policies > Data requests" in site administration
|
||||||
|
And I follow "Actions"
|
||||||
|
And I follow "Approve request"
|
||||||
|
And I press "Approve request"
|
||||||
|
|
||||||
|
And I log out
|
||||||
|
And I log in as "victim"
|
||||||
|
And I follow "Profile" in the user menu
|
||||||
|
And I follow "Data requests"
|
||||||
|
And I should see "Approved" in the "Export all of my personal data" "table_row"
|
||||||
|
And I run all adhoc tasks
|
||||||
|
And I reload the page
|
||||||
|
And I should see "Complete" in the "Export all of my personal data" "table_row"
|
||||||
|
And I follow "Actions"
|
||||||
|
And following "Download" should download between "1" and "100000" bytes
|
||||||
|
|
||||||
|
@javascript
|
||||||
|
Scenario: As a parent, request data export for my child because I don't trust the little blighter
|
||||||
|
Given I log in as "parent"
|
||||||
|
And I follow "Profile" in the user menu
|
||||||
|
And I follow "Data requests"
|
||||||
|
And I follow "New request"
|
||||||
|
And I set the field "Requesting for" to "Victim User 1"
|
||||||
|
And I press "Save changes"
|
||||||
|
Then I should see "Victim User 1"
|
||||||
|
And I should see "Pending" in the "Victim User 1" "table_row"
|
||||||
|
And I run all adhoc tasks
|
||||||
|
And I reload the page
|
||||||
|
And I should see "Awaiting approval" in the "Victim User 1" "table_row"
|
||||||
|
|
||||||
|
And I log out
|
||||||
|
And I log in as "admin"
|
||||||
|
And I navigate to "Users > Privacy and policies > Data requests" in site administration
|
||||||
|
And I follow "Actions"
|
||||||
|
And I follow "Approve request"
|
||||||
|
And I press "Approve request"
|
||||||
|
|
||||||
|
And I log out
|
||||||
|
And I log in as "parent"
|
||||||
|
And I follow "Profile" in the user menu
|
||||||
|
And I follow "Data requests"
|
||||||
|
And I should see "Approved" in the "Victim User 1" "table_row"
|
||||||
|
And I run all adhoc tasks
|
||||||
|
And I reload the page
|
||||||
|
And I should see "Complete" in the "Victim User 1" "table_row"
|
||||||
|
And I follow "Actions"
|
||||||
|
And following "Download" should download between "1" and "100000" bytes
|
|
@ -24,6 +24,6 @@
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die;
|
defined('MOODLE_INTERNAL') || die;
|
||||||
|
|
||||||
$plugin->version = 2018051402;
|
$plugin->version = 2018051403;
|
||||||
$plugin->requires = 2018050800; // Moodle 3.5dev (Build 2018031600) and upwards.
|
$plugin->requires = 2018050800; // Moodle 3.5dev (Build 2018031600) and upwards.
|
||||||
$plugin->component = 'tool_dataprivacy';
|
$plugin->component = 'tool_dataprivacy';
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue