Merge branch 'MDL-63102-master' of git://github.com/peterRd/moodle
[moodle.git] / admin / tool / dataprivacy / tests / external_test.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * External tests.
19  *
20  * @package    tool_dataprivacy
21  * @copyright  2018 Jun Pataleta
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
26 global $CFG;
28 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
30 use tool_dataprivacy\api;
31 use tool_dataprivacy\context_instance;
32 use tool_dataprivacy\external;
34 /**
35  * External testcase.
36  *
37  * @package    tool_dataprivacy
38  * @copyright  2018 Jun Pataleta
39  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40  */
41 class tool_dataprivacy_external_testcase extends externallib_advanced_testcase {
43     /**
44      * Test for external::approve_data_request() with the user not logged in.
45      */
46     public function test_approve_data_request_not_logged_in() {
47         $this->resetAfterTest();
49         $generator = new testing_data_generator();
50         $requester = $generator->create_user();
51         $comment = 'sample comment';
53         // Test data request creation.
54         $this->setUser($requester);
55         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
57         // Log out the user and set force login to true.
58         $this->setUser();
60         $this->expectException(require_login_exception::class);
61         external::approve_data_request($datarequest->get('id'));
62     }
64     /**
65      * Test for external::approve_data_request() with the user not having a DPO role.
66      */
67     public function test_approve_data_request_not_dpo() {
68         $this->resetAfterTest();
70         $generator = new testing_data_generator();
71         $requester = $generator->create_user();
72         $comment = 'sample comment';
74         // Test data request creation.
75         $this->setUser($requester);
76         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
78         // Login as the requester.
79         $this->setUser($requester);
80         $this->expectException(required_capability_exception::class);
81         external::approve_data_request($datarequest->get('id'));
82     }
84     /**
85      * Test for external::approve_data_request() for request that's not ready for approval
86      */
87     public function test_approve_data_request_not_waiting_for_approval() {
88         $this->resetAfterTest();
90         $generator = new testing_data_generator();
91         $requester = $generator->create_user();
92         $comment = 'sample comment';
94         // Test data request creation.
95         $this->setUser($requester);
96         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
98         // Admin as DPO. (The default when no one's assigned as a DPO in the site).
99         $this->setAdminUser();
100         $this->expectException(moodle_exception::class);
101         external::approve_data_request($datarequest->get('id'));
102     }
104     /**
105      * Test for external::approve_data_request()
106      */
107     public function test_approve_data_request() {
108         $this->resetAfterTest();
110         $generator = new testing_data_generator();
111         $requester = $generator->create_user();
112         $comment = 'sample comment';
114         // Test data request creation.
115         $this->setUser($requester);
116         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
118         // Admin as DPO. (The default when no one's assigned as a DPO in the site).
119         $this->setAdminUser();
120         api::update_request_status($datarequest->get('id'), api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
121         $result = external::approve_data_request($datarequest->get('id'));
122         $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result);
123         $this->assertTrue($return->result);
124         $this->assertEmpty($return->warnings);
125     }
127     /**
128      * Test for external::approve_data_request() for a non-existent request ID.
129      */
130     public function test_approve_data_request_non_existent() {
131         $this->resetAfterTest();
133         // Admin as DPO. (The default when no one's assigned as a DPO in the site).
134         $this->setAdminUser();
136         $result = external::approve_data_request(1);
138         $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result);
139         $this->assertFalse($return->result);
140         $this->assertCount(1, $return->warnings);
141         $warning = reset($return->warnings);
142         $this->assertEquals('errorrequestnotfound', $warning['warningcode']);
143     }
145     /**
146      * Test for external::cancel_data_request() of another user.
147      */
148     public function test_cancel_data_request_other_user() {
149         $this->resetAfterTest();
151         $generator = new testing_data_generator();
152         $requester = $generator->create_user();
153         $otheruser = $generator->create_user();
154         $comment = 'sample comment';
156         // Test data request creation.
157         $this->setUser($requester);
158         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
160         // Login as other user.
161         $this->setUser($otheruser);
163         $result = external::cancel_data_request($datarequest->get('id'));
164         $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result);
165         $this->assertFalse($return->result);
166         $this->assertCount(1, $return->warnings);
167         $warning = reset($return->warnings);
168         $this->assertEquals('errorrequestnotfound', $warning['warningcode']);
169     }
171     /**
172      * Test cancellation of a request where you are the requester of another user's data.
173      */
174     public function test_cancel_data_request_other_user_as_requester() {
175         $this->resetAfterTest();
177         $generator = new testing_data_generator();
178         $requester = $generator->create_user();
179         $otheruser = $generator->create_user();
180         $comment = 'sample comment';
182         // Assign requester as otheruser'sparent.
183         $systemcontext = \context_system::instance();
184         $parentrole = $generator->create_role();
185         assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext);
186         role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id));
188         // Test data request creation.
189         $this->setUser($requester);
190         $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
192         $result = external::cancel_data_request($datarequest->get('id'));
193         $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result);
194         $this->assertTrue($return->result);
195         $this->assertEmpty($return->warnings);
196     }
198     /**
199      * Test cancellation of a request where you are the requester of another user's data.
200      */
201     public function test_cancel_data_request_requester_lost_permissions() {
202         $this->resetAfterTest();
204         $generator = new testing_data_generator();
205         $requester = $generator->create_user();
206         $otheruser = $generator->create_user();
207         $comment = 'sample comment';
209         // Assign requester as otheruser'sparent.
210         $systemcontext = \context_system::instance();
211         $parentrole = $generator->create_role();
212         assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext);
213         role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id));
215         $this->setUser($requester);
216         $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
218         // Unassign the role.
219         role_unassign($parentrole, $requester->id, \context_user::instance($otheruser->id)->id);
221         // This user can no longer make the request.
222         $this->expectException(required_capability_exception::class);
224         $result = external::cancel_data_request($datarequest->get('id'));
225     }
227     /**
228      * Test cancellation of a request where you are the requester of another user's data.
229      */
230     public function test_cancel_data_request_other_user_as_child() {
231         $this->resetAfterTest();
233         $generator = new testing_data_generator();
234         $requester = $generator->create_user();
235         $otheruser = $generator->create_user();
236         $comment = 'sample comment';
238         // Assign requester as otheruser'sparent.
239         $systemcontext = \context_system::instance();
240         $parentrole = $generator->create_role();
241         assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext);
242         role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id));
244         // Test data request creation.
245         $this->setUser($otheruser);
246         $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
248         $result = external::cancel_data_request($datarequest->get('id'));
249         $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result);
250         $this->assertTrue($return->result);
251         $this->assertEmpty($return->warnings);
252     }
254     /**
255      * Test for external::cancel_data_request()
256      */
257     public function test_cancel_data_request() {
258         $this->resetAfterTest();
260         $generator = new testing_data_generator();
261         $requester = $generator->create_user();
262         $comment = 'sample comment';
264         // Test data request creation.
265         $this->setUser($requester);
266         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
268         // Test cancellation.
269         $this->setUser($requester);
270         $result = external::cancel_data_request($datarequest->get('id'));
272         $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result);
273         $this->assertTrue($return->result);
274         $this->assertEmpty($return->warnings);
275     }
277     /**
278      * Test contact DPO.
279      */
280     public function test_contact_dpo() {
281         $this->resetAfterTest();
283         $generator = new testing_data_generator();
284         $user = $generator->create_user();
286         $this->setUser($user);
287         $message = 'Hello world!';
288         $result = external::contact_dpo($message);
289         $return = (object) external_api::clean_returnvalue(external::contact_dpo_returns(), $result);
290         $this->assertTrue($return->result);
291         $this->assertEmpty($return->warnings);
292     }
294     /**
295      * Test contact DPO with message containing invalid input.
296      */
297     public function test_contact_dpo_with_nasty_input() {
298         $this->resetAfterTest();
300         $generator = new testing_data_generator();
301         $user = $generator->create_user();
303         $this->setUser($user);
304         $this->expectException('invalid_parameter_exception');
305         external::contact_dpo('de<>\\..scription');
306     }
308     /**
309      * Test for external::deny_data_request() with the user not logged in.
310      */
311     public function test_deny_data_request_not_logged_in() {
312         $this->resetAfterTest();
314         $generator = new testing_data_generator();
315         $requester = $generator->create_user();
316         $comment = 'sample comment';
318         // Test data request creation.
319         $this->setUser($requester);
320         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
322         // Log out.
323         $this->setUser();
324         $this->expectException(require_login_exception::class);
325         external::deny_data_request($datarequest->get('id'));
326     }
328     /**
329      * Test for external::deny_data_request() with the user not having a DPO role.
330      */
331     public function test_deny_data_request_not_dpo() {
332         $this->resetAfterTest();
334         $generator = new testing_data_generator();
335         $requester = $generator->create_user();
336         $comment = 'sample comment';
338         $this->setUser($requester);
339         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
341         // Login as the requester.
342         $this->setUser($requester);
343         $this->expectException(required_capability_exception::class);
344         external::deny_data_request($datarequest->get('id'));
345     }
347     /**
348      * Test for external::deny_data_request() for request that's not ready for approval
349      */
350     public function test_deny_data_request_not_waiting_for_approval() {
351         $this->resetAfterTest();
353         $generator = new testing_data_generator();
354         $requester = $generator->create_user();
355         $comment = 'sample comment';
357         $this->setUser($requester);
358         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
360         // Admin as DPO. (The default when no one's assigned as a DPO in the site).
361         $this->setAdminUser();
362         $this->expectException(moodle_exception::class);
363         external::deny_data_request($datarequest->get('id'));
364     }
366     /**
367      * Test for external::deny_data_request()
368      */
369     public function test_deny_data_request() {
370         $this->resetAfterTest();
372         $generator = new testing_data_generator();
373         $requester = $generator->create_user();
374         $comment = 'sample comment';
376         $this->setUser($requester);
377         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
379         // Admin as DPO. (The default when no one's assigned as a DPO in the site).
380         $this->setAdminUser();
381         api::update_request_status($datarequest->get('id'), api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
382         $result = external::approve_data_request($datarequest->get('id'));
383         $return = (object) external_api::clean_returnvalue(external::deny_data_request_returns(), $result);
384         $this->assertTrue($return->result);
385         $this->assertEmpty($return->warnings);
386     }
388     /**
389      * Test for external::deny_data_request() for a non-existent request ID.
390      */
391     public function test_deny_data_request_non_existent() {
392         $this->resetAfterTest();
394         // Admin as DPO. (The default when no one's assigned as a DPO in the site).
395         $this->setAdminUser();
396         $result = external::deny_data_request(1);
398         $return = (object) external_api::clean_returnvalue(external::deny_data_request_returns(), $result);
399         $this->assertFalse($return->result);
400         $this->assertCount(1, $return->warnings);
401         $warning = reset($return->warnings);
402         $this->assertEquals('errorrequestnotfound', $warning['warningcode']);
403     }
405     /**
406      * Test for external::get_data_request() with the user not logged in.
407      */
408     public function test_get_data_request_not_logged_in() {
409         $this->resetAfterTest();
411         $generator = new testing_data_generator();
412         $requester = $generator->create_user();
413         $comment = 'sample comment';
415         $this->setUser($requester);
416         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
418         $this->setUser();
419         $this->expectException(require_login_exception::class);
420         external::get_data_request($datarequest->get('id'));
421     }
423     /**
424      * Test for external::get_data_request() with the user not having a DPO role.
425      */
426     public function test_get_data_request_not_dpo() {
427         $this->resetAfterTest();
429         $generator = new testing_data_generator();
430         $requester = $generator->create_user();
431         $otheruser = $generator->create_user();
432         $comment = 'sample comment';
434         $this->setUser($requester);
435         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
437         // Login as the otheruser.
438         $this->setUser($otheruser);
439         $this->expectException(required_capability_exception::class);
440         external::get_data_request($datarequest->get('id'));
441     }
443     /**
444      * Test for external::get_data_request()
445      */
446     public function test_get_data_request() {
447         $this->resetAfterTest();
449         $generator = new testing_data_generator();
450         $requester = $generator->create_user();
451         $comment = 'sample comment';
453         $this->setUser($requester);
454         $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment);
456         // Admin as DPO. (The default when no one's assigned as a DPO in the site).
457         $this->setAdminUser();
458         $result = external::get_data_request($datarequest->get('id'));
460         $return = (object) external_api::clean_returnvalue(external::get_data_request_returns(), $result);
461         $this->assertEquals(api::DATAREQUEST_TYPE_EXPORT, $return->result['type']);
462         $this->assertEquals('sample comment', $return->result['comments']);
463         $this->assertEquals($requester->id, $return->result['userid']);
464         $this->assertEquals($requester->id, $return->result['requestedby']);
465         $this->assertEmpty($return->warnings);
466     }
468     /**
469      * Test for external::get_data_request() for a non-existent request ID.
470      */
471     public function test_get_data_request_non_existent() {
472         $this->resetAfterTest();
474         // Admin as DPO. (The default when no one's assigned as a DPO in the site).
475         $this->setAdminUser();
476         $this->expectException(dml_missing_record_exception::class);
477         external::get_data_request(1);
478     }
480     /**
481      * Test for \tool_dataprivacy\external::set_context_defaults()
482      * when called by a user that doesn't have the manage registry capability.
483      */
484     public function test_set_context_defaults_no_capability() {
485         $this->resetAfterTest();
487         $generator = $this->getDataGenerator();
488         $user = $generator->create_user();
489         $this->setUser($user);
490         $this->expectException(required_capability_exception::class);
491         external::set_context_defaults(CONTEXT_COURSECAT, context_instance::INHERIT, context_instance::INHERIT, '', false);
492     }
494     /**
495      * Test for \tool_dataprivacy\external::set_context_defaults().
496      *
497      * We're just checking the module context level here to test the WS function.
498      * More testing is done in \tool_dataprivacy_api_testcase::test_set_context_defaults().
499      *
500      * @dataProvider get_options_provider
501      * @param bool $modulelevel Whether defaults are to be applied on the module context level or for an activity only.
502      * @param bool $override Whether to override instances.
503      */
504     public function test_set_context_defaults($modulelevel, $override) {
505         $this->resetAfterTest();
507         $this->setAdminUser();
508         $generator = $this->getDataGenerator();
510         // Generate course cat, course, block, assignment, forum instances.
511         $coursecat = $generator->create_category();
512         $course = $generator->create_course(['category' => $coursecat->id]);
513         $assign = $generator->create_module('assign', ['course' => $course->id]);
514         list($course, $assigncm) = get_course_and_cm_from_instance($assign->id, 'assign');
515         $assigncontext = context_module::instance($assigncm->id);
517         // Generate purpose and category.
518         $category1 = api::create_category((object)['name' => 'Test category 1']);
519         $category2 = api::create_category((object)['name' => 'Test category 2']);
520         $purpose1 = api::create_purpose((object)[
521             'name' => 'Test purpose 1', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a'
522         ]);
523         $purpose2 = api::create_purpose((object)[
524             'name' => 'Test purpose 2', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a'
525         ]);
527         // Set a custom purpose and ID for this assignment instance.
528         $assignctxinstance = api::set_context_instance((object) [
529             'contextid' => $assigncontext->id,
530             'purposeid' => $purpose1->get('id'),
531             'categoryid' => $category1->get('id'),
532         ]);
534         $modulename = $modulelevel ? 'assign' : '';
535         $categoryid = $category2->get('id');
536         $purposeid = $purpose2->get('id');
537         $result = external::set_context_defaults(CONTEXT_MODULE, $categoryid, $purposeid, $modulename, $override);
539         // Extract the result.
540         $return = external_api::clean_returnvalue(external::set_context_defaults_returns(), $result);
541         $this->assertTrue($return['result']);
543         // Check the assignment context instance.
544         $instanceexists = context_instance::record_exists($assignctxinstance->get('id'));
545         if ($override) {
546             // The custom assign instance should have been deleted.
547             $this->assertFalse($instanceexists);
548         } else {
549             // The custom assign instance should still exist.
550             $this->assertTrue($instanceexists);
551         }
553         // Check the saved defaults.
554         list($savedpurpose, $savedcategory) = \tool_dataprivacy\data_registry::get_defaults(CONTEXT_MODULE, $modulename);
555         $this->assertEquals($categoryid, $savedcategory);
556         $this->assertEquals($purposeid, $savedpurpose);
557     }
559     /**
560      * Test for \tool_dataprivacy\external::get_category_options()
561      * when called by a user that doesn't have the manage registry capability.
562      */
563     public function test_get_category_options_no_capability() {
564         $this->resetAfterTest();
566         $user = $this->getDataGenerator()->create_user();
567         $this->setUser($user);
569         $this->expectException(required_capability_exception::class);
570         external::get_category_options(true, true);
571     }
573     /**
574      * Data provider for \tool_dataprivacy_external_testcase::test_XX_options().
575      */
576     public function get_options_provider() {
577         return [
578             [false, false],
579             [false, true],
580             [true, false],
581             [true, true],
582         ];
583     }
585     /**
586      * Test for \tool_dataprivacy\external::get_category_options().
587      *
588      * @dataProvider get_options_provider
589      * @param bool $includeinherit Whether "Inherit" would be included to the options.
590      * @param bool $includenotset Whether "Not set" would be included to the options.
591      */
592     public function test_get_category_options($includeinherit, $includenotset) {
593         $this->resetAfterTest();
594         $this->setAdminUser();
596         // Prepare our expected options.
597         $expectedoptions = [];
598         if ($includeinherit) {
599             $expectedoptions[] = [
600                 'id' => context_instance::INHERIT,
601                 'name' => get_string('inherit', 'tool_dataprivacy'),
602             ];
603         }
605         if ($includenotset) {
606             $expectedoptions[] = [
607                 'id' => context_instance::NOTSET,
608                 'name' => get_string('notset', 'tool_dataprivacy'),
609             ];
610         }
612         for ($i = 1; $i <= 3; $i++) {
613             $category = api::create_category((object)['name' => 'Category ' . $i]);
614             $expectedoptions[] = [
615                 'id' => $category->get('id'),
616                 'name' => $category->get('name'),
617             ];
618         }
620         // Call the WS function.
621         $result = external::get_category_options($includeinherit, $includenotset);
623         // Extract the options.
624         $return = (object) external_api::clean_returnvalue(external::get_category_options_returns(), $result);
625         $options = $return->options;
627         // Make sure everything checks out.
628         $this->assertCount(count($expectedoptions), $options);
629         foreach ($options as $option) {
630             $this->assertContains($option, $expectedoptions);
631         }
632     }
634     /**
635      * Test for \tool_dataprivacy\external::get_purpose_options()
636      * when called by a user that doesn't have the manage registry capability.
637      */
638     public function test_get_purpose_options_no_capability() {
639         $this->resetAfterTest();
640         $generator = $this->getDataGenerator();
641         $user = $generator->create_user();
642         $this->setUser($user);
643         $this->expectException(required_capability_exception::class);
644         external::get_category_options(true, true);
645     }
647     /**
648      * Test for \tool_dataprivacy\external::get_purpose_options().
649      *
650      * @dataProvider get_options_provider
651      * @param bool $includeinherit Whether "Inherit" would be included to the options.
652      * @param bool $includenotset Whether "Not set" would be included to the options.
653      */
654     public function test_get_purpose_options($includeinherit, $includenotset) {
655         $this->resetAfterTest();
656         $this->setAdminUser();
658         // Prepare our expected options.
659         $expectedoptions = [];
660         if ($includeinherit) {
661             $expectedoptions[] = [
662                 'id' => context_instance::INHERIT,
663                 'name' => get_string('inherit', 'tool_dataprivacy'),
664             ];
665         }
667         if ($includenotset) {
668             $expectedoptions[] = [
669                 'id' => context_instance::NOTSET,
670                 'name' => get_string('notset', 'tool_dataprivacy'),
671             ];
672         }
674         for ($i = 1; $i <= 3; $i++) {
675             $purpose = api::create_purpose((object)[
676                 'name' => 'Purpose ' . $i, 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a'
677             ]);
678             $expectedoptions[] = [
679                 'id' => $purpose->get('id'),
680                 'name' => $purpose->get('name'),
681             ];
682         }
684         // Call the WS function.
685         $result = external::get_purpose_options($includeinherit, $includenotset);
687         // Extract the options.
688         $return = (object) external_api::clean_returnvalue(external::get_purpose_options_returns(), $result);
689         $options = $return->options;
691         // Make sure everything checks out.
692         $this->assertCount(count($expectedoptions), $options);
693         foreach ($options as $option) {
694             $this->assertContains($option, $expectedoptions);
695         }
696     }
698     /**
699      * Data provider for \tool_dataprivacy_external_testcase::get_activity_options().
700      */
701     public function get_activity_options_provider() {
702         return [
703             [false, false, true],
704             [false, true, true],
705             [true, false, true],
706             [true, true, true],
707             [false, false, false],
708             [false, true, false],
709             [true, false, false],
710             [true, true, false],
711         ];
712     }
714     /**
715      * Test for \tool_dataprivacy\external::get_activity_options().
716      *
717      * @dataProvider get_activity_options_provider
718      * @param bool $inheritcategory Whether the category would be set to "Inherit".
719      * @param bool $inheritpurpose Whether the purpose would be set to "Inherit".
720      * @param bool $nodefaults Whether to fetch only activities that don't have defaults.
721      */
722     public function test_get_activity_options($inheritcategory, $inheritpurpose, $nodefaults) {
723         $this->resetAfterTest();
724         $this->setAdminUser();
726         $category = api::create_category((object)['name' => 'Test category']);
727         $purpose = api::create_purpose((object)[
728             'name' => 'Test purpose ', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a'
729         ]);
730         $categoryid = $category->get('id');
731         $purposeid = $purpose->get('id');
733         if ($inheritcategory) {
734             $categoryid = context_instance::INHERIT;
735         }
736         if ($inheritpurpose) {
737             $purposeid = context_instance::INHERIT;
738         }
740         // Set the context default for the assignment module.
741         api::set_context_defaults(CONTEXT_MODULE, $categoryid, $purposeid, 'assign');
743         // Call the WS function.
744         $result = external::get_activity_options($nodefaults);
746         // Extract the options.
747         $return = (object) external_api::clean_returnvalue(external::get_activity_options_returns(), $result);
748         $options = $return->options;
750         // Make sure the options list is not empty.
751         $this->assertNotEmpty($options);
753         $pluginwithdefaults = [
754             'name' => 'assign',
755             'displayname' => get_string('pluginname', 'assign')
756         ];
758         // If we don't want plugins with defaults to be listed or if both of the category and purpose are set to inherit,
759         // the assign module should be listed.
760         if (!$nodefaults || ($inheritcategory && $inheritpurpose)) {
761             $this->assertContains($pluginwithdefaults, $options);
762         } else {
763             $this->assertNotContains($pluginwithdefaults, $options);
764         }
765     }
767     /**
768      * Test for external::bulk_approve_data_requests().
769      */
770     public function test_bulk_approve_data_requests() {
771         $this->resetAfterTest();
773         // Create delete data requests.
774         $requester1 = $this->getDataGenerator()->create_user();
775         $this->setUser($requester1->id);
776         $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
777         $requestid1 = $datarequest1->get('id');
779         $requester2 = $this->getDataGenerator()->create_user();
780         $this->setUser($requester2->id);
781         $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
782         $requestid2 = $datarequest2->get('id');
784         // Approve the requests.
785         $this->setAdminUser();
786         api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
787         api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
788         $result = external::bulk_approve_data_requests([$requestid1, $requestid2]);
790         $return = (object) external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result);
791         $this->assertTrue($return->result);
792         $this->assertEmpty($return->warnings);
793     }
795     /**
796      * Test for external::bulk_approve_data_requests() for a non-existent request ID.
797      */
798     public function test_bulk_approve_data_requests_non_existent() {
799         $this->resetAfterTest();
801         $this->setAdminUser();
803         $result = external::bulk_approve_data_requests([42]);
805         $return = (object) external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result);
806         $this->assertFalse($return->result);
807         $this->assertCount(1, $return->warnings);
808         $warning = reset($return->warnings);
809         $this->assertEquals('errorrequestnotfound', $warning['warningcode']);
810         $this->assertEquals(42, $warning['item']);
811     }
813     /**
814      * Test for external::bulk_deny_data_requests() for a user without permission to deny requests.
815      */
816     public function test_bulk_approve_data_requests_no_permission() {
817         $this->resetAfterTest();
819         // Create delete data requests.
820         $requester1 = $this->getDataGenerator()->create_user();
821         $this->setUser($requester1->id);
822         $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
823         $requestid1 = $datarequest1->get('id');
825         $requester2 = $this->getDataGenerator()->create_user();
826         $this->setUser($requester2->id);
827         $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
828         $requestid2 = $datarequest2->get('id');
830         $this->setAdminUser();
831         api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
832         api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
834         // Approve the requests.
835         $uut = $this->getDataGenerator()->create_user();
836         $this->setUser($uut);
838         $this->expectException(required_capability_exception::class);
839         $result = external::bulk_approve_data_requests([$requestid1, $requestid2]);
840     }
842     /**
843      * Test for external::bulk_deny_data_requests() for a user without permission to deny requests.
844      */
845     public function test_bulk_approve_data_requests_own_request() {
846         $this->resetAfterTest();
848         // Create delete data requests.
849         $requester1 = $this->getDataGenerator()->create_user();
850         $this->setUser($requester1->id);
851         $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
852         $requestid1 = $datarequest1->get('id');
854         $requester2 = $this->getDataGenerator()->create_user();
855         $this->setUser($requester2->id);
856         $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
857         $requestid2 = $datarequest2->get('id');
859         $this->setAdminUser();
860         api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
861         api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
863         // Deny the requests.
864         $this->setUser($requester1);
866         $this->expectException(required_capability_exception::class);
867         $result = external::bulk_approve_data_requests([$requestid1]);
868     }
870     /**
871      * Test for external::bulk_deny_data_requests().
872      */
873     public function test_bulk_deny_data_requests() {
874         $this->resetAfterTest();
876         // Create delete data requests.
877         $requester1 = $this->getDataGenerator()->create_user();
878         $this->setUser($requester1->id);
879         $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
880         $requestid1 = $datarequest1->get('id');
882         $requester2 = $this->getDataGenerator()->create_user();
883         $this->setUser($requester2->id);
884         $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
885         $requestid2 = $datarequest2->get('id');
887         // Deny the requests.
888         $this->setAdminUser();
889         api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
890         api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
891         $result = external::bulk_deny_data_requests([$requestid1, $requestid2]);
893         $return = (object) external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result);
894         $this->assertTrue($return->result);
895         $this->assertEmpty($return->warnings);
896     }
898     /**
899      * Test for external::bulk_deny_data_requests() for a non-existent request ID.
900      */
901     public function test_bulk_deny_data_requests_non_existent() {
902         $this->resetAfterTest();
904         $this->setAdminUser();
905         $result = external::bulk_deny_data_requests([42]);
906         $return = (object) external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result);
908         $this->assertFalse($return->result);
909         $this->assertCount(1, $return->warnings);
910         $warning = reset($return->warnings);
911         $this->assertEquals('errorrequestnotfound', $warning['warningcode']);
912         $this->assertEquals(42, $warning['item']);
913     }
915     /**
916      * Test for external::bulk_deny_data_requests() for a user without permission to deny requests.
917      */
918     public function test_bulk_deny_data_requests_no_permission() {
919         $this->resetAfterTest();
921         // Create delete data requests.
922         $requester1 = $this->getDataGenerator()->create_user();
923         $this->setUser($requester1->id);
924         $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
925         $requestid1 = $datarequest1->get('id');
927         $requester2 = $this->getDataGenerator()->create_user();
928         $this->setUser($requester2->id);
929         $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
930         $requestid2 = $datarequest2->get('id');
932         $this->setAdminUser();
933         api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
934         api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
936         // Deny the requests.
937         $uut = $this->getDataGenerator()->create_user();
938         $this->setUser($uut);
940         $this->expectException(required_capability_exception::class);
941         $result = external::bulk_deny_data_requests([$requestid1, $requestid2]);
942     }
944     /**
945      * Test for external::bulk_deny_data_requests() for a user cannot approve their own request.
946      */
947     public function test_bulk_deny_data_requests_own_request() {
948         $this->resetAfterTest();
950         // Create delete data requests.
951         $requester1 = $this->getDataGenerator()->create_user();
952         $this->setUser($requester1->id);
953         $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
954         $requestid1 = $datarequest1->get('id');
956         $requester2 = $this->getDataGenerator()->create_user();
957         $this->setUser($requester2->id);
958         $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment');
959         $requestid2 = $datarequest2->get('id');
961         $this->setAdminUser();
962         api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
963         api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL);
965         // Deny the requests.
966         $this->setUser($requester1);
968         $this->expectException(required_capability_exception::class);
969         $result = external::bulk_deny_data_requests([$requestid1]);
970     }