░▒▓████████████████████████████████▓▒░ ░▒▓█ ▓▒░ ░▒▓█ ~ S W A M P ~ ▓▒░ ░▒▓█ ▓▒░ ░▒▓████████████████████████████████▓▒░
pplmvsvm
LOCATION:
/var/www/moodle/public/admin/tool/dataprivacy/tests/external
☗ ROOT
↻ REFRESH
✎ CARVE FLESH
EDITING: external_test.php
<?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. namespace tool_dataprivacy\external; use core_external\external_api; use tool_dataprivacy\api; use tool_dataprivacy\data_request; use tool_dataprivacy\context_instance; use tool_dataprivacy\external; /** * External testcase. * * @package tool_dataprivacy * @copyright 2018 Jun Pataleta * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class external_test extends \core_external\tests\externallib_testcase { /** * Test for external::approve_data_request() with the user not logged in. */ public function test_approve_data_request_not_logged_in(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; // Test data request creation. $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Log out the user and set force login to true. $this->setUser(); $this->expectException(\require_login_exception::class); external::approve_data_request($datarequest->get('id')); } /** * Test for external::approve_data_request() with the user not having a DPO role. */ public function test_approve_data_request_not_dpo(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; // Test data request creation. $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Login as the requester. $this->setUser($requester); $this->expectException(\required_capability_exception::class); external::approve_data_request($datarequest->get('id')); } /** * Test for external::approve_data_request() for request that's not ready for approval */ public function test_approve_data_request_not_waiting_for_approval(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; // Test data request creation. $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); $datarequest->set('status', api::DATAREQUEST_STATUS_CANCELLED)->save(); // Admin as DPO. (The default when no one's assigned as a DPO in the site). $this->setAdminUser(); $this->expectException(\moodle_exception::class); external::approve_data_request($datarequest->get('id')); } /** * Test for external::approve_data_request() */ public function test_approve_data_request(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; // Test data request creation. $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Admin as DPO. (The default when no one's assigned as a DPO in the site). $this->setAdminUser(); api::update_request_status($datarequest->get('id'), api::DATAREQUEST_STATUS_AWAITING_APPROVAL); $result = external::approve_data_request($datarequest->get('id')); $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result); $this->assertTrue($return->result); $this->assertEmpty($return->warnings); } /** * Test for external::approve_data_request() for a non-existent request ID. */ public function test_approve_data_request_non_existent(): void { $this->resetAfterTest(); // Admin as DPO. (The default when no one's assigned as a DPO in the site). $this->setAdminUser(); $result = external::approve_data_request(1); $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result); $this->assertFalse($return->result); $this->assertCount(1, $return->warnings); $warning = reset($return->warnings); $this->assertEquals('errorrequestnotfound', $warning['warningcode']); } /** * Test for external::cancel_data_request() of another user. */ public function test_cancel_data_request_other_user(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $otheruser = $generator->create_user(); $comment = 'sample comment'; // Test data request creation. $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Login as other user. $this->setUser($otheruser); $result = external::cancel_data_request($datarequest->get('id')); $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result); $this->assertFalse($return->result); $this->assertCount(1, $return->warnings); $warning = reset($return->warnings); $this->assertEquals('errorrequestnotfound', $warning['warningcode']); } /** * Test cancellation of a request where you are the requester of another user's data. */ public function test_cancel_data_request_other_user_as_requester(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $otheruser = $generator->create_user(); $comment = 'sample comment'; // Assign requester as otheruser'sparent. $systemcontext = \context_system::instance(); $parentrole = $generator->create_role(); assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext); role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id)); // Test data request creation. $this->setUser($requester); $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment); $result = external::cancel_data_request($datarequest->get('id')); $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result); $this->assertTrue($return->result); $this->assertEmpty($return->warnings); } /** * Test cancellation of a request where you are the requester of another user's data. */ public function test_cancel_data_request_requester_lost_permissions(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $otheruser = $generator->create_user(); $comment = 'sample comment'; // Assign requester as otheruser'sparent. $systemcontext = \context_system::instance(); $parentrole = $generator->create_role(); assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext); role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id)); $this->setUser($requester); $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Unassign the role. role_unassign($parentrole, $requester->id, \context_user::instance($otheruser->id)->id); // This user can no longer make the request. $this->expectException(\required_capability_exception::class); $result = external::cancel_data_request($datarequest->get('id')); } /** * Test cancellation of a request where you are the requester of another user's data. */ public function test_cancel_data_request_other_user_as_child(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $otheruser = $generator->create_user(); $comment = 'sample comment'; // Assign requester as otheruser'sparent. $systemcontext = \context_system::instance(); $parentrole = $generator->create_role(); assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $parentrole, $systemcontext); role_assign($parentrole, $requester->id, \context_user::instance($otheruser->id)); // Test data request creation. $this->setUser($otheruser); $datarequest = api::create_data_request($otheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment); $result = external::cancel_data_request($datarequest->get('id')); $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result); $this->assertTrue($return->result); $this->assertEmpty($return->warnings); } /** * Test for external::cancel_data_request() */ public function test_cancel_data_request(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; // Test data request creation. $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Test cancellation. $this->setUser($requester); $result = external::cancel_data_request($datarequest->get('id')); $return = (object) external_api::clean_returnvalue(external::approve_data_request_returns(), $result); $this->assertTrue($return->result); $this->assertEmpty($return->warnings); } /** * Test contact DPO. */ public function test_contact_dpo(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $user = $generator->create_user(); $this->setUser($user); $message = 'Hello world!'; $result = external::contact_dpo($message); $return = (object) external_api::clean_returnvalue(external::contact_dpo_returns(), $result); $this->assertTrue($return->result); $this->assertEmpty($return->warnings); } /** * Test contact DPO with message containing invalid input. */ public function test_contact_dpo_with_nasty_input(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $user = $generator->create_user(); $this->setUser($user); $this->expectException('invalid_parameter_exception'); external::contact_dpo('de<>\\..scription'); } /** * Test for external::deny_data_request() with the user not logged in. */ public function test_deny_data_request_not_logged_in(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; // Test data request creation. $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Log out. $this->setUser(); $this->expectException(\require_login_exception::class); external::deny_data_request($datarequest->get('id')); } /** * Test for external::deny_data_request() with the user not having a DPO role. */ public function test_deny_data_request_not_dpo(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Login as the requester. $this->setUser($requester); $this->expectException(\required_capability_exception::class); external::deny_data_request($datarequest->get('id')); } /** * Test for external::deny_data_request() for request that's not ready for approval */ public function test_deny_data_request_not_waiting_for_approval(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); $datarequest->set('status', api::DATAREQUEST_STATUS_CANCELLED)->save(); // Admin as DPO. (The default when no one's assigned as a DPO in the site). $this->setAdminUser(); $this->expectException(\moodle_exception::class); external::deny_data_request($datarequest->get('id')); } /** * Test for external::deny_data_request() */ public function test_deny_data_request(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Admin as DPO. (The default when no one's assigned as a DPO in the site). $this->setAdminUser(); api::update_request_status($datarequest->get('id'), api::DATAREQUEST_STATUS_AWAITING_APPROVAL); $result = external::approve_data_request($datarequest->get('id')); $return = (object) external_api::clean_returnvalue(external::deny_data_request_returns(), $result); $this->assertTrue($return->result); $this->assertEmpty($return->warnings); } /** * Test for external::deny_data_request() for a non-existent request ID. */ public function test_deny_data_request_non_existent(): void { $this->resetAfterTest(); // Admin as DPO. (The default when no one's assigned as a DPO in the site). $this->setAdminUser(); $result = external::deny_data_request(1); $return = (object) external_api::clean_returnvalue(external::deny_data_request_returns(), $result); $this->assertFalse($return->result); $this->assertCount(1, $return->warnings); $warning = reset($return->warnings); $this->assertEquals('errorrequestnotfound', $warning['warningcode']); } /** * Test for external::get_data_request() with the user not logged in. */ public function test_get_data_request_not_logged_in(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); $this->setUser(); $this->expectException(\require_login_exception::class); external::get_data_request($datarequest->get('id')); } /** * Test for external::get_data_request() with the user not having a DPO role. */ public function test_get_data_request_not_dpo(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $otheruser = $generator->create_user(); $comment = 'sample comment'; $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Login as the otheruser. $this->setUser($otheruser); $this->expectException(\required_capability_exception::class); external::get_data_request($datarequest->get('id')); } /** * Test for external::get_data_request() */ public function test_get_data_request(): void { $this->resetAfterTest(); $generator = new \testing_data_generator(); $requester = $generator->create_user(); $comment = 'sample comment'; $this->setUser($requester); $datarequest = api::create_data_request($requester->id, api::DATAREQUEST_TYPE_EXPORT, $comment); // Admin as DPO. (The default when no one's assigned as a DPO in the site). $this->setAdminUser(); $result = external::get_data_request($datarequest->get('id')); $return = (object) external_api::clean_returnvalue(external::get_data_request_returns(), $result); $this->assertEquals(api::DATAREQUEST_TYPE_EXPORT, $return->result['type']); $this->assertEquals('sample comment', $return->result['comments']); $this->assertEquals($requester->id, $return->result['userid']); $this->assertEquals($requester->id, $return->result['requestedby']); $this->assertEmpty($return->warnings); } /** * Test for external::get_data_request() for a non-existent request ID. */ public function test_get_data_request_non_existent(): void { $this->resetAfterTest(); // Admin as DPO. (The default when no one's assigned as a DPO in the site). $this->setAdminUser(); $this->expectException(\dml_missing_record_exception::class); external::get_data_request(1); } /** * Test for \tool_dataprivacy\external::set_context_defaults() * when called by a user that doesn't have the manage registry capability. */ public function test_set_context_defaults_no_capability(): void { $this->resetAfterTest(); $generator = $this->getDataGenerator(); $user = $generator->create_user(); $this->setUser($user); $this->expectException(\required_capability_exception::class); external::set_context_defaults(CONTEXT_COURSECAT, context_instance::INHERIT, context_instance::INHERIT, '', false); } /** * Test for \tool_dataprivacy\external::set_context_defaults(). * * We're just checking the module context level here to test the WS function. * More testing is done in \tool_dataprivacy_api_testcase::test_set_context_defaults(). * * @dataProvider get_options_provider * @param bool $modulelevel Whether defaults are to be applied on the module context level or for an activity only. * @param bool $override Whether to override instances. */ public function test_set_context_defaults($modulelevel, $override): void { $this->resetAfterTest(); $this->setAdminUser(); $generator = $this->getDataGenerator(); // Generate course cat, course, block, assignment, forum instances. $coursecat = $generator->create_category(); $course = $generator->create_course(['category' => $coursecat->id]); $assign = $generator->create_module('assign', ['course' => $course->id]); list($course, $assigncm) = get_course_and_cm_from_instance($assign->id, 'assign'); $assigncontext = \context_module::instance($assigncm->id); // Generate purpose and category. $category1 = api::create_category((object)['name' => 'Test category 1']); $category2 = api::create_category((object)['name' => 'Test category 2']); $purpose1 = api::create_purpose((object)[ 'name' => 'Test purpose 1', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a' ]); $purpose2 = api::create_purpose((object)[ 'name' => 'Test purpose 2', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a' ]); // Set a custom purpose and ID for this assignment instance. $assignctxinstance = api::set_context_instance((object) [ 'contextid' => $assigncontext->id, 'purposeid' => $purpose1->get('id'), 'categoryid' => $category1->get('id'), ]); $modulename = $modulelevel ? 'assign' : ''; $categoryid = $category2->get('id'); $purposeid = $purpose2->get('id'); $result = external::set_context_defaults(CONTEXT_MODULE, $categoryid, $purposeid, $modulename, $override); // Extract the result. $return = external_api::clean_returnvalue(external::set_context_defaults_returns(), $result); $this->assertTrue($return['result']); // Check the assignment context instance. $instanceexists = context_instance::record_exists($assignctxinstance->get('id')); if ($override) { // The custom assign instance should have been deleted. $this->assertFalse($instanceexists); } else { // The custom assign instance should still exist. $this->assertTrue($instanceexists); } // Check the saved defaults. list($savedpurpose, $savedcategory) = \tool_dataprivacy\data_registry::get_defaults(CONTEXT_MODULE, $modulename); $this->assertEquals($categoryid, $savedcategory); $this->assertEquals($purposeid, $savedpurpose); } /** * Test for \tool_dataprivacy\external::get_category_options() * when called by a user that doesn't have the manage registry capability. */ public function test_get_category_options_no_capability(): void { $this->resetAfterTest(); $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $this->expectException(\required_capability_exception::class); external::get_category_options(true, true); } /** * Data provider for \tool_dataprivacy_external_testcase::test_XX_options(). */ public static function get_options_provider(): array { return [ [false, false], [false, true], [true, false], [true, true], ]; } /** * Test for \tool_dataprivacy\external::get_category_options(). * * @dataProvider get_options_provider * @param bool $includeinherit Whether "Inherit" would be included to the options. * @param bool $includenotset Whether "Not set" would be included to the options. */ public function test_get_category_options($includeinherit, $includenotset): void { $this->resetAfterTest(); $this->setAdminUser(); // Prepare our expected options. $expectedoptions = []; if ($includeinherit) { $expectedoptions[] = [ 'id' => context_instance::INHERIT, 'name' => get_string('inherit', 'tool_dataprivacy'), ]; } if ($includenotset) { $expectedoptions[] = [ 'id' => context_instance::NOTSET, 'name' => get_string('notset', 'tool_dataprivacy'), ]; } for ($i = 1; $i <= 3; $i++) { $category = api::create_category((object)['name' => 'Category ' . $i]); $expectedoptions[] = [ 'id' => $category->get('id'), 'name' => $category->get('name'), ]; } // Call the WS function. $result = external::get_category_options($includeinherit, $includenotset); // Extract the options. $return = (object) external_api::clean_returnvalue(external::get_category_options_returns(), $result); $options = $return->options; // Make sure everything checks out. $this->assertCount(count($expectedoptions), $options); foreach ($options as $option) { $this->assertContains($option, $expectedoptions); } } /** * Test for \tool_dataprivacy\external::get_purpose_options() * when called by a user that doesn't have the manage registry capability. */ public function test_get_purpose_options_no_capability(): void { $this->resetAfterTest(); $generator = $this->getDataGenerator(); $user = $generator->create_user(); $this->setUser($user); $this->expectException(\required_capability_exception::class); external::get_category_options(true, true); } /** * Test for \tool_dataprivacy\external::get_purpose_options(). * * @dataProvider get_options_provider * @param bool $includeinherit Whether "Inherit" would be included to the options. * @param bool $includenotset Whether "Not set" would be included to the options. */ public function test_get_purpose_options($includeinherit, $includenotset): void { $this->resetAfterTest(); $this->setAdminUser(); // Prepare our expected options. $expectedoptions = []; if ($includeinherit) { $expectedoptions[] = [ 'id' => context_instance::INHERIT, 'name' => get_string('inherit', 'tool_dataprivacy'), ]; } if ($includenotset) { $expectedoptions[] = [ 'id' => context_instance::NOTSET, 'name' => get_string('notset', 'tool_dataprivacy'), ]; } for ($i = 1; $i <= 3; $i++) { $purpose = api::create_purpose((object)[ 'name' => 'Purpose ' . $i, 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a' ]); $expectedoptions[] = [ 'id' => $purpose->get('id'), 'name' => $purpose->get('name'), ]; } // Call the WS function. $result = external::get_purpose_options($includeinherit, $includenotset); // Extract the options. $return = (object) external_api::clean_returnvalue(external::get_purpose_options_returns(), $result); $options = $return->options; // Make sure everything checks out. $this->assertCount(count($expectedoptions), $options); foreach ($options as $option) { $this->assertContains($option, $expectedoptions); } } /** * Data provider for \tool_dataprivacy_external_testcase::get_activity_options(). */ public static function get_activity_options_provider(): array { return [ [false, false, true], [false, true, true], [true, false, true], [true, true, true], [false, false, false], [false, true, false], [true, false, false], [true, true, false], ]; } /** * Test for \tool_dataprivacy\external::get_activity_options(). * * @dataProvider get_activity_options_provider * @param bool $inheritcategory Whether the category would be set to "Inherit". * @param bool $inheritpurpose Whether the purpose would be set to "Inherit". * @param bool $nodefaults Whether to fetch only activities that don't have defaults. */ public function test_get_activity_options($inheritcategory, $inheritpurpose, $nodefaults): void { $this->resetAfterTest(); $this->setAdminUser(); $category = api::create_category((object)['name' => 'Test category']); $purpose = api::create_purpose((object)[ 'name' => 'Test purpose ', 'retentionperiod' => 'PT1M', 'lawfulbases' => 'gdpr_art_6_1_a' ]); $categoryid = $category->get('id'); $purposeid = $purpose->get('id'); if ($inheritcategory) { $categoryid = context_instance::INHERIT; } if ($inheritpurpose) { $purposeid = context_instance::INHERIT; } // Set the context default for the assignment module. api::set_context_defaults(CONTEXT_MODULE, $categoryid, $purposeid, 'assign'); // Call the WS function. $result = external::get_activity_options($nodefaults); // Extract the options. $return = (object) external_api::clean_returnvalue(external::get_activity_options_returns(), $result); $options = $return->options; // Make sure the options list is not empty. $this->assertNotEmpty($options); $pluginwithdefaults = [ 'name' => 'assign', 'displayname' => get_string('pluginname', 'assign') ]; // If we don't want plugins with defaults to be listed or if both of the category and purpose are set to inherit, // the assign module should be listed. if (!$nodefaults || ($inheritcategory && $inheritpurpose)) { $this->assertContains($pluginwithdefaults, $options); } else { $this->assertNotContains($pluginwithdefaults, $options); } } /** * Test for external::bulk_approve_data_requests(). */ public function test_bulk_approve_data_requests(): void { $this->resetAfterTest(); // Create delete data requests. $requester1 = $this->getDataGenerator()->create_user(); $this->setUser($requester1->id); $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid1 = $datarequest1->get('id'); $requester2 = $this->getDataGenerator()->create_user(); $this->setUser($requester2->id); $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid2 = $datarequest2->get('id'); // Approve the requests. $this->setAdminUser(); api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); $result = external::bulk_approve_data_requests([$requestid1, $requestid2]); $return = (object) external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result); $this->assertTrue($return->result); $this->assertEmpty($return->warnings); } /** * Test for external::bulk_approve_data_requests() for a non-existent request ID. */ public function test_bulk_approve_data_requests_non_existent(): void { $this->resetAfterTest(); $this->setAdminUser(); $result = external::bulk_approve_data_requests([42]); $return = (object) external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result); $this->assertFalse($return->result); $this->assertCount(1, $return->warnings); $warning = reset($return->warnings); $this->assertEquals('errorrequestnotfound', $warning['warningcode']); $this->assertEquals(42, $warning['item']); } /** * Test for external::bulk_deny_data_requests() for a user without permission to deny requests. */ public function test_bulk_approve_data_requests_no_permission(): void { $this->resetAfterTest(); // Create delete data requests. $requester1 = $this->getDataGenerator()->create_user(); $this->setUser($requester1->id); $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid1 = $datarequest1->get('id'); $requester2 = $this->getDataGenerator()->create_user(); $this->setUser($requester2->id); $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid2 = $datarequest2->get('id'); $this->setAdminUser(); api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); // Approve the requests. $uut = $this->getDataGenerator()->create_user(); $this->setUser($uut); $this->expectException(\required_capability_exception::class); $result = external::bulk_approve_data_requests([$requestid1, $requestid2]); } /** * Test for external::bulk_deny_data_requests() for a user without permission to deny requests. */ public function test_bulk_approve_data_requests_own_request(): void { $this->resetAfterTest(); // Create delete data requests. $requester1 = $this->getDataGenerator()->create_user(); $this->setUser($requester1->id); $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid1 = $datarequest1->get('id'); $requester2 = $this->getDataGenerator()->create_user(); $this->setUser($requester2->id); $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid2 = $datarequest2->get('id'); $this->setAdminUser(); api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); // Deny the requests. $this->setUser($requester1); $this->expectException(\required_capability_exception::class); $result = external::bulk_approve_data_requests([$requestid1]); } /** * Test for external::bulk_deny_data_requests(). */ public function test_bulk_deny_data_requests(): void { $this->resetAfterTest(); // Create delete data requests. $requester1 = $this->getDataGenerator()->create_user(); $this->setUser($requester1->id); $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid1 = $datarequest1->get('id'); $requester2 = $this->getDataGenerator()->create_user(); $this->setUser($requester2->id); $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid2 = $datarequest2->get('id'); // Deny the requests. $this->setAdminUser(); api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); $result = external::bulk_deny_data_requests([$requestid1, $requestid2]); $return = (object) external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result); $this->assertTrue($return->result); $this->assertEmpty($return->warnings); } /** * Test for external::bulk_deny_data_requests() for a non-existent request ID. */ public function test_bulk_deny_data_requests_non_existent(): void { $this->resetAfterTest(); $this->setAdminUser(); $result = external::bulk_deny_data_requests([42]); $return = (object) external_api::clean_returnvalue(external::bulk_approve_data_requests_returns(), $result); $this->assertFalse($return->result); $this->assertCount(1, $return->warnings); $warning = reset($return->warnings); $this->assertEquals('errorrequestnotfound', $warning['warningcode']); $this->assertEquals(42, $warning['item']); } /** * Test for external::bulk_deny_data_requests() for a user without permission to deny requests. */ public function test_bulk_deny_data_requests_no_permission(): void { $this->resetAfterTest(); // Create delete data requests. $requester1 = $this->getDataGenerator()->create_user(); $this->setUser($requester1->id); $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid1 = $datarequest1->get('id'); $requester2 = $this->getDataGenerator()->create_user(); $this->setUser($requester2->id); $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid2 = $datarequest2->get('id'); $this->setAdminUser(); api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); // Deny the requests. $uut = $this->getDataGenerator()->create_user(); $this->setUser($uut); $this->expectException(\required_capability_exception::class); $result = external::bulk_deny_data_requests([$requestid1, $requestid2]); } /** * Test for external::bulk_deny_data_requests() for a user cannot approve their own request. */ public function test_bulk_deny_data_requests_own_request(): void { $this->resetAfterTest(); // Create delete data requests. $requester1 = $this->getDataGenerator()->create_user(); $this->setUser($requester1->id); $datarequest1 = api::create_data_request($requester1->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid1 = $datarequest1->get('id'); $requester2 = $this->getDataGenerator()->create_user(); $this->setUser($requester2->id); $datarequest2 = api::create_data_request($requester2->id, api::DATAREQUEST_TYPE_DELETE, 'Example comment'); $requestid2 = $datarequest2->get('id'); $this->setAdminUser(); api::update_request_status($requestid1, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); api::update_request_status($requestid2, api::DATAREQUEST_STATUS_AWAITING_APPROVAL); // Deny the requests. $this->setUser($requester1); $this->expectException(\required_capability_exception::class); $result = external::bulk_deny_data_requests([$requestid1]); } /** * Test for external::get_users(), case search using non-identity field without * facing any permission problem. * * @throws coding_exception * @throws dml_exception * @throws invalid_parameter_exception * @throws required_capability_exception * @throws restricted_context_exception */ public function test_get_users_using_using_non_identity(): void { $this->resetAfterTest(); $context = \context_system::instance(); $requester = $this->getDataGenerator()->create_user(); $role = $this->getDataGenerator()->create_role(); role_assign($role, $requester->id, $context); assign_capability('tool/dataprivacy:managedatarequests', CAP_ALLOW, $role, $context); $this->setUser($requester); $this->getDataGenerator()->create_user([ 'firstname' => 'First Student' ]); $student2 = $this->getDataGenerator()->create_user([ 'firstname' => 'Second Student' ]); $results = external::get_users('Second'); $this->assertCount(1, $results); $this->assertEquals((object)[ 'id' => $student2->id, 'fullname' => fullname($student2), 'extrafields' => [] ], $results[$student2->id]); } /** * Test for external::get_users(), case search using identity field but * don't have "moodle/site:viewuseridentity" permission. * * @throws coding_exception * @throws dml_exception * @throws invalid_parameter_exception * @throws required_capability_exception * @throws restricted_context_exception */ public function test_get_users_using_identity_without_permission(): void { global $CFG; $this->resetAfterTest(); $CFG->showuseridentity = 'institution'; // Create requester user and assign correct capability. $context = \context_system::instance(); $requester = $this->getDataGenerator()->create_user(); $role = $this->getDataGenerator()->create_role(); role_assign($role, $requester->id, $context); assign_capability('tool/dataprivacy:managedatarequests', CAP_ALLOW, $role, $context); $this->setUser($requester); $this->getDataGenerator()->create_user([ 'institution' => 'University1' ]); $results = external::get_users('University1'); $this->assertEmpty($results); } /** * Test for external::get_users(), case search using disabled identity field * even they have "moodle/site:viewuseridentity" permission. * * @throws coding_exception * @throws dml_exception * @throws invalid_parameter_exception * @throws required_capability_exception * @throws restricted_context_exception */ public function test_get_users_using_field_not_in_identity(): void { $this->resetAfterTest(); $context = \context_system::instance(); $requester = $this->getDataGenerator()->create_user(); $role = $this->getDataGenerator()->create_role(); role_assign($role, $requester->id, $context); assign_capability('tool/dataprivacy:managedatarequests', CAP_ALLOW, $role, $context); assign_capability('moodle/site:viewuseridentity', CAP_ALLOW, $role, $context); $this->setUser($requester); $this->getDataGenerator()->create_user([ 'institution' => 'University1' ]); $results = external::get_users('University1'); $this->assertEmpty($results); } /** * Test for external::get_users(), case search using enabled identity field * with "moodle/site:viewuseridentity" permission. * * @throws coding_exception * @throws dml_exception * @throws invalid_parameter_exception * @throws required_capability_exception * @throws restricted_context_exception */ public function test_get_users(): void { global $CFG; $this->resetAfterTest(); $CFG->showuseridentity = 'institution'; $context = \context_system::instance(); $requester = $this->getDataGenerator()->create_user(); $role = $this->getDataGenerator()->create_role(); role_assign($role, $requester->id, $context); assign_capability('tool/dataprivacy:managedatarequests', CAP_ALLOW, $role, $context); assign_capability('moodle/site:viewuseridentity', CAP_ALLOW, $role, $context); $this->setUser($requester); $student1 = $this->getDataGenerator()->create_user([ 'institution' => 'University1' ]); $this->getDataGenerator()->create_user([ 'institution' => 'University2' ]); $results = external::get_users('University1'); $this->assertCount(1, $results); $this->assertEquals((object)[ 'id' => $student1->id, 'fullname' => fullname($student1), 'extrafields' => [ 0 => (object)[ 'name' => 'institution', 'value' => 'University1' ] ] ], $results[$student1->id]); } /** * Test for external::get_access_information(). */ public function test_get_access_information(): void { $this->resetAfterTest(); $this->setAdminUser(); $result = get_access_information::execute(); $result = external_api::clean_returnvalue(get_access_information::execute_returns(), $result); $this->assertFalse($result['cancontactdpo']); // Disabled by default. // Enable contact DPO. set_config('contactdataprotectionofficer', 1, 'tool_dataprivacy'); $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $result = get_access_information::execute(); $result = external_api::clean_returnvalue(get_access_information::execute_returns(), $result); $this->assertTrue($result['cancontactdpo']); $this->assertTrue($result['cancreatedatadownloadrequest']); $this->assertTrue($result['cancreatedatadeletionrequest']); $this->assertFalse($result['canmanagedatarequests']); $this->assertFalse($result['hasongoingdatadownloadrequest']); $this->assertFalse($result['hasongoingdatadeletionrequest']); } /** * Test for external::create_data_request() */ public function test_create_data_request(): void { $this->resetAfterTest(); $systemcontext = \context_system::instance(); $user = $this->getDataGenerator()->create_user(); $requester = $this->getDataGenerator()->create_user(); $role = $this->getDataGenerator()->create_role(); assign_capability('tool/dataprivacy:makedatarequestsforchildren', CAP_ALLOW, $role, $systemcontext); role_assign($role, $requester->id, \context_user::instance($user->id)); // Enable contact DPO. set_config('contactdataprotectionofficer', 1, 'tool_dataprivacy'); // Create a data request for myself. $this->setUser($user); $comment = 'Example comment'; $result = create_data_request::execute(api::DATAREQUEST_TYPE_DELETE, $comment); $result = external_api::clean_returnvalue(create_data_request::execute_returns(), $result); $this->assertEmpty($result['warnings']); $requests = api::get_data_requests($user->id); $this->assertCount(1, $requests); $request = reset($requests); $this->assertEquals($result['datarequestid'], $request->get('id')); $this->assertEquals($user->id, $request->get('userid')); $this->assertEquals(api::DATAREQUEST_TYPE_DELETE, $request->get('type')); $this->assertEquals($comment, $request->get('comments')); // Create on behalf of other user a different type of request. $this->setUser($requester); $comment = 'Example comment'; $result = create_data_request::execute(api::DATAREQUEST_TYPE_EXPORT, $comment, $user->id); $result = external_api::clean_returnvalue(create_data_request::execute_returns(), $result); $this->assertEmpty($result['warnings']); $requests = api::get_data_requests($user->id); $this->assertCount(2, $requests); foreach ($requests as $request) { if ($request->get('type') == api::DATAREQUEST_TYPE_EXPORT) { $this->assertEquals($result['datarequestid'], $request->get('id')); $this->assertEquals($user->id, $request->get('userid')); $this->assertEquals($comment, $request->get('comments')); } else { $this->assertEquals($user->id, $request->get('userid')); $this->assertEquals(api::DATAREQUEST_TYPE_DELETE, $request->get('type')); $this->assertEquals('Example comment', $request->get('comments')); } } } /** * Test for external::create_data_request() when no dpo available. */ public function test_create_data_request_no_dpo(): void { $this->resetAfterTest(); $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $this->expectException(\moodle_exception::class); $this->expectExceptionMessage(get_string('contactdpoviaprivacypolicy', 'tool_dataprivacy')); create_data_request::execute(api::DATAREQUEST_TYPE_DELETE, 'Example comment'); } /** * Test for external::create_data_request() with missing permission. */ public function test_create_data_request_no_permission(): void { $this->resetAfterTest(); // Enable contact DPO. set_config('contactdataprotectionofficer', 1, 'tool_dataprivacy'); $user = $this->getDataGenerator()->create_user(); $anotheruser = $this->getDataGenerator()->create_user(); $this->setUser($user); $this->expectException(\required_capability_exception::class); create_data_request::execute(api::DATAREQUEST_TYPE_DELETE, 'Example comment', $anotheruser->id); } /** * Test for external::create_data_request() with invalid request type. */ public function test_create_data_request_invalid_type(): void { $this->resetAfterTest(); // Enable contact DPO. set_config('contactdataprotectionofficer', 1, 'tool_dataprivacy'); $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $this->expectException(\moodle_exception::class); $this->expectExceptionMessage(get_string('errorinvalidrequesttype', 'tool_dataprivacy')); create_data_request::execute(125, 'Example comment'); } /** * Test for external::get_data_requests(). */ public function test_get_data_requests(): void { global $DB; $this->resetAfterTest(); $user = $this->getDataGenerator()->create_user(); $anotheruser = $this->getDataGenerator()->create_user(); $this->setUser($user); // Empty results. $result = get_data_requests::execute($user->id); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertEmpty($result['warnings']); $this->assertEmpty($result['requests']); // Create data requests. $comment = 'Example comment'; $request1 = api::create_data_request($user->id, api::DATAREQUEST_TYPE_DELETE, $comment); $request2 = api::create_data_request($user->id, api::DATAREQUEST_TYPE_EXPORT, $comment); $request3 = api::create_data_request($anotheruser->id, api::DATAREQUEST_TYPE_EXPORT, $comment, data_request::DATAREQUEST_CREATION_AUTO); // Get data requests. $result = get_data_requests::execute($user->id); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertEmpty($result['warnings']); $this->assertCount(2, $result['requests']); foreach ($result['requests'] as $request) { if ($request['id'] == $request1->get('id')) { $this->assertEquals($user->id, $request['userid']); $this->assertEquals(api::DATAREQUEST_TYPE_DELETE, $request['type']); $this->assertEquals($comment, $request['comments']); } else { $this->assertEquals($user->id, $request['userid']); $this->assertEquals(api::DATAREQUEST_TYPE_EXPORT, $request['type']); $this->assertEquals($comment, $request['comments']); } $this->assertArrayNotHasKey('downloadlink', $request); // Download link only present for download ready requests. } // Filter by type. $result = get_data_requests::execute($user->id, [], [api::DATAREQUEST_TYPE_DELETE]); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertCount(1, $result['requests']); $this->assertEquals($request1->get('id'), $result['requests'][0]['id']); // Admin get all. $this->setAdminUser(); $result = get_data_requests::execute(); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertCount(3, $result['requests']); // Test limit. $result = get_data_requests::execute(0, [], [], [], '', 2, 1); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertCount(1, $result['requests']); // Test sort. $result = get_data_requests::execute(0, [], [], [], 'id DESC'); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertEquals($request1->get('id'), $result['requests'][2]['id']); $this->assertEquals($request2->get('id'), $result['requests'][1]['id']); $this->assertEquals($request3->get('id'), $result['requests'][0]['id']); // Test filter by status. api::update_request_status($request3->get('id'), api::DATAREQUEST_STATUS_DOWNLOAD_READY); $result = get_data_requests::execute(0, [api::DATAREQUEST_STATUS_DOWNLOAD_READY]); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertCount(1, $result['requests']); $this->assertEquals($request3->get('id'), $result['requests'][0]['id']); // Check download link because the download is now ready. $usercontext = \context_user::instance($anotheruser->id, IGNORE_MISSING); $downloadlink = api::get_download_link($usercontext, $result['requests'][0]['id'])->url; $this->assertEquals($downloadlink->out(false), $result['requests'][0]['downloadlink']); // Test filter by creation method. $result = get_data_requests::execute(0, [], [], [data_request::DATAREQUEST_CREATION_AUTO]); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertCount(1, $result['requests']); $this->assertEquals($request3->get('id'), $result['requests'][0]['id']); // Get data requests for another user without required permissions. $userrole = $DB->get_field('role', 'id', ['shortname' => 'user'], MUST_EXIST); assign_capability('tool/dataprivacy:downloadownrequest', CAP_PROHIBIT, $userrole, \context_user::instance($anotheruser->id)); $this->setUser($anotheruser); // Get my data request ready for download but without permissons for download it. $result = get_data_requests::execute($anotheruser->id, [api::DATAREQUEST_STATUS_DOWNLOAD_READY]); $result = external_api::clean_returnvalue(get_data_requests::execute_returns(), $result); $this->assertArrayNotHasKey('downloadlink', $result['requests'][0]); // Download link is not present. // And now try to see a different user requests. $this->expectException(\moodle_exception::class); $dponamestring = implode (', ', api::get_dpo_role_names()); $this->expectExceptionMessage(get_string('privacyofficeronly', 'tool_dataprivacy', $dponamestring)); $result = get_data_requests::execute($user->id); } /** * Test for external::get_data_requests() invalid user id. */ public function test_get_data_requests_invalid_userid(): void { $this->resetAfterTest(); $this->setAdminUser(); $this->expectException(\dml_exception::class); get_data_requests::execute(-1); } }
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 external_test.php
PHP
54 KB
2026-02-11 01:44
EDIT
📄 submit_selected_courses_form_test.php
PHP
3 KB
2026-02-11 01:44
EDIT