Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310]

   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   * Privacy provider tests.
  19   *
  20   * @package    core_backup
  21   * @copyright  2018 Mark Nelson <markn@moodle.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  use core_backup\privacy\provider;
  26  use core_privacy\local\request\approved_userlist;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  /**
  31   * Privacy provider tests class.
  32   *
  33   * @copyright  2018 Mark Nelson <markn@moodle.com>
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class core_backup_privacy_provider_testcase extends \core_privacy\tests\provider_testcase {
  37  
  38      /**
  39       * Test getting the context for the user ID related to this plugin.
  40       */
  41      public function test_get_contexts_for_userid() {
  42          global $DB;
  43  
  44          $this->resetAfterTest();
  45  
  46          $course = $this->getDataGenerator()->create_course();
  47          $user = $this->getDataGenerator()->create_user();
  48  
  49          // Just insert directly into the 'backup_controllers' table.
  50          $bcdata = (object) [
  51              'backupid' => 1,
  52              'operation' => 'restore',
  53              'type' => 'course',
  54              'itemid' => $course->id,
  55              'format' => 'moodle2',
  56              'interactive' => 1,
  57              'purpose' => 10,
  58              'userid' => $user->id,
  59              'status' => 1000,
  60              'execution' => 1,
  61              'executiontime' => 0,
  62              'checksum' => 'checksumyolo',
  63              'timecreated' => time(),
  64              'timemodified' => time(),
  65              'controller' => ''
  66          ];
  67          $DB->insert_record('backup_controllers', $bcdata);
  68  
  69          $contextlist = provider::get_contexts_for_userid($user->id);
  70          $this->assertCount(1, $contextlist);
  71          $contextforuser = $contextlist->current();
  72          $context = context_course::instance($course->id);
  73          $this->assertEquals($context->id, $contextforuser->id);
  74      }
  75  
  76      /**
  77       * Test for provider::export_user_data().
  78       */
  79      public function test_export_for_context() {
  80          global $DB;
  81  
  82          $this->resetAfterTest();
  83  
  84          $course = $this->getDataGenerator()->create_course();
  85          $user1 = $this->getDataGenerator()->create_user();
  86  
  87          // Just insert directly into the 'backup_controllers' table.
  88          $bcdata1 = (object) [
  89              'backupid' => 1,
  90              'operation' => 'restore',
  91              'type' => 'course',
  92              'itemid' => $course->id,
  93              'format' => 'moodle2',
  94              'interactive' => 1,
  95              'purpose' => 10,
  96              'userid' => $user1->id,
  97              'status' => 1000,
  98              'execution' => 1,
  99              'executiontime' => 0,
 100              'checksum' => 'checksumyolo',
 101              'timecreated' => time(),
 102              'timemodified' => time(),
 103              'controller' => ''
 104          ];
 105          $DB->insert_record('backup_controllers', $bcdata1);
 106  
 107          // Create another user who will perform a backup operation.
 108          $user2 = $this->getDataGenerator()->create_user();
 109          $bcdata2 = (object) [
 110              'backupid' => 2,
 111              'operation' => 'restore',
 112              'type' => 'course',
 113              'itemid' => $course->id,
 114              'format' => 'moodle2',
 115              'interactive' => 1,
 116              'purpose' => 10,
 117              'userid' => $user2->id,
 118              'status' => 1000,
 119              'execution' => 1,
 120              'executiontime' => 0,
 121              'checksum' => 'checksumyolo',
 122              'timecreated' => time(),
 123              'timemodified' => time(),
 124              'controller' => ''
 125          ];
 126          $DB->insert_record('backup_controllers', $bcdata2);
 127  
 128          // Create another backup_controllers record.
 129          $bcdata3 = (object) [
 130              'backupid' => 3,
 131              'operation' => 'backup',
 132              'type' => 'course',
 133              'itemid' => $course->id,
 134              'format' => 'moodle2',
 135              'interactive' => 1,
 136              'purpose' => 10,
 137              'userid' => $user1->id,
 138              'status' => 1000,
 139              'execution' => 1,
 140              'executiontime' => 0,
 141              'checksum' => 'checksumyolo',
 142              'timecreated' => time() + DAYSECS,
 143              'timemodified' => time() + DAYSECS,
 144              'controller' => ''
 145          ];
 146          $DB->insert_record('backup_controllers', $bcdata3);
 147  
 148          $coursecontext = context_course::instance($course->id);
 149  
 150          // Export all of the data for the context.
 151          $this->export_context_data_for_user($user1->id, $coursecontext, 'core_backup');
 152          $writer = \core_privacy\local\request\writer::with_context($coursecontext);
 153          $this->assertTrue($writer->has_any_data());
 154  
 155          $data = (array) $writer->get_data([get_string('backup'), $course->id]);
 156  
 157          $this->assertCount(2, $data);
 158  
 159          $bc1 = array_shift($data);
 160          $this->assertEquals('restore', $bc1['operation']);
 161  
 162          $bc2 = array_shift($data);
 163          $this->assertEquals('backup', $bc2['operation']);
 164      }
 165  
 166      /**
 167       * Test for provider::delete_data_for_all_users_in_context().
 168       */
 169      public function test_delete_data_for_all_users_in_context() {
 170          global $DB;
 171  
 172          $this->resetAfterTest();
 173  
 174          $course = $this->getDataGenerator()->create_course();
 175          $user1 = $this->getDataGenerator()->create_user();
 176  
 177          // Just insert directly into the 'backup_controllers' table.
 178          $bcdata1 = (object) [
 179              'backupid' => 1,
 180              'operation' => 'restore',
 181              'type' => 'course',
 182              'itemid' => $course->id,
 183              'format' => 'moodle2',
 184              'interactive' => 1,
 185              'purpose' => 10,
 186              'userid' => $user1->id,
 187              'status' => 1000,
 188              'execution' => 1,
 189              'executiontime' => 0,
 190              'checksum' => 'checksumyolo',
 191              'timecreated' => time(),
 192              'timemodified' => time(),
 193              'controller' => ''
 194          ];
 195          $DB->insert_record('backup_controllers', $bcdata1);
 196  
 197          // Create another user who will perform a backup operation.
 198          $user2 = $this->getDataGenerator()->create_user();
 199          $bcdata2 = (object) [
 200              'backupid' => 2,
 201              'operation' => 'restore',
 202              'type' => 'course',
 203              'itemid' => $course->id,
 204              'format' => 'moodle2',
 205              'interactive' => 1,
 206              'purpose' => 10,
 207              'userid' => $user2->id,
 208              'status' => 1000,
 209              'execution' => 1,
 210              'executiontime' => 0,
 211              'checksum' => 'checksumyolo',
 212              'timecreated' => time(),
 213              'timemodified' => time(),
 214              'controller' => ''
 215          ];
 216          $DB->insert_record('backup_controllers', $bcdata2);
 217  
 218          // Before deletion, we should have 2 operations.
 219          $count = $DB->count_records('backup_controllers', ['itemid' => $course->id]);
 220          $this->assertEquals(2, $count);
 221  
 222          // Delete data based on context.
 223          $coursecontext = context_course::instance($course->id);
 224          provider::delete_data_for_all_users_in_context($coursecontext);
 225  
 226          // After deletion, the operations for that course should have been deleted.
 227          $count = $DB->count_records('backup_controllers', ['itemid' => $course->id]);
 228          $this->assertEquals(0, $count);
 229      }
 230  
 231      /**
 232       * Test for provider::delete_data_for_user().
 233       */
 234      public function test_delete_data_for_user() {
 235          global $DB;
 236  
 237          $this->resetAfterTest();
 238  
 239          $course = $this->getDataGenerator()->create_course();
 240          $user1 = $this->getDataGenerator()->create_user();
 241  
 242          // Just insert directly into the 'backup_controllers' table.
 243          $bcdata1 = (object) [
 244              'backupid' => 1,
 245              'operation' => 'restore',
 246              'type' => 'course',
 247              'itemid' => $course->id,
 248              'format' => 'moodle2',
 249              'interactive' => 1,
 250              'purpose' => 10,
 251              'userid' => $user1->id,
 252              'status' => 1000,
 253              'execution' => 1,
 254              'executiontime' => 0,
 255              'checksum' => 'checksumyolo',
 256              'timecreated' => time(),
 257              'timemodified' => time(),
 258              'controller' => ''
 259          ];
 260          $DB->insert_record('backup_controllers', $bcdata1);
 261  
 262          // Create another user who will perform a backup operation.
 263          $user2 = $this->getDataGenerator()->create_user();
 264          $bcdata2 = (object) [
 265              'backupid' => 2,
 266              'operation' => 'restore',
 267              'type' => 'course',
 268              'itemid' => $course->id,
 269              'format' => 'moodle2',
 270              'interactive' => 1,
 271              'purpose' => 10,
 272              'userid' => $user2->id,
 273              'status' => 1000,
 274              'execution' => 1,
 275              'executiontime' => 0,
 276              'checksum' => 'checksumyolo',
 277              'timecreated' => time(),
 278              'timemodified' => time(),
 279              'controller' => ''
 280          ];
 281          $DB->insert_record('backup_controllers', $bcdata2);
 282  
 283          // Before deletion, we should have 2 operations.
 284          $count = $DB->count_records('backup_controllers', ['itemid' => $course->id]);
 285          $this->assertEquals(2, $count);
 286  
 287          $coursecontext = context_course::instance($course->id);
 288          $contextlist = new \core_privacy\local\request\approved_contextlist($user1, 'core_backup',
 289              [context_system::instance()->id, $coursecontext->id]);
 290          provider::delete_data_for_user($contextlist);
 291  
 292          // After deletion, the backup operation for the user should have been deleted.
 293          $count = $DB->count_records('backup_controllers', ['itemid' => $course->id, 'userid' => $user1->id]);
 294          $this->assertEquals(0, $count);
 295  
 296          // Confirm we still have the other users record.
 297          $bcs = $DB->get_records('backup_controllers');
 298          $this->assertCount(1, $bcs);
 299          $lastsubmission = reset($bcs);
 300          $this->assertNotEquals($user1->id, $lastsubmission->userid);
 301      }
 302  
 303      /**
 304       * Test that only users with a course and module context are fetched.
 305       */
 306      public function test_get_users_in_context() {
 307          global $DB;
 308  
 309          $this->resetAfterTest();
 310  
 311          $component = 'core_backup';
 312  
 313          $course = $this->getDataGenerator()->create_course();
 314          $activity = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
 315  
 316          $user = $this->getDataGenerator()->create_user();
 317          $user2 = $this->getDataGenerator()->create_user();
 318  
 319          $coursecontext = context_course::instance($course->id);
 320          $activitycontext = \context_module::instance($activity->cmid);
 321  
 322          // The list of users for course context should return the user.
 323          $userlist = new \core_privacy\local\request\userlist($coursecontext, $component);
 324          provider::get_users_in_context($userlist);
 325          $this->assertCount(0, $userlist);
 326  
 327          // Create a course backup.
 328          // Just insert directly into the 'backup_controllers' table.
 329          $bcdata = (object) [
 330              'backupid' => 1,
 331              'operation' => 'restore',
 332              'type' => 'course',
 333              'itemid' => $course->id,
 334              'format' => 'moodle2',
 335              'interactive' => 1,
 336              'purpose' => 10,
 337              'userid' => $user->id,
 338              'status' => 1000,
 339              'execution' => 1,
 340              'executiontime' => 0,
 341              'checksum' => 'checksumyolo',
 342              'timecreated' => time(),
 343              'timemodified' => time(),
 344              'controller' => ''
 345          ];
 346  
 347          $DB->insert_record('backup_controllers', $bcdata);
 348  
 349          // The list of users for the course context should return user.
 350          provider::get_users_in_context($userlist);
 351          $this->assertCount(1, $userlist);
 352          $expected = [$user->id];
 353          $actual = $userlist->get_userids();
 354          $this->assertEquals($expected, $actual);
 355  
 356          // Create an activity backup.
 357          // Just insert directly into the 'backup_controllers' table.
 358          $bcdata = (object) [
 359              'backupid' => 2,
 360              'operation' => 'restore',
 361              'type' => 'activity',
 362              'itemid' => $activity->cmid,
 363              'format' => 'moodle2',
 364              'interactive' => 1,
 365              'purpose' => 10,
 366              'userid' => $user2->id,
 367              'status' => 1000,
 368              'execution' => 1,
 369              'executiontime' => 0,
 370              'checksum' => 'checksumyolo',
 371              'timecreated' => time(),
 372              'timemodified' => time(),
 373              'controller' => ''
 374          ];
 375  
 376          $DB->insert_record('backup_controllers', $bcdata);
 377  
 378          // The list of users for the course context should return user2.
 379          $userlist = new \core_privacy\local\request\userlist($activitycontext, $component);
 380          provider::get_users_in_context($userlist);
 381          $this->assertCount(1, $userlist);
 382          $expected = [$user2->id];
 383          $actual = $userlist->get_userids();
 384          $this->assertEquals($expected, $actual);
 385  
 386          // The list of users for system context should not return any users.
 387          $systemcontext = context_system::instance();
 388          $userlist = new \core_privacy\local\request\userlist($systemcontext, $component);
 389          provider::get_users_in_context($userlist);
 390          $this->assertCount(0, $userlist);
 391      }
 392  
 393      /**
 394       * Test that data for users in approved userlist is deleted.
 395       */
 396      public function test_delete_data_for_users() {
 397          global $DB;
 398  
 399          $this->resetAfterTest();
 400  
 401          $component = 'core_backup';
 402  
 403          // Create course1.
 404          $course1 = $this->getDataGenerator()->create_course();
 405          $coursecontext = context_course::instance($course1->id);
 406          // Create course2.
 407          $course2 = $this->getDataGenerator()->create_course();
 408          $coursecontext2 = context_course::instance($course2->id);
 409          // Create an activity.
 410          $activity = $this->getDataGenerator()->create_module('chat', ['course' => $course1->id]);
 411          $activitycontext = \context_module::instance($activity->cmid);
 412          // Create user1.
 413          $user1 = $this->getDataGenerator()->create_user();
 414          // Create user2.
 415          $user2 = $this->getDataGenerator()->create_user();
 416          // Create user2.
 417          $user3 = $this->getDataGenerator()->create_user();
 418  
 419          // Just insert directly into the 'backup_controllers' table.
 420          $bcdata1 = (object) [
 421              'backupid' => 1,
 422              'operation' => 'restore',
 423              'type' => 'course',
 424              'itemid' => $course1->id,
 425              'format' => 'moodle2',
 426              'interactive' => 1,
 427              'purpose' => 10,
 428              'userid' => $user1->id,
 429              'status' => 1000,
 430              'execution' => 1,
 431              'executiontime' => 0,
 432              'checksum' => 'checksumyolo',
 433              'timecreated' => time(),
 434              'timemodified' => time(),
 435              'controller' => ''
 436          ];
 437          $DB->insert_record('backup_controllers', $bcdata1);
 438  
 439          // Just insert directly into the 'backup_controllers' table.
 440          $bcdata2 = (object) [
 441              'backupid' => 2,
 442              'operation' => 'backup',
 443              'type' => 'course',
 444              'itemid' => $course1->id,
 445              'format' => 'moodle2',
 446              'interactive' => 1,
 447              'purpose' => 10,
 448              'userid' => $user2->id,
 449              'status' => 1000,
 450              'execution' => 1,
 451              'executiontime' => 0,
 452              'checksum' => 'checksumyolo',
 453              'timecreated' => time(),
 454              'timemodified' => time(),
 455              'controller' => ''
 456          ];
 457          $DB->insert_record('backup_controllers', $bcdata2);
 458  
 459          // Just insert directly into the 'backup_controllers' table.
 460          $bcdata3 = (object) [
 461              'backupid' => 3,
 462              'operation' => 'restore',
 463              'type' => 'activity',
 464              'itemid' => $activity->cmid,
 465              'format' => 'moodle2',
 466              'interactive' => 1,
 467              'purpose' => 10,
 468              'userid' => $user3->id,
 469              'status' => 1000,
 470              'execution' => 1,
 471              'executiontime' => 0,
 472              'checksum' => 'checksumyolo',
 473              'timecreated' => time(),
 474              'timemodified' => time(),
 475              'controller' => ''
 476          ];
 477          $DB->insert_record('backup_controllers', $bcdata3);
 478  
 479          // The list of users for coursecontext should return user1 and user2.
 480          $userlist1 = new \core_privacy\local\request\userlist($coursecontext, $component);
 481          provider::get_users_in_context($userlist1);
 482          $this->assertCount(2, $userlist1);
 483          $expected = [$user1->id, $user2->id];
 484          $actual = $userlist1->get_userids();
 485          $this->assertEqualsCanonicalizing($expected, $actual);
 486  
 487          // The list of users for coursecontext2 should not return users.
 488          $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
 489          provider::get_users_in_context($userlist2);
 490          $this->assertCount(0, $userlist2);
 491  
 492          // The list of users for activitycontext should return user3.
 493          $userlist3 = new \core_privacy\local\request\userlist($activitycontext, $component);
 494          provider::get_users_in_context($userlist3);
 495          $this->assertCount(1, $userlist3);
 496          $expected = [$user3->id];
 497          $actual = $userlist3->get_userids();
 498          $this->assertEquals($expected, $actual);
 499  
 500          // Add user1 to the approved user list.
 501          $approvedlist = new approved_userlist($coursecontext, $component, [$user1->id]);
 502          // Delete user data using delete_data_for_user for usercontext1.
 503          provider::delete_data_for_users($approvedlist);
 504  
 505          // Re-fetch users in coursecontext - The user list should now return only user2.
 506          $userlist1 = new \core_privacy\local\request\userlist($coursecontext, $component);
 507          provider::get_users_in_context($userlist1);
 508          $this->assertCount(1, $userlist1);
 509          $expected = [$user2->id];
 510          $actual = $userlist1->get_userids();
 511          $this->assertEquals($expected, $actual);
 512  
 513          // Re-fetch users in activitycontext - The user list should not be empty (user3).
 514          $userlist3 = new \core_privacy\local\request\userlist($activitycontext, $component);
 515          provider::get_users_in_context($userlist3);
 516          $this->assertCount(1, $userlist3);
 517  
 518          // Add user1 to the approved user list.
 519          $approvedlist = new approved_userlist($activitycontext, $component, [$user3->id]);
 520          // Delete user data using delete_data_for_user for usercontext1.
 521          provider::delete_data_for_users($approvedlist);
 522  
 523          // Re-fetch users in activitycontext - The user list should not return any users.
 524          $userlist3 = new \core_privacy\local\request\userlist($activitycontext, $component);
 525          provider::get_users_in_context($userlist3);
 526          $this->assertCount(0, $userlist3);
 527  
 528          // User data should be only removed in the course context and module context.
 529          $systemcontext = context_system::instance();
 530          // Add userlist2 to the approved user list in the system context.
 531          $approvedlist = new approved_userlist($systemcontext, $component, $userlist2->get_userids());
 532          // Delete user1 data using delete_data_for_user.
 533          provider::delete_data_for_users($approvedlist);
 534          // Re-fetch users in usercontext2 - The user list should not be empty (user2).
 535          $userlist2 = new \core_privacy\local\request\userlist($coursecontext, $component);
 536          provider::get_users_in_context($userlist2);
 537          $this->assertCount(1, $userlist2);
 538      }
 539  }