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