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  namespace auth_lti\privacy;
  18  
  19  use core_privacy\local\request\approved_contextlist;
  20  use core_privacy\local\request\userlist;
  21  use core_privacy\local\request\writer;
  22  use core_privacy\tests\provider_testcase;
  23  use core_privacy\local\request\approved_userlist;
  24  
  25  /**
  26   * Test for the auth_lti privacy provider.
  27   *
  28   * @package    auth_lti
  29   * @copyright  2021 Jake Dallimore <jrhdallimore@gmail.com>
  30   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  31   * @coversDefaultClass \auth_lti\privacy\provider
  32   */
  33  class provider_test extends provider_testcase {
  34      /**
  35       * Set up method.
  36       */
  37      public function setUp(): void {
  38          $this->resetAfterTest();
  39          $this->setAdminUser();
  40      }
  41  
  42      /**
  43       * Check that a user context is returned if there is any user data for this user.
  44       *
  45       * @covers ::get_contexts_for_userid
  46       */
  47      public function test_get_contexts_for_userid() {
  48          $user = $this->getDataGenerator()->create_user();
  49          $this->assertEmpty(provider::get_contexts_for_userid($user->id));
  50  
  51          $auth = get_auth_plugin('lti');
  52          $auth->create_user_binding('https://lms.example.com', 'abc123', $user->id);
  53  
  54          $contextlist = provider::get_contexts_for_userid($user->id);
  55          // Check that we only get back one context.
  56          $this->assertCount(1, $contextlist);
  57  
  58          // Check that a context is returned is the expected.
  59          $usercontext = \context_user::instance($user->id);
  60          $this->assertEquals($usercontext->id, $contextlist->get_contextids()[0]);
  61      }
  62  
  63      /**
  64       * Test that user data is exported correctly.
  65       *
  66       * @covers ::export_user_data
  67       */
  68      public function test_export_user_data() {
  69          $user = $this->getDataGenerator()->create_user();
  70          $auth = get_auth_plugin('lti');
  71          $auth->create_user_binding('https://lms.example.com', 'abc123', $user->id);
  72          $usercontext = \context_user::instance($user->id);
  73  
  74          $writer = writer::with_context($usercontext);
  75          $this->assertFalse($writer->has_any_data());
  76          $approvedlist = new approved_contextlist($user, 'auth_lti', [$usercontext->id]);
  77          provider::export_user_data($approvedlist);
  78          $data = $writer->get_data([get_string('privacy:metadata:auth_lti', 'auth_lti'), 'https://lms.example.com']);
  79          $this->assertEquals('https://lms.example.com', $data->issuer);
  80          $this->assertEquals(hash('sha256', 'https://lms.example.com'), $data->issuer256);
  81          $this->assertEquals('abc123', $data->sub);
  82          $this->assertEquals(hash('sha256', 'abc123'), $data->sub256);
  83      }
  84  
  85      /**
  86       * Test deleting all user data for a specific context.
  87       *
  88       * @covers ::delete_data_for_all_users_in_context
  89       */
  90      public function test_delete_data_for_all_users_in_context() {
  91          global $DB;
  92          $auth = get_auth_plugin('lti');
  93  
  94          $user1 = $this->getDataGenerator()->create_user();
  95          $auth->create_user_binding('https://lms.example.com', 'abc123', $user1->id);
  96          $user1context = \context_user::instance($user1->id);
  97  
  98          $user2 = $this->getDataGenerator()->create_user();
  99          $auth->create_user_binding('https://lms.example.com', 'def456', $user2->id);
 100  
 101          // Verify there are two linked logins.
 102          $ltiaccounts = $DB->get_records('auth_lti_linked_login');
 103          $this->assertCount(2, $ltiaccounts);
 104  
 105          // Delete everything for the first user context.
 106          provider::delete_data_for_all_users_in_context($user1context);
 107  
 108          // Get all LTI linked accounts match with user1.
 109          $ltiaccounts = $DB->get_records('auth_lti_linked_login', ['userid' => $user1->id]);
 110          $this->assertCount(0, $ltiaccounts);
 111  
 112          // Verify there is now only one linked login.
 113          $ltiaccounts = $DB->get_records('auth_lti_linked_login');
 114          $this->assertCount(1, $ltiaccounts);
 115      }
 116  
 117      /**
 118       * This should work identical to the above test.
 119       *
 120       * @covers ::delete_data_for_user
 121       */
 122      public function test_delete_data_for_user() {
 123          global $DB;
 124          $auth = get_auth_plugin('lti');
 125  
 126          $user1 = $this->getDataGenerator()->create_user();
 127          $auth->create_user_binding('https://lms.example.com', 'abc123', $user1->id);
 128          $user1context = \context_user::instance($user1->id);
 129  
 130          $user2 = $this->getDataGenerator()->create_user();
 131          $auth->create_user_binding('https://lms.example.com', 'def456', $user2->id);
 132  
 133          // Verify there are two linked logins.
 134          $ltiaccounts = $DB->get_records('auth_lti_linked_login');
 135          $this->assertCount(2, $ltiaccounts);
 136  
 137          // Delete everything for the first user.
 138          $approvedlist = new approved_contextlist($user1, 'auth_lti', [$user1context->id]);
 139          provider::delete_data_for_user($approvedlist);
 140  
 141          // Get all LTI accounts linked with user1.
 142          $ltiaccounts = $DB->get_records('auth_lti_linked_login', ['userid' => $user1->id]);
 143          $this->assertCount(0, $ltiaccounts);
 144  
 145          // Verify there is only one linked login now.
 146          $ltiaccounts = $DB->get_records('auth_lti_linked_login', array());
 147          $this->assertCount(1, $ltiaccounts);
 148      }
 149  
 150      /**
 151       * Test that only users with a user context are fetched.
 152       *
 153       * @covers ::get_users_in_context
 154       */
 155      public function test_get_users_in_context() {
 156          $auth = get_auth_plugin('lti');
 157          $component = 'auth_lti';
 158          $user = $this->getDataGenerator()->create_user();
 159          $usercontext = \context_user::instance($user->id);
 160  
 161          // The list of users should not return anything yet (no linked login yet).
 162          $userlist = new userlist($usercontext, $component);
 163          provider::get_users_in_context($userlist);
 164          $this->assertCount(0, $userlist);
 165  
 166          $auth->create_user_binding('https://lms.example.com', 'abc123', $user->id);
 167  
 168          // The list of users for user context should return the user.
 169          provider::get_users_in_context($userlist);
 170          $this->assertCount(1, $userlist);
 171          $expected = [$user->id];
 172          $actual = $userlist->get_userids();
 173          $this->assertEquals($expected, $actual);
 174  
 175          // The list of users for system context should not return any users.
 176          $systemcontext = \context_system::instance();
 177          $userlist = new userlist($systemcontext, $component);
 178          provider::get_users_in_context($userlist);
 179          $this->assertCount(0, $userlist);
 180      }
 181  
 182      /**
 183       * Test that data for users in approved userlist is deleted.
 184       *
 185       * @covers ::delete_data_for_users
 186       */
 187      public function test_delete_data_for_users() {
 188          $auth = get_auth_plugin('lti');
 189          $component = 'auth_lti';
 190          $user1 = $this->getDataGenerator()->create_user();
 191          $usercontext1 = \context_user::instance($user1->id);
 192          $user2 = $this->getDataGenerator()->create_user();
 193          $usercontext2 = \context_user::instance($user2->id);
 194  
 195          $auth->create_user_binding('https://lms.example.com', 'abc123', $user1->id);
 196          $auth->create_user_binding('https://lms.example.com', 'def456', $user2->id);
 197  
 198          // The list of users for usercontext1 should return user1.
 199          $userlist1 = new userlist($usercontext1, $component);
 200          provider::get_users_in_context($userlist1);
 201          $this->assertCount(1, $userlist1);
 202          $expected = [$user1->id];
 203          $actual = $userlist1->get_userids();
 204          $this->assertEquals($expected, $actual);
 205  
 206          // The list of users for usercontext2 should return user2.
 207          $userlist2 = new userlist($usercontext2, $component);
 208          provider::get_users_in_context($userlist2);
 209          $this->assertCount(1, $userlist2);
 210          $expected = [$user2->id];
 211          $actual = $userlist2->get_userids();
 212          $this->assertEquals($expected, $actual);
 213  
 214          // Add userlist1 to the approved user list.
 215          $approvedlist = new approved_userlist($usercontext1, $component, $userlist1->get_userids());
 216  
 217          // Delete user data using delete_data_for_user for usercontext1.
 218          provider::delete_data_for_users($approvedlist);
 219  
 220          // Re-fetch users in usercontext1 - The user list should now be empty.
 221          $userlist1 = new userlist($usercontext1, $component);
 222          provider::get_users_in_context($userlist1);
 223          $this->assertCount(0, $userlist1);
 224          // Re-fetch users in usercontext2 - The user list should not be empty (user2).
 225          $userlist2 = new userlist($usercontext2, $component);
 226          provider::get_users_in_context($userlist2);
 227          $this->assertCount(1, $userlist2);
 228  
 229          // User data should be only removed in the user context.
 230          $systemcontext = \context_system::instance();
 231          // Add userlist2 to the approved user list in the system context.
 232          $approvedlist = new approved_userlist($systemcontext, $component, $userlist2->get_userids());
 233          // Delete user1 data using delete_data_for_user.
 234          provider::delete_data_for_users($approvedlist);
 235          // Re-fetch users in usercontext2 - The user list should not be empty (user2).
 236          $userlist2 = new userlist($usercontext2, $component);
 237          provider::get_users_in_context($userlist2);
 238          $this->assertCount(1, $userlist2);
 239      }
 240  }