Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

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