See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 402] [Versions 401 and 403]
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/>. 16 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 */ 24 25 namespace tool_dataprivacy\external; 26 27 use externallib_advanced_testcase; 28 use tool_dataprivacy\api; 29 use tool_dataprivacy\context_instance; 30 use tool_dataprivacy\external; 31 32 defined('MOODLE_INTERNAL') || die(); 33 global $CFG; 34 35 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 36 37 /** 38 * External testcase. 39 * 40 * @package tool_dataprivacy 41 * @copyright 2018 Jun Pataleta 42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 43 */ 44 class external_test extends externallib_advanced_testcase { 45 46 /** 47 * Test for external::approve_data_request() with the user not logged in. 48 */ 49 public function test_approve_data_request_not_logged_in() { 50 $this->resetAfterTest(); 51 52 $generator = new \testing_data_generator(); 53 $requester = $generator->create_user(); 54 $comment = 'sample comment'; 55 56 // Test data request creation. 57 $this->setUser($requester); 58 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 59 60 // Log out the user and set force login to true. 61 $this->setUser(); 62 63 $this->expectException(\require_login_exception::class); 64 external::approve_data_request($datarequest->get('id')); 65 } 66 67 /** 68 * Test for external::approve_data_request() with the user not having a DPO role. 69 */ 70 public function test_approve_data_request_not_dpo() { 71 $this->resetAfterTest(); 72 73 $generator = new \testing_data_generator(); 74 $requester = $generator->create_user(); 75 $comment = 'sample comment'; 76 77 // Test data request creation. 78 $this->setUser($requester); 79 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 80 81 // Login as the requester. 82 $this->setUser($requester); 83 $this->expectException(\required_capability_exception::class); 84 external::approve_data_request($datarequest->get('id')); 85 } 86 87 /** 88 * Test for external::approve_data_request() for request that's not ready for approval 89 */ 90 public function test_approve_data_request_not_waiting_for_approval() { 91 $this->resetAfterTest(); 92 93 $generator = new \testing_data_generator(); 94 $requester = $generator->create_user(); 95 $comment = 'sample comment'; 96 97 // Test data request creation. 98 $this->setUser($requester); 99 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 100 $datarequest->set('status', api::DATAREQUEST_STATUS_CANCELLED)->save(); 101 102 // Admin as DPO. (The default when no one's assigned as a DPO in the site). 103 $this->setAdminUser(); 104 $this->expectException(\moodle_exception::class); 105 external::approve_data_request($datarequest->get('id')); 106 } 107 108 /** 109 * Test for external::approve_data_request() 110 */ 111 public function test_approve_data_request() { 112 $this->resetAfterTest(); 113 114 $generator = new \testing_data_generator(); 115 $requester = $generator->create_user(); 116 $comment = 'sample comment'; 117 118 // Test data request creation. 119 $this->setUser($requester); 120 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 121 122 // Admin as DPO. (The default when no one's assigned as a DPO in the site). 123 $this->setAdminUser(); 124 api::update_request_status($datarequest->get('id'), api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 125 $result = external::approve_data_request($datarequest->get('id')); 126 $return = (object) \external_api::clean_returnvalue(external::approve_data_request_returns(), $result); 127 $this->assertTrue($return->result); 128 $this->assertEmpty($return->warnings); 129 } 130 131 /** 132 * Test for external::approve_data_request() for a non-existent request ID. 133 */ 134 public function test_approve_data_request_non_existent() { 135 $this->resetAfterTest(); 136 137 // Admin as DPO. (The default when no one's assigned as a DPO in the site). 138 $this->setAdminUser(); 139 140 $result = external::approve_data_request(1); 141 142 $return = (object) \external_api::clean_returnvalue(external::approve_data_request_returns(), $result); 143 $this->assertFalse($return->result); 144 $this->assertCount(1, $return->warnings); 145 $warning = reset($return->warnings); 146 $this->assertEquals('errorrequestnotfound', $warning['warningcode']); 147 } 148 149 /** 150 * Test for external::cancel_data_request() of another user. 151 */ 152 public function test_cancel_data_request_other_user() { 153 $this->resetAfterTest(); 154 155 $generator = new \testing_data_generator(); 156 $requester = $generator->create_user(); 157 $otheruser = $generator->create_user(); 158 $comment = 'sample comment'; 159 160 // Test data request creation. 161 $this->setUser($requester); 162 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 163 164 // Login as other user. 165 $this->setUser($otheruser); 166 167 $result = external::cancel_data_request($datarequest->get('id')); 168 $return = (object) \external_api::clean_returnvalue(external::approve_data_request_returns(), $result); 169 $this->assertFalse($return->result); 170 $this->assertCount(1, $return->warnings); 171 $warning = reset($return->warnings); 172 $this->assertEquals('errorrequestnotfound', $warning['warningcode']); 173 } 174 175 /** 176 * Test cancellation of a request where you are the requester of another user's data. 177 */ 178 public function test_cancel_data_request_other_user_as_requester() { 179 $this->resetAfterTest(); 180 181 $generator = new \testing_data_generator(); 182 $requester = $generator->create_user(); 183 $otheruser = $generator->create_user(); 184 $comment = 'sample comment'; 185 186 // Assign requester as otheruser'sparent. 187 $systemcontext = \context_system::instance(); 188 $parentrole = $generator->create_role(); 189 assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext); 190 role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id)); 191 192 // Test data request creation. 193 $this->setUser($requester); 194 $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 195 196 $result = external::cancel_data_request($datarequest->get('id')); 197 $return = (object) \external_api::clean_returnvalue(external::approve_data_request_returns(), $result); 198 $this->assertTrue($return->result); 199 $this->assertEmpty($return->warnings); 200 } 201 202 /** 203 * Test cancellation of a request where you are the requester of another user's data. 204 */ 205 public function test_cancel_data_request_requester_lost_permissions() { 206 $this->resetAfterTest(); 207 208 $generator = new \testing_data_generator(); 209 $requester = $generator->create_user(); 210 $otheruser = $generator->create_user(); 211 $comment = 'sample comment'; 212 213 // Assign requester as otheruser'sparent. 214 $systemcontext = \context_system::instance(); 215 $parentrole = $generator->create_role(); 216 assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext); 217 role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id)); 218 219 $this->setUser($requester); 220 $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 221 222 // Unassign the role. 223 role_unassign($parentrole, $requester->id, \context_user::instance($otheruser->id)->id); 224 225 // This user can no longer make the request. 226 $this->expectException(\required_capability_exception::class); 227 228 $result = external::cancel_data_request($datarequest->get('id')); 229 } 230 231 /** 232 * Test cancellation of a request where you are the requester of another user's data. 233 */ 234 public function test_cancel_data_request_other_user_as_child() { 235 $this->resetAfterTest(); 236 237 $generator = new \testing_data_generator(); 238 $requester = $generator->create_user(); 239 $otheruser = $generator->create_user(); 240 $comment = 'sample comment'; 241 242 // Assign requester as otheruser'sparent. 243 $systemcontext = \context_system::instance(); 244 $parentrole = $generator->create_role(); 245 assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext); 246 role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id)); 247 248 // Test data request creation. 249 $this->setUser($otheruser); 250 $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 251 252 $result = external::cancel_data_request($datarequest->get('id')); 253 $return = (object) \external_api::clean_returnvalue(external::approve_data_request_returns(), $result); 254 $this->assertTrue($return->result); 255 $this->assertEmpty($return->warnings); 256 } 257 258 /** 259 * Test for external::cancel_data_request() 260 */ 261 public function test_cancel_data_request() { 262 $this->resetAfterTest(); 263 264 $generator = new \testing_data_generator(); 265 $requester = $generator->create_user(); 266 $comment = 'sample comment'; 267 268 // Test data request creation. 269 $this->setUser($requester); 270 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 271 272 // Test cancellation. 273 $this->setUser($requester); 274 $result = external::cancel_data_request($datarequest->get('id')); 275 276 $return = (object) \external_api::clean_returnvalue(external::approve_data_request_returns(), $result); 277 $this->assertTrue($return->result); 278 $this->assertEmpty($return->warnings); 279 } 280 281 /** 282 * Test contact DPO. 283 */ 284 public function test_contact_dpo() { 285 $this->resetAfterTest(); 286 287 $generator = new \testing_data_generator(); 288 $user = $generator->create_user(); 289 290 $this->setUser($user); 291 $message = 'Hello world!'; 292 $result = external::contact_dpo($message); 293 $return = (object) \external_api::clean_returnvalue(external::contact_dpo_returns(), $result); 294 $this->assertTrue($return->result); 295 $this->assertEmpty($return->warnings); 296 } 297 298 /** 299 * Test contact DPO with message containing invalid input. 300 */ 301 public function test_contact_dpo_with_nasty_input() { 302 $this->resetAfterTest(); 303 304 $generator = new \testing_data_generator(); 305 $user = $generator->create_user(); 306 307 $this->setUser($user); 308 $this->expectException('invalid_parameter_exception'); 309 external::contact_dpo('de<>\\..scription'); 310 } 311 312 /** 313 * Test for external::deny_data_request() with the user not logged in. 314 */ 315 public function test_deny_data_request_not_logged_in() { 316 $this->resetAfterTest(); 317 318 $generator = new \testing_data_generator(); 319 $requester = $generator->create_user(); 320 $comment = 'sample comment'; 321 322 // Test data request creation. 323 $this->setUser($requester); 324 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 325 326 // Log out. 327 $this->setUser(); 328 $this->expectException(\require_login_exception::class); 329 external::deny_data_request($datarequest->get('id')); 330 } 331 332 /** 333 * Test for external::deny_data_request() with the user not having a DPO role. 334 */ 335 public function test_deny_data_request_not_dpo() { 336 $this->resetAfterTest(); 337 338 $generator = new \testing_data_generator(); 339 $requester = $generator->create_user(); 340 $comment = 'sample comment'; 341 342 $this->setUser($requester); 343 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 344 345 // Login as the requester. 346 $this->setUser($requester); 347 $this->expectException(\required_capability_exception::class); 348 external::deny_data_request($datarequest->get('id')); 349 } 350 351 /** 352 * Test for external::deny_data_request() for request that's not ready for approval 353 */ 354 public function test_deny_data_request_not_waiting_for_approval() { 355 $this->resetAfterTest(); 356 357 $generator = new \testing_data_generator(); 358 $requester = $generator->create_user(); 359 $comment = 'sample comment'; 360 361 $this->setUser($requester); 362 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 363 $datarequest->set('status', api::DATAREQUEST_STATUS_CANCELLED)->save(); 364 365 // Admin as DPO. (The default when no one's assigned as a DPO in the site). 366 $this->setAdminUser(); 367 $this->expectException(\moodle_exception::class); 368 external::deny_data_request($datarequest->get('id')); 369 } 370 371 /** 372 * Test for external::deny_data_request() 373 */ 374 public function test_deny_data_request() { 375 $this->resetAfterTest(); 376 377 $generator = new \testing_data_generator(); 378 $requester = $generator->create_user(); 379 $comment = 'sample comment'; 380 381 $this->setUser($requester); 382 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 383 384 // Admin as DPO. (The default when no one's assigned as a DPO in the site). 385 $this->setAdminUser(); 386 api::update_request_status($datarequest->get('id'), api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 387 $result = external::approve_data_request($datarequest->get('id')); 388 $return = (object) \external_api::clean_returnvalue(external::deny_data_request_returns(), $result); 389 $this->assertTrue($return->result); 390 $this->assertEmpty($return->warnings); 391 } 392 393 /** 394 * Test for external::deny_data_request() for a non-existent request ID. 395 */ 396 public function test_deny_data_request_non_existent() { 397 $this->resetAfterTest(); 398 399 // Admin as DPO. (The default when no one's assigned as a DPO in the site). 400 $this->setAdminUser(); 401 $result = external::deny_data_request(1); 402 403 $return = (object) \external_api::clean_returnvalue(external::deny_data_request_returns(), $result); 404 $this->assertFalse($return->result); 405 $this->assertCount(1, $return->warnings); 406 $warning = reset($return->warnings); 407 $this->assertEquals('errorrequestnotfound', $warning['warningcode']); 408 } 409 410 /** 411 * Test for external::get_data_request() with the user not logged in. 412 */ 413 public function test_get_data_request_not_logged_in() { 414 $this->resetAfterTest(); 415 416 $generator = new \testing_data_generator(); 417 $requester = $generator->create_user(); 418 $comment = 'sample comment'; 419 420 $this->setUser($requester); 421 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 422 423 $this->setUser(); 424 $this->expectException(\require_login_exception::class); 425 external::get_data_request($datarequest->get('id')); 426 } 427 428 /** 429 * Test for external::get_data_request() with the user not having a DPO role. 430 */ 431 public function test_get_data_request_not_dpo() { 432 $this->resetAfterTest(); 433 434 $generator = new \testing_data_generator(); 435 $requester = $generator->create_user(); 436 $otheruser = $generator->create_user(); 437 $comment = 'sample comment'; 438 439 $this->setUser($requester); 440 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 441 442 // Login as the otheruser. 443 $this->setUser($otheruser); 444 $this->expectException(\required_capability_exception::class); 445 external::get_data_request($datarequest->get('id')); 446 } 447 448 /** 449 * Test for external::get_data_request() 450 */ 451 public function test_get_data_request() { 452 $this->resetAfterTest(); 453 454 $generator = new \testing_data_generator(); 455 $requester = $generator->create_user(); 456 $comment = 'sample comment'; 457 458 $this->setUser($requester); 459 $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); 460 461 // Admin as DPO. (The default when no one's assigned as a DPO in the site). 462 $this->setAdminUser(); 463 $result = external::get_data_request($datarequest->get('id')); 464 465 $return = (object) \external_api::clean_returnvalue(external::get_data_request_returns(), $result); 466 $this->assertEquals(api::DATAREQUEST_TYPE_EXPORT, $return->result['type']); 467 $this->assertEquals('sample comment', $return->result['comments']); 468 $this->assertEquals($requester->id, $return->result['userid']); 469 $this->assertEquals($requester->id, $return->result['requestedby']); 470 $this->assertEmpty($return->warnings); 471 } 472 473 /** 474 * Test for external::get_data_request() for a non-existent request ID. 475 */ 476 public function test_get_data_request_non_existent() { 477 $this->resetAfterTest(); 478 479 // Admin as DPO. (The default when no one's assigned as a DPO in the site). 480 $this->setAdminUser(); 481 $this->expectException(\dml_missing_record_exception::class); 482 external::get_data_request(1); 483 } 484 485 /** 486 * Test for \tool_dataprivacy\external::set_context_defaults() 487 * when called by a user that doesn't have the manage registry capability. 488 */ 489 public function test_set_context_defaults_no_capability() { 490 $this->resetAfterTest(); 491 492 $generator = $this->getDataGenerator(); 493 $user = $generator->create_user(); 494 $this->setUser($user); 495 $this->expectException(\required_capability_exception::class); 496 external::set_context_defaults(CONTEXT_COURSECAT, context_instance::INHERIT, context_instance::INHERIT, '', false); 497 } 498 499 /** 500 * Test for \tool_dataprivacy\external::set_context_defaults(). 501 * 502 * We're just checking the module context level here to test the WS function. 503 * More testing is done in \tool_dataprivacy_api_testcase::test_set_context_defaults(). 504 * 505 * @dataProvider get_options_provider 506 * @param bool $modulelevel Whether defaults are to be applied on the module context level or for an activity only. 507 * @param bool $override Whether to override instances. 508 */ 509 public function test_set_context_defaults($modulelevel, $override) { 510 $this->resetAfterTest(); 511 512 $this->setAdminUser(); 513 $generator = $this->getDataGenerator(); 514 515 // Generate course cat, course, block, assignment, forum instances. 516 $coursecat = $generator->create_category(); 517 $course = $generator->create_course(['category' => $coursecat->id]); 518 $assign = $generator->create_module('assign', ['course' => $course->id]); 519 list($course, $assigncm) = get_course_and_cm_from_instance($assign->id, 'assign'); 520 $assigncontext = \context_module::instance($assigncm->id); 521 522 // Generate purpose and category. 523 $category1 = api::create_category((object)['name' => 'Test category 1']); 524 $category2 = api::create_category((object)['name' => 'Test category 2']); 525 $purpose1 = api::create_purpose((object)[ 526 'name' => 'Test purpose 1', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a' 527 ]); 528 $purpose2 = api::create_purpose((object)[ 529 'name' => 'Test purpose 2', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a' 530 ]); 531 532 // Set a custom purpose and ID for this assignment instance. 533 $assignctxinstance = api::set_context_instance((object) [ 534 'contextid' => $assigncontext->id, 535 'purposeid' => $purpose1->get('id'), 536 'categoryid' => $category1->get('id'), 537 ]); 538 539 $modulename = $modulelevel ? 'assign' : ''; 540 $categoryid = $category2->get('id'); 541 $purposeid = $purpose2->get('id'); 542 $result = external::set_context_defaults(CONTEXT_MODULE, $categoryid, $purposeid, $modulename, $override); 543 544 // Extract the result. 545 $return = \external_api::clean_returnvalue(external::set_context_defaults_returns(), $result); 546 $this->assertTrue($return['result']); 547 548 // Check the assignment context instance. 549 $instanceexists = context_instance::record_exists($assignctxinstance->get('id')); 550 if ($override) { 551 // The custom assign instance should have been deleted. 552 $this->assertFalse($instanceexists); 553 } else { 554 // The custom assign instance should still exist. 555 $this->assertTrue($instanceexists); 556 } 557 558 // Check the saved defaults. 559 list($savedpurpose, $savedcategory) = \tool_dataprivacy\data_registry::get_defaults(CONTEXT_MODULE, $modulename); 560 $this->assertEquals($categoryid, $savedcategory); 561 $this->assertEquals($purposeid, $savedpurpose); 562 } 563 564 /** 565 * Test for \tool_dataprivacy\external::get_category_options() 566 * when called by a user that doesn't have the manage registry capability. 567 */ 568 public function test_get_category_options_no_capability() { 569 $this->resetAfterTest(); 570 571 $user = $this->getDataGenerator()->create_user(); 572 $this->setUser($user); 573 574 $this->expectException(\required_capability_exception::class); 575 external::get_category_options(true, true); 576 } 577 578 /** 579 * Data provider for \tool_dataprivacy_external_testcase::test_XX_options(). 580 */ 581 public function get_options_provider() { 582 return [ 583 [false, false], 584 [false, true], 585 [true, false], 586 [true, true], 587 ]; 588 } 589 590 /** 591 * Test for \tool_dataprivacy\external::get_category_options(). 592 * 593 * @dataProvider get_options_provider 594 * @param bool $includeinherit Whether "Inherit" would be included to the options. 595 * @param bool $includenotset Whether "Not set" would be included to the options. 596 */ 597 public function test_get_category_options($includeinherit, $includenotset) { 598 $this->resetAfterTest(); 599 $this->setAdminUser(); 600 601 // Prepare our expected options. 602 $expectedoptions = []; 603 if ($includeinherit) { 604 $expectedoptions[] = [ 605 'id' => context_instance::INHERIT, 606 'name' => get_string('inherit', 'tool_dataprivacy'), 607 ]; 608 } 609 610 if ($includenotset) { 611 $expectedoptions[] = [ 612 'id' => context_instance::NOTSET, 613 'name' => get_string('notset', 'tool_dataprivacy'), 614 ]; 615 } 616 617 for ($i = 1; $i <= 3; $i++) { 618 $category = api::create_category((object)['name' => 'Category ' . $i]); 619 $expectedoptions[] = [ 620 'id' => $category->get('id'), 621 'name' => $category->get('name'), 622 ]; 623 } 624 625 // Call the WS function. 626 $result = external::get_category_options($includeinherit, $includenotset); 627 628 // Extract the options. 629 $return = (object) \external_api::clean_returnvalue(external::get_category_options_returns(), $result); 630 $options = $return->options; 631 632 // Make sure everything checks out. 633 $this->assertCount(count($expectedoptions), $options); 634 foreach ($options as $option) { 635 $this->assertContains($option, $expectedoptions); 636 } 637 } 638 639 /** 640 * Test for \tool_dataprivacy\external::get_purpose_options() 641 * when called by a user that doesn't have the manage registry capability. 642 */ 643 public function test_get_purpose_options_no_capability() { 644 $this->resetAfterTest(); 645 $generator = $this->getDataGenerator(); 646 $user = $generator->create_user(); 647 $this->setUser($user); 648 $this->expectException(\required_capability_exception::class); 649 external::get_category_options(true, true); 650 } 651 652 /** 653 * Test for \tool_dataprivacy\external::get_purpose_options(). 654 * 655 * @dataProvider get_options_provider 656 * @param bool $includeinherit Whether "Inherit" would be included to the options. 657 * @param bool $includenotset Whether "Not set" would be included to the options. 658 */ 659 public function test_get_purpose_options($includeinherit, $includenotset) { 660 $this->resetAfterTest(); 661 $this->setAdminUser(); 662 663 // Prepare our expected options. 664 $expectedoptions = []; 665 if ($includeinherit) { 666 $expectedoptions[] = [ 667 'id' => context_instance::INHERIT, 668 'name' => get_string('inherit', 'tool_dataprivacy'), 669 ]; 670 } 671 672 if ($includenotset) { 673 $expectedoptions[] = [ 674 'id' => context_instance::NOTSET, 675 'name' => get_string('notset', 'tool_dataprivacy'), 676 ]; 677 } 678 679 for ($i = 1; $i <= 3; $i++) { 680 $purpose = api::create_purpose((object)[ 681 'name' => 'Purpose ' . $i, 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a' 682 ]); 683 $expectedoptions[] = [ 684 'id' => $purpose->get('id'), 685 'name' => $purpose->get('name'), 686 ]; 687 } 688 689 // Call the WS function. 690 $result = external::get_purpose_options($includeinherit, $includenotset); 691 692 // Extract the options. 693 $return = (object) \external_api::clean_returnvalue(external::get_purpose_options_returns(), $result); 694 $options = $return->options; 695 696 // Make sure everything checks out. 697 $this->assertCount(count($expectedoptions), $options); 698 foreach ($options as $option) { 699 $this->assertContains($option, $expectedoptions); 700 } 701 } 702 703 /** 704 * Data provider for \tool_dataprivacy_external_testcase::get_activity_options(). 705 */ 706 public function get_activity_options_provider() { 707 return [ 708 [false, false, true], 709 [false, true, true], 710 [true, false, true], 711 [true, true, true], 712 [false, false, false], 713 [false, true, false], 714 [true, false, false], 715 [true, true, false], 716 ]; 717 } 718 719 /** 720 * Test for \tool_dataprivacy\external::get_activity_options(). 721 * 722 * @dataProvider get_activity_options_provider 723 * @param bool $inheritcategory Whether the category would be set to "Inherit". 724 * @param bool $inheritpurpose Whether the purpose would be set to "Inherit". 725 * @param bool $nodefaults Whether to fetch only activities that don't have defaults. 726 */ 727 public function test_get_activity_options($inheritcategory, $inheritpurpose, $nodefaults) { 728 $this->resetAfterTest(); 729 $this->setAdminUser(); 730 731 $category = api::create_category((object)['name' => 'Test category']); 732 $purpose = api::create_purpose((object)[ 733 'name' => 'Test purpose ', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a' 734 ]); 735 $categoryid = $category->get('id'); 736 $purposeid = $purpose->get('id'); 737 738 if ($inheritcategory) { 739 $categoryid = context_instance::INHERIT; 740 } 741 if ($inheritpurpose) { 742 $purposeid = context_instance::INHERIT; 743 } 744 745 // Set the context default for the assignment module. 746 api::set_context_defaults(CONTEXT_MODULE, $categoryid, $purposeid, 'assign'); 747 748 // Call the WS function. 749 $result = external::get_activity_options($nodefaults); 750 751 // Extract the options. 752 $return = (object) \external_api::clean_returnvalue(external::get_activity_options_returns(), $result); 753 $options = $return->options; 754 755 // Make sure the options list is not empty. 756 $this->assertNotEmpty($options); 757 758 $pluginwithdefaults = [ 759 'name' => 'assign', 760 'displayname' => get_string('pluginname', 'assign') 761 ]; 762 763 // If we don't want plugins with defaults to be listed or if both of the category and purpose are set to inherit, 764 // the assign module should be listed. 765 if (!$nodefaults || ($inheritcategory && $inheritpurpose)) { 766 $this->assertContains($pluginwithdefaults, $options); 767 } else { 768 $this->assertNotContains($pluginwithdefaults, $options); 769 } 770 } 771 772 /** 773 * Test for external::bulk_approve_data_requests(). 774 */ 775 public function test_bulk_approve_data_requests() { 776 $this->resetAfterTest(); 777 778 // Create delete data requests. 779 $requester1 = $this->getDataGenerator()->create_user(); 780 $this->setUser($requester1->id); 781 $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 782 $requestid1 = $datarequest1->get('id'); 783 784 $requester2 = $this->getDataGenerator()->create_user(); 785 $this->setUser($requester2->id); 786 $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 787 $requestid2 = $datarequest2->get('id'); 788 789 // Approve the requests. 790 $this->setAdminUser(); 791 api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 792 api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 793 $result = external::bulk_approve_data_requests([$requestid1, $requestid2]); 794 795 $return = (object) \external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result); 796 $this->assertTrue($return->result); 797 $this->assertEmpty($return->warnings); 798 } 799 800 /** 801 * Test for external::bulk_approve_data_requests() for a non-existent request ID. 802 */ 803 public function test_bulk_approve_data_requests_non_existent() { 804 $this->resetAfterTest(); 805 806 $this->setAdminUser(); 807 808 $result = external::bulk_approve_data_requests([42]); 809 810 $return = (object) \external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result); 811 $this->assertFalse($return->result); 812 $this->assertCount(1, $return->warnings); 813 $warning = reset($return->warnings); 814 $this->assertEquals('errorrequestnotfound', $warning['warningcode']); 815 $this->assertEquals(42, $warning['item']); 816 } 817 818 /** 819 * Test for external::bulk_deny_data_requests() for a user without permission to deny requests. 820 */ 821 public function test_bulk_approve_data_requests_no_permission() { 822 $this->resetAfterTest(); 823 824 // Create delete data requests. 825 $requester1 = $this->getDataGenerator()->create_user(); 826 $this->setUser($requester1->id); 827 $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 828 $requestid1 = $datarequest1->get('id'); 829 830 $requester2 = $this->getDataGenerator()->create_user(); 831 $this->setUser($requester2->id); 832 $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 833 $requestid2 = $datarequest2->get('id'); 834 835 $this->setAdminUser(); 836 api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 837 api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 838 839 // Approve the requests. 840 $uut = $this->getDataGenerator()->create_user(); 841 $this->setUser($uut); 842 843 $this->expectException(\required_capability_exception::class); 844 $result = external::bulk_approve_data_requests([$requestid1, $requestid2]); 845 } 846 847 /** 848 * Test for external::bulk_deny_data_requests() for a user without permission to deny requests. 849 */ 850 public function test_bulk_approve_data_requests_own_request() { 851 $this->resetAfterTest(); 852 853 // Create delete data requests. 854 $requester1 = $this->getDataGenerator()->create_user(); 855 $this->setUser($requester1->id); 856 $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 857 $requestid1 = $datarequest1->get('id'); 858 859 $requester2 = $this->getDataGenerator()->create_user(); 860 $this->setUser($requester2->id); 861 $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 862 $requestid2 = $datarequest2->get('id'); 863 864 $this->setAdminUser(); 865 api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 866 api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 867 868 // Deny the requests. 869 $this->setUser($requester1); 870 871 $this->expectException(\required_capability_exception::class); 872 $result = external::bulk_approve_data_requests([$requestid1]); 873 } 874 875 /** 876 * Test for external::bulk_deny_data_requests(). 877 */ 878 public function test_bulk_deny_data_requests() { 879 $this->resetAfterTest(); 880 881 // Create delete data requests. 882 $requester1 = $this->getDataGenerator()->create_user(); 883 $this->setUser($requester1->id); 884 $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 885 $requestid1 = $datarequest1->get('id'); 886 887 $requester2 = $this->getDataGenerator()->create_user(); 888 $this->setUser($requester2->id); 889 $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 890 $requestid2 = $datarequest2->get('id'); 891 892 // Deny the requests. 893 $this->setAdminUser(); 894 api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 895 api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 896 $result = external::bulk_deny_data_requests([$requestid1, $requestid2]); 897 898 $return = (object) \external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result); 899 $this->assertTrue($return->result); 900 $this->assertEmpty($return->warnings); 901 } 902 903 /** 904 * Test for external::bulk_deny_data_requests() for a non-existent request ID. 905 */ 906 public function test_bulk_deny_data_requests_non_existent() { 907 $this->resetAfterTest(); 908 909 $this->setAdminUser(); 910 $result = external::bulk_deny_data_requests([42]); 911 $return = (object) \external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result); 912 913 $this->assertFalse($return->result); 914 $this->assertCount(1, $return->warnings); 915 $warning = reset($return->warnings); 916 $this->assertEquals('errorrequestnotfound', $warning['warningcode']); 917 $this->assertEquals(42, $warning['item']); 918 } 919 920 /** 921 * Test for external::bulk_deny_data_requests() for a user without permission to deny requests. 922 */ 923 public function test_bulk_deny_data_requests_no_permission() { 924 $this->resetAfterTest(); 925 926 // Create delete data requests. 927 $requester1 = $this->getDataGenerator()->create_user(); 928 $this->setUser($requester1->id); 929 $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 930 $requestid1 = $datarequest1->get('id'); 931 932 $requester2 = $this->getDataGenerator()->create_user(); 933 $this->setUser($requester2->id); 934 $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 935 $requestid2 = $datarequest2->get('id'); 936 937 $this->setAdminUser(); 938 api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 939 api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 940 941 // Deny the requests. 942 $uut = $this->getDataGenerator()->create_user(); 943 $this->setUser($uut); 944 945 $this->expectException(\required_capability_exception::class); 946 $result = external::bulk_deny_data_requests([$requestid1, $requestid2]); 947 } 948 949 /** 950 * Test for external::bulk_deny_data_requests() for a user cannot approve their own request. 951 */ 952 public function test_bulk_deny_data_requests_own_request() { 953 $this->resetAfterTest(); 954 955 // Create delete data requests. 956 $requester1 = $this->getDataGenerator()->create_user(); 957 $this->setUser($requester1->id); 958 $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 959 $requestid1 = $datarequest1->get('id'); 960 961 $requester2 = $this->getDataGenerator()->create_user(); 962 $this->setUser($requester2->id); 963 $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); 964 $requestid2 = $datarequest2->get('id'); 965 966 $this->setAdminUser(); 967 api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 968 api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); 969 970 // Deny the requests. 971 $this->setUser($requester1); 972 973 $this->expectException(\required_capability_exception::class); 974 $result = external::bulk_deny_data_requests([$requestid1]); 975 } 976 977 /** 978 * Test for external::get_users(), case search using non-identity field without 979 * facing any permission problem. 980 * 981 * @throws coding_exception 982 * @throws dml_exception 983 * @throws invalid_parameter_exception 984 * @throws required_capability_exception 985 * @throws restricted_context_exception 986 */ 987 public function test_get_users_using_using_non_identity() { 988 $this->resetAfterTest(); 989 $context = \context_system::instance(); 990 $requester = $this->getDataGenerator()->create_user(); 991 $role = $this->getDataGenerator()->create_role(); 992 role_assign($role, $requester->id, $context); 993 assign_capability('tool/dataprivacy:managedatarequests', CAP_ALLOW, $role, $context); 994 $this->setUser($requester); 995 996 $this->getDataGenerator()->create_user([ 997 'firstname' => 'First Student' 998 ]); 999 $student2 = $this->getDataGenerator()->create_user([ 1000 'firstname' => 'Second Student' 1001 ]); 1002 1003 $results = external::get_users('Second'); 1004 $this->assertCount(1, $results); 1005 $this->assertEquals((object)[ 1006 'id' => $student2->id, 1007 'fullname' => fullname($student2), 1008 'extrafields' => [] 1009 ], $results[$student2->id]); 1010 } 1011 1012 /** 1013 * Test for external::get_users(), case search using identity field but 1014 * don't have "moodle/site:viewuseridentity" permission. 1015 * 1016 * @throws coding_exception 1017 * @throws dml_exception 1018 * @throws invalid_parameter_exception 1019 * @throws required_capability_exception 1020 * @throws restricted_context_exception 1021 */ 1022 public function test_get_users_using_identity_without_permission() { 1023 global $CFG; 1024 1025 $this->resetAfterTest(); 1026 $CFG->showuseridentity = 'institution'; 1027 1028 // Create requester user and assign correct capability. 1029 $context = \context_system::instance(); 1030 $requester = $this->getDataGenerator()->create_user(); 1031 $role = $this->getDataGenerator()->create_role(); 1032 role_assign($role, $requester->id, $context); 1033 assign_capability('tool/dataprivacy:managedatarequests', CAP_ALLOW, $role, $context); 1034 $this->setUser($requester); 1035 1036 $this->getDataGenerator()->create_user([ 1037 'institution' => 'University1' 1038 ]); 1039 1040 $results = external::get_users('University1'); 1041 $this->assertEmpty($results); 1042 } 1043 1044 /** 1045 * Test for external::get_users(), case search using disabled identity field 1046 * even they have "moodle/site:viewuseridentity" permission. 1047 * 1048 * @throws coding_exception 1049 * @throws dml_exception 1050 * @throws invalid_parameter_exception 1051 * @throws required_capability_exception 1052 * @throws restricted_context_exception 1053 */ 1054 public function test_get_users_using_field_not_in_identity() { 1055 $this->resetAfterTest(); 1056 1057 $context = \context_system::instance(); 1058 $requester = $this->getDataGenerator()->create_user(); 1059 $role = $this->getDataGenerator()->create_role(); 1060 role_assign($role, $requester->id, $context); 1061 assign_capability('tool/dataprivacy:managedatarequests', CAP_ALLOW, $role, $context); 1062 assign_capability('moodle/site:viewuseridentity', CAP_ALLOW, $role, $context); 1063 $this->setUser($requester); 1064 1065 $this->getDataGenerator()->create_user([ 1066 'institution' => 'University1' 1067 ]); 1068 1069 $results = external::get_users('University1'); 1070 $this->assertEmpty($results); 1071 } 1072 1073 /** 1074 * Test for external::get_users(), case search using enabled identity field 1075 * with "moodle/site:viewuseridentity" permission. 1076 * 1077 * @throws coding_exception 1078 * @throws dml_exception 1079 * @throws invalid_parameter_exception 1080 * @throws required_capability_exception 1081 * @throws restricted_context_exception 1082 */ 1083 public function test_get_users() { 1084 global $CFG; 1085 $this->resetAfterTest(); 1086 $CFG->showuseridentity = 'institution'; 1087 $context = \context_system::instance(); 1088 $requester = $this->getDataGenerator()->create_user(); 1089 $role = $this->getDataGenerator()->create_role(); 1090 role_assign($role, $requester->id, $context); 1091 assign_capability('tool/dataprivacy:managedatarequests', CAP_ALLOW, $role, $context); 1092 assign_capability('moodle/site:viewuseridentity', CAP_ALLOW, $role, $context); 1093 $this->setUser($requester); 1094 1095 $student1 = $this->getDataGenerator()->create_user([ 1096 'institution' => 'University1' 1097 ]); 1098 $this->getDataGenerator()->create_user([ 1099 'institution' => 'University2' 1100 ]); 1101 1102 $results = external::get_users('University1'); 1103 $this->assertCount(1, $results); 1104 $this->assertEquals((object)[ 1105 'id' => $student1->id, 1106 'fullname' => fullname($student1), 1107 'extrafields' => [ 1108 0 => (object)[ 1109 'name' => 'institution', 1110 'value' => 'University1' 1111 ] 1112 ] 1113 ], $results[$student1->id]); 1114 } 1115 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body