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 * Data provider tests. 19 * 20 * @package core_external 21 * @category test 22 * @copyright 2018 Frédéric Massart 23 * @author Frédéric Massart <fred@branchup.tech> 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 namespace core_external\privacy; 27 28 use core_external\privacy\provider; 29 use core_privacy\local\request\approved_contextlist; 30 use core_privacy\local\request\approved_userlist; 31 use core_privacy\local\request\transform; 32 use core_privacy\local\request\writer; 33 use core_privacy\tests\provider_testcase; 34 35 /** 36 * External subsytem testcase class. 37 * 38 * @package core_external 39 * @category test 40 * @copyright 2018 Frédéric Massart 41 * @author Frédéric Massart <fred@branchup.tech> 42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 43 */ 44 class provider_test extends provider_testcase { 45 public function setUp(): void { 46 $this->resetAfterTest(); 47 } 48 49 /** 50 * Test the external service get_contexts_for_userid function. 51 * 52 * @covers \core_external\privacy\provider::get_contexts_for_userid 53 */ 54 public function test_get_contexts_for_userid(): void { 55 $dg = $this->getDataGenerator(); 56 $u1 = $dg->create_user(); 57 $u2 = $dg->create_user(); 58 $u3 = $dg->create_user(); 59 $u4 = $dg->create_user(); 60 $u5 = $dg->create_user(); 61 $u1ctx = \context_user::instance($u1->id); 62 $u2ctx = \context_user::instance($u2->id); 63 $u3ctx = \context_user::instance($u3->id); 64 $u5ctx = \context_user::instance($u5->id); 65 66 $s = $this->create_service(); 67 $this->create_token(['userid' => $u1->id]); 68 $this->create_token(['userid' => $u1->id]); 69 $this->create_token(['userid' => $u2->id, 'creatorid' => $u3->id]); 70 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u5->id]); 71 72 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids(); 73 $this->assertCount(1, $contextids); 74 $this->assertTrue(in_array($u1ctx->id, $contextids)); 75 76 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids(); 77 $this->assertCount(1, $contextids); 78 $this->assertTrue(in_array($u2ctx->id, $contextids)); 79 80 $contextids = provider::get_contexts_for_userid($u3->id)->get_contextids(); 81 $this->assertCount(1, $contextids); 82 $this->assertTrue(in_array($u2ctx->id, $contextids)); 83 84 $contextids = provider::get_contexts_for_userid($u4->id)->get_contextids(); 85 $this->assertCount(0, $contextids); 86 87 $contextids = provider::get_contexts_for_userid($u5->id)->get_contextids(); 88 $this->assertCount(1, $contextids); 89 $this->assertTrue(in_array($u5ctx->id, $contextids)); 90 } 91 92 /** 93 * Test delete_data_for_user 94 * 95 * @covers \core_external\privacy\provider::delete_data_for_user 96 */ 97 public function test_delete_data_for_user(): void { 98 global $DB; 99 100 $dg = $this->getDataGenerator(); 101 $u1 = $dg->create_user(); 102 $u2 = $dg->create_user(); 103 $u1ctx = \context_user::instance($u1->id); 104 $u2ctx = \context_user::instance($u2->id); 105 106 $s = $this->create_service(); 107 $this->create_token(['userid' => $u1->id, 'creatorid' => $u2->id]); 108 $this->create_token(['userid' => $u1->id]); 109 $this->create_token(['userid' => $u2->id]); 110 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u1->id]); 111 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u2->id]); 112 113 $this->assertEquals(2, $DB->count_records('external_tokens', ['userid' => $u1->id])); 114 $this->assertEquals(1, $DB->count_records('external_tokens', ['userid' => $u2->id])); 115 $this->assertTrue($DB->record_exists('external_services_users', ['userid' => $u1->id])); 116 $this->assertTrue($DB->record_exists('external_services_users', ['userid' => $u2->id])); 117 118 // Delete in another context, nothing happens. 119 provider::delete_data_for_user(new approved_contextlist($u2, 'core_external', [$u1ctx->id])); 120 $this->assertEquals(2, $DB->count_records('external_tokens', ['userid' => $u1->id])); 121 $this->assertEquals(1, $DB->count_records('external_tokens', ['userid' => $u2->id])); 122 $this->assertTrue($DB->record_exists('external_services_users', ['userid' => $u1->id])); 123 $this->assertTrue($DB->record_exists('external_services_users', ['userid' => $u2->id])); 124 125 // Delete in my context. 126 provider::delete_data_for_user(new approved_contextlist($u2, 'core_external', [$u2ctx->id])); 127 $this->assertEquals(2, $DB->count_records('external_tokens', ['userid' => $u1->id])); 128 $this->assertEquals(0, $DB->count_records('external_tokens', ['userid' => $u2->id])); 129 $this->assertTrue($DB->record_exists('external_services_users', ['userid' => $u1->id])); 130 $this->assertFalse($DB->record_exists('external_services_users', ['userid' => $u2->id])); 131 } 132 133 /** 134 * Test delete_data_for_all_users_in_context 135 * 136 * @covers \core_external\privacy\provider::delete_data_for_all_users_in_context 137 */ 138 public function test_delete_data_for_all_users_in_context() { 139 global $DB; 140 141 $dg = $this->getDataGenerator(); 142 $u1 = $dg->create_user(); 143 $u2 = $dg->create_user(); 144 $u1ctx = \context_user::instance($u1->id); 145 $u2ctx = \context_user::instance($u2->id); 146 147 $s = $this->create_service(); 148 $this->create_token(['userid' => $u1->id, 'creatorid' => $u2->id]); 149 $this->create_token(['userid' => $u1->id]); 150 $this->create_token(['userid' => $u2->id]); 151 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u1->id]); 152 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u2->id]); 153 154 $this->assertEquals(2, $DB->count_records('external_tokens', ['userid' => $u1->id])); 155 $this->assertEquals(1, $DB->count_records('external_tokens', ['userid' => $u2->id])); 156 $this->assertTrue($DB->record_exists('external_services_users', ['userid' => $u1->id])); 157 $this->assertTrue($DB->record_exists('external_services_users', ['userid' => $u2->id])); 158 159 provider::delete_data_for_all_users_in_context($u2ctx); 160 $this->assertEquals(2, $DB->count_records('external_tokens', ['userid' => $u1->id])); 161 $this->assertEquals(0, $DB->count_records('external_tokens', ['userid' => $u2->id])); 162 $this->assertTrue($DB->record_exists('external_services_users', ['userid' => $u1->id])); 163 $this->assertFalse($DB->record_exists('external_services_users', ['userid' => $u2->id])); 164 165 provider::delete_data_for_all_users_in_context($u1ctx); 166 $this->assertEquals(0, $DB->count_records('external_tokens', ['userid' => $u1->id])); 167 $this->assertEquals(0, $DB->count_records('external_tokens', ['userid' => $u2->id])); 168 $this->assertFalse($DB->record_exists('external_services_users', ['userid' => $u1->id])); 169 $this->assertFalse($DB->record_exists('external_services_users', ['userid' => $u2->id])); 170 171 } 172 173 /** 174 * Test the export_user_data function. 175 * @covers \core_external\privacy\provider::export_user_data 176 */ 177 public function test_export_data_for_user() { 178 global $DB; 179 180 $dg = $this->getDataGenerator(); 181 $u1 = $dg->create_user(); 182 $u2 = $dg->create_user(); 183 $u1ctx = \context_user::instance($u1->id); 184 $u2ctx = \context_user::instance($u2->id); 185 186 $path = [get_string('services', 'core_external')]; 187 $yearago = time() - YEARSECS; 188 $hourago = time() - HOURSECS; 189 190 $s = $this->create_service(['name' => 'Party time!']); 191 $this->create_token(['userid' => $u1->id, 'timecreated' => $yearago]); 192 $this->create_token([ 193 'userid' => $u1->id, 194 'creatorid' => $u2->id, 195 'iprestriction' => '127.0.0.1', 196 'lastaccess' => $hourago, 197 ]); 198 $this->create_token([ 199 'userid' => $u2->id, 200 'iprestriction' => '192.168.1.0/24', 201 'lastaccess' => $yearago, 202 'externalserviceid' => $s->id, 203 ]); 204 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u2->id]); 205 206 // User 1 exporting user 2 context does not give anything. 207 writer::reset(); 208 provider::export_user_data(new approved_contextlist($u1, 'core_external', [$u2ctx->id])); 209 $data = writer::with_context($u1ctx)->get_data($path); 210 $this->assertEmpty($data); 211 $data = writer::with_context($u1ctx)->get_related_data($path, 'created_by_you'); 212 $this->assertEmpty($data); 213 $data = writer::with_context($u2ctx)->get_data($path); 214 $this->assertEmpty($data); 215 $data = writer::with_context($u2ctx)->get_related_data($path, 'created_by_you'); 216 $this->assertEmpty($data); 217 218 // User 1 exporting their context. 219 writer::reset(); 220 provider::export_user_data(new approved_contextlist($u1, 'core_external', [$u1ctx->id, $u2ctx->id])); 221 $data = writer::with_context($u1ctx)->get_data($path); 222 $this->assertFalse(isset($data->services_user)); 223 $this->assertCount(2, $data->tokens); 224 $this->assertEquals(transform::datetime($yearago), $data->tokens[0]['created_on']); 225 $this->assertEquals(null, $data->tokens[0]['ip_restriction']); 226 $this->assertEquals(transform::datetime($hourago), $data->tokens[1]['last_access']); 227 $this->assertEquals('127.0.0.1', $data->tokens[1]['ip_restriction']); 228 $data = writer::with_context($u1ctx)->get_related_data($path, 'created_by_you'); 229 $this->assertEmpty($data); 230 $data = writer::with_context($u2ctx)->get_data($path); 231 $this->assertEmpty($data); 232 $data = writer::with_context($u2ctx)->get_related_data($path, 'created_by_you'); 233 $this->assertEmpty($data); 234 235 // User 2 exporting their context. 236 writer::reset(); 237 provider::export_user_data(new approved_contextlist($u2, 'core_external', [$u1ctx->id, $u2ctx->id])); 238 $data = writer::with_context($u2ctx)->get_data($path); 239 $this->assertCount(1, $data->tokens); 240 $this->assertEquals('Party time!', $data->tokens[0]['external_service']); 241 $this->assertEquals(transform::datetime($yearago), $data->tokens[0]['last_access']); 242 $this->assertEquals('192.168.1.0/24', $data->tokens[0]['ip_restriction']); 243 $this->assertCount(1, $data->services_user); 244 $this->assertEquals('Party time!', $data->services_user[0]['external_service']); 245 $data = writer::with_context($u1ctx)->get_related_data($path, 'created_by_you'); 246 $this->assertCount(1, $data->tokens); 247 $this->assertEquals(transform::datetime($hourago), $data->tokens[0]['last_access']); 248 $this->assertEquals('127.0.0.1', $data->tokens[0]['ip_restriction']); 249 $data = writer::with_context($u1ctx)->get_data($path); 250 $this->assertEmpty($data); 251 $data = writer::with_context($u2ctx)->get_related_data($path, 'created_by_you'); 252 $this->assertEmpty($data); 253 } 254 255 /** 256 * Test that only users with a user context are fetched. 257 * 258 * @covers \core_external\privacy\provider::get_users_in_context 259 */ 260 public function test_get_users_in_context() { 261 262 $component = 'core_external'; 263 // Create user u1. 264 $u1 = $this->getDataGenerator()->create_user(); 265 $u1ctx = \context_user::instance($u1->id); 266 // Create user u2. 267 $u2 = $this->getDataGenerator()->create_user(); 268 $u2ctx = \context_user::instance($u2->id); 269 // Create user u3. 270 $u3 = $this->getDataGenerator()->create_user(); 271 $u3ctx = \context_user::instance($u3->id); 272 // Create user u4. 273 $u4 = $this->getDataGenerator()->create_user(); 274 $u4ctx = \context_user::instance($u4->id); 275 // Create user u5. 276 $u5 = $this->getDataGenerator()->create_user(); 277 $u5ctx = \context_user::instance($u5->id); 278 279 // The lists of users for each user context ($u1ctx, $u2ctx, etc.) should be empty. 280 // Related user data have not been created yet. 281 $userlist1 = new \core_privacy\local\request\userlist($u1ctx, $component); 282 provider::get_users_in_context($userlist1); 283 $this->assertCount(0, $userlist1); 284 $userlist2 = new \core_privacy\local\request\userlist($u2ctx, $component); 285 provider::get_users_in_context($userlist2); 286 $this->assertCount(0, $userlist2); 287 $userlist3 = new \core_privacy\local\request\userlist($u3ctx, $component); 288 provider::get_users_in_context($userlist3); 289 $this->assertCount(0, $userlist3); 290 $userlist4 = new \core_privacy\local\request\userlist($u4ctx, $component); 291 provider::get_users_in_context($userlist4); 292 $this->assertCount(0, $userlist4); 293 $userlist5 = new \core_privacy\local\request\userlist($u5ctx, $component); 294 provider::get_users_in_context($userlist5); 295 $this->assertCount(0, $userlist5); 296 297 // Create a service. 298 $s = $this->create_service(); 299 // Create a ws token for u1. 300 $this->create_token(['userid' => $u1->id]); 301 // Create a ws token for u2, and u3 as the creator of the token. 302 $this->create_token(['userid' => $u2->id, 'creatorid' => $u3->id]); 303 // Create a service user (u4). 304 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u4->id]); 305 306 // The list of users for userlist1 should return one user (u1). 307 provider::get_users_in_context($userlist1); 308 $this->assertCount(1, $userlist1); 309 $expected = [$u1->id]; 310 $actual = $userlist1->get_userids(); 311 $this->assertEquals($expected, $actual); 312 // The list of users for userlist2 should return one user (u2). 313 provider::get_users_in_context($userlist2); 314 $this->assertCount(1, $userlist2); 315 $expected = [$u2->id]; 316 $actual = $userlist2->get_userids(); 317 $this->assertEquals($expected, $actual); 318 // The list of users for userlist3 should return one user (u3). 319 provider::get_users_in_context($userlist3); 320 $this->assertCount(1, $userlist3); 321 $expected = [$u3->id]; 322 $actual = $userlist3->get_userids(); 323 $this->assertEquals($expected, $actual); 324 // The list of users for userlist4 should return one user (u4). 325 provider::get_users_in_context($userlist4); 326 $this->assertCount(1, $userlist4); 327 $expected = [$u4->id]; 328 $actual = $userlist4->get_userids(); 329 $this->assertEquals($expected, $actual); 330 // The list of users for userlist5 should not return any users. 331 provider::get_users_in_context($userlist5); 332 $this->assertCount(0, $userlist5); 333 334 // The list of users should only return users in the user context. 335 $systemcontext = \context_system::instance(); 336 $userlist6 = new \core_privacy\local\request\userlist($systemcontext, $component); 337 provider::get_users_in_context($userlist6); 338 $this->assertCount(0, $userlist6); 339 } 340 341 /** 342 * Test that data for users in approved userlist is deleted. 343 * 344 * @covers \core_external\privacy\provider::delete_data_for_users 345 */ 346 public function test_delete_data_for_users() { 347 348 $component = 'core_external'; 349 // Create user u1. 350 $u1 = $this->getDataGenerator()->create_user(); 351 $u1ctx = \context_user::instance($u1->id); 352 // Create user u2. 353 $u2 = $this->getDataGenerator()->create_user(); 354 $u2ctx = \context_user::instance($u2->id); 355 // Create user u3. 356 $u3 = $this->getDataGenerator()->create_user(); 357 $u3ctx = \context_user::instance($u3->id); 358 // Create user u4. 359 $u4 = $this->getDataGenerator()->create_user(); 360 $u4ctx = \context_user::instance($u4->id); 361 // Create user u5. 362 $u5 = $this->getDataGenerator()->create_user(); 363 $u5ctx = \context_user::instance($u5->id); 364 365 // Create a service. 366 $s = $this->create_service(); 367 // Create a ws token for u1. 368 $this->create_token(['userid' => $u1->id]); 369 // Create a ws token for u2, and u3 as the creator of the token. 370 $this->create_token(['userid' => $u2->id, 'creatorid' => $u3->id]); 371 // Create a service user (u4). 372 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u4->id]); 373 // Create a service user (u5). 374 $this->create_service_user(['externalserviceid' => $s->id, 'userid' => $u5->id]); 375 376 // The list of users for u1ctx should return one user (u1). 377 $userlist1 = new \core_privacy\local\request\userlist($u1ctx, $component); 378 provider::get_users_in_context($userlist1); 379 $this->assertCount(1, $userlist1); 380 // The list of users for u2ctx should return one user (u2). 381 $userlist2 = new \core_privacy\local\request\userlist($u2ctx, $component); 382 provider::get_users_in_context($userlist2); 383 $this->assertCount(1, $userlist2); 384 // The list of users for u3ctx should return one user (u3). 385 $userlist3 = new \core_privacy\local\request\userlist($u3ctx, $component); 386 provider::get_users_in_context($userlist3); 387 $this->assertCount(1, $userlist3); 388 // The list of users for u4ctx should return one user (u4). 389 $userlist4 = new \core_privacy\local\request\userlist($u4ctx, $component); 390 provider::get_users_in_context($userlist4); 391 $this->assertCount(1, $userlist4); 392 393 $approvedlist = new approved_userlist($u1ctx, $component, $userlist1->get_userids()); 394 // Delete using delete_data_for_user. 395 provider::delete_data_for_users($approvedlist); 396 // Re-fetch users in u1ctx - the user data should now be empty. 397 $userlist1 = new \core_privacy\local\request\userlist($u1ctx, $component); 398 provider::get_users_in_context($userlist1); 399 $this->assertCount(0, $userlist1); 400 401 $approvedlist = new approved_userlist($u2ctx, $component, $userlist2->get_userids()); 402 // Delete using delete_data_for_user. 403 provider::delete_data_for_users($approvedlist); 404 // Re-fetch users in u2ctx - the user data should now be empty. 405 $userlist2 = new \core_privacy\local\request\userlist($u2ctx, $component); 406 provider::get_users_in_context($userlist2); 407 $this->assertCount(0, $userlist2); 408 409 $approvedlist = new approved_userlist($u3ctx, $component, $userlist3->get_userids()); 410 // Delete using delete_data_for_user. 411 provider::delete_data_for_users($approvedlist); 412 // Re-fetch users in u3ctx - the user data should now be empty. 413 $userlist3 = new \core_privacy\local\request\userlist($u3ctx, $component); 414 provider::get_users_in_context($userlist3); 415 $this->assertCount(0, $userlist3); 416 417 $approvedlist = new approved_userlist($u4ctx, $component, $userlist3->get_userids()); 418 // Delete using delete_data_for_user. 419 provider::delete_data_for_users($approvedlist); 420 // Re-fetch users in u4ctx - the user data should now be empty. 421 $userlist4 = new \core_privacy\local\request\userlist($u4ctx, $component); 422 provider::get_users_in_context($userlist4); 423 $this->assertCount(0, $userlist4); 424 425 // The list of users for u5ctx should still return one user (u5). 426 $userlist5 = new \core_privacy\local\request\userlist($u5ctx, $component); 427 provider::get_users_in_context($userlist5); 428 $this->assertCount(1, $userlist5); 429 430 // User data should only be removed in the user context. 431 $systemcontext = \context_system::instance(); 432 $approvedlist = new approved_userlist($systemcontext, $component, $userlist5->get_userids()); 433 // Delete using delete_data_for_user. 434 provider::delete_data_for_users($approvedlist); 435 // Re-fetch users in u5ctx - the user data should still be present. 436 $userlist5 = new \core_privacy\local\request\userlist($u5ctx, $component); 437 provider::get_users_in_context($userlist5); 438 $this->assertCount(1, $userlist5); 439 } 440 441 /** 442 * Create a service. 443 * 444 * @param array $params The params. 445 * @return \stdClass 446 */ 447 protected function create_service(array $params = []) { 448 global $DB; 449 static $i = 0; 450 $record = (object) array_merge([ 451 'name' => 'Some service', 452 'enabled' => '1', 453 'requiredcapability' => '', 454 'restrictedusers' => '0', 455 'component' => 'core_external', 456 'timecreated' => time(), 457 'timemodified' => time(), 458 'shortname' => 'service' . $i, 459 'downloadfiles' => '1', 460 'uploadfiles' => '1', 461 ], $params); 462 $record->id = $DB->insert_record('external_services', $record); 463 return $record; 464 } 465 466 /** 467 * Create a service user. 468 * 469 * @param array $params The params. 470 * @return \stdClass 471 */ 472 protected function create_service_user(array $params) { 473 global $DB, $USER; 474 static $i = 0; 475 $record = (object) array_merge([ 476 'externalserviceid' => null, 477 'userid' => $USER->id, 478 'validuntil' => time() + YEARSECS, 479 'iprestriction' => '', 480 'timecreated' => time(), 481 ], $params); 482 $record->id = $DB->insert_record('external_services_users', $record); 483 return $record; 484 } 485 486 /** 487 * Create a token. 488 * 489 * @param array $params The params. 490 * @return stdClass 491 */ 492 protected function create_token(array $params) { 493 global $DB, $USER; 494 $service = $DB->get_record('external_services', ['shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE]); 495 $record = (object) array_merge([ 496 'token' => random_string(64), 497 'privatetoken' => random_string(64), 498 'tokentype' => EXTERNAL_TOKEN_PERMANENT, 499 'contextid' => SYSCONTEXTID, 500 'externalserviceid' => $service->id, 501 'userid' => $USER->id, 502 'validuntil' => time() + YEARSECS, 503 'iprestriction' => null, 504 'sid' => null, 505 'timecreated' => time(), 506 'lastaccess' => time(), 507 'creatorid' => $USER->id, 508 ], $params); 509 $record->id = $DB->insert_record('external_tokens', $record); 510 return $record; 511 } 512 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body