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   * Data provider tests.
  19   *
  20   * @package    mod_chat
  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  
  27  defined('MOODLE_INTERNAL') || die();
  28  global $CFG;
  29  
  30  use core_privacy\tests\provider_testcase;
  31  use core_privacy\local\request\approved_contextlist;
  32  use core_privacy\local\request\approved_userlist;
  33  use core_privacy\local\request\transform;
  34  use core_privacy\local\request\writer;
  35  use mod_chat\privacy\provider;
  36  
  37  require_once($CFG->dirroot . '/mod/chat/lib.php');
  38  
  39  /**
  40   * Data provider testcase class.
  41   *
  42   * @package    mod_chat
  43   * @category   test
  44   * @copyright  2018 Frédéric Massart
  45   * @author     Frédéric Massart <fred@branchup.tech>
  46   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  47   */
  48  class mod_chat_privacy_testcase extends provider_testcase {
  49  
  50      public function setUp(): void {
  51          global $PAGE;
  52          $this->resetAfterTest();
  53          $PAGE->get_renderer('core');
  54      }
  55  
  56      public function test_get_contexts_for_userid() {
  57          global $DB;
  58          $dg = $this->getDataGenerator();
  59          $c1 = $dg->create_course();
  60          $c2 = $dg->create_course();
  61  
  62          $u1 = $dg->create_user();
  63          $u2 = $dg->create_user();
  64  
  65          $chat1a = $dg->create_module('chat', ['course' => $c1]);
  66          $chat1b = $dg->create_module('chat', ['course' => $c1]);
  67          $chat2a = $dg->create_module('chat', ['course' => $c2]);
  68  
  69          // Logins but no message.
  70          $chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1a);
  71  
  72          // Logins and messages.
  73          $chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1b);
  74          chat_send_chatmessage($chatuser, 'Hello world!');
  75  
  76          // Silent login (no system message).
  77          $chatuser = $this->login_user_in_course_chat($u1, $c2, $chat2a, 0, true);
  78  
  79          // Silent login and messages.
  80          $chatuser = $this->login_user_in_course_chat($u2, $c1, $chat1b, 0, true);
  81          chat_send_chatmessage($chatuser, 'Ça va ?');
  82          chat_send_chatmessage($chatuser, 'Moi, ça va.');
  83  
  84          // Silent login and messages.
  85          $chatuser = $this->login_user_in_course_chat($u2, $c2, $chat2a);
  86          chat_send_chatmessage($chatuser, 'What\'s happening here?');
  87  
  88          // Check contexts for user 1.
  89          $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
  90          $this->assertCount(2, $contextids);
  91          $this->assertTrue(in_array(context_module::instance($chat1a->cmid)->id, $contextids));
  92          $this->assertTrue(in_array(context_module::instance($chat1b->cmid)->id, $contextids));
  93  
  94          $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
  95          $this->assertCount(2, $contextids);
  96          $this->assertTrue(in_array(context_module::instance($chat1b->cmid)->id, $contextids));
  97          $this->assertTrue(in_array(context_module::instance($chat2a->cmid)->id, $contextids));
  98      }
  99  
 100      /**
 101       * Test that only users with relevant contexts are fetched.
 102       */
 103      public function test_get_users_in_context() {
 104          $component = 'mod_chat';
 105          $dg = $this->getDataGenerator();
 106          $c1 = $dg->create_course();
 107          $c2 = $dg->create_course();
 108  
 109          $u1 = $dg->create_user();
 110          $u2 = $dg->create_user();
 111  
 112          $chat1a = $dg->create_module('chat', ['course' => $c1]);
 113          $chat1b = $dg->create_module('chat', ['course' => $c1]);
 114          $chat2a = $dg->create_module('chat', ['course' => $c2]);
 115  
 116          // Logins but no message.
 117          $chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1a);
 118  
 119          // Logins and messages.
 120          $chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1b);
 121          chat_send_chatmessage($chatuser, 'Hello world!');
 122  
 123          // Silent login (no system message).
 124          $chatuser = $this->login_user_in_course_chat($u1, $c2, $chat2a, 0, true);
 125  
 126          // Silent login and messages.
 127          $chatuser = $this->login_user_in_course_chat($u2, $c1, $chat1b, 0, true);
 128          chat_send_chatmessage($chatuser, 'Ça va ?');
 129          chat_send_chatmessage($chatuser, 'Moi, ça va.');
 130  
 131          // Silent login and messages.
 132          $chatuser = $this->login_user_in_course_chat($u2, $c2, $chat2a);
 133          chat_send_chatmessage($chatuser, 'What\'s happening here?');
 134  
 135          $context1a = context_module::instance($chat1a->cmid);
 136          $context1b = context_module::instance($chat1b->cmid);
 137          $context2a = context_module::instance($chat2a->cmid);
 138  
 139          $userlist1a = new \core_privacy\local\request\userlist($context1a, $component);
 140          $userlist1b = new \core_privacy\local\request\userlist($context1b, $component);
 141          $userlist2a = new \core_privacy\local\request\userlist($context2a, $component);
 142          \mod_chat\privacy\provider::get_users_in_context($userlist1a);
 143          \mod_chat\privacy\provider::get_users_in_context($userlist1b);
 144          \mod_chat\privacy\provider::get_users_in_context($userlist2a);
 145  
 146          // Ensure correct users are found in relevant contexts.
 147          $this->assertCount(1, $userlist1a);
 148          $expected = [$u1->id];
 149          $actual = $userlist1a->get_userids();
 150          $this->assertEquals($expected, $actual);
 151  
 152          $this->assertCount(2, $userlist1b);
 153          $expected = [$u1->id, $u2->id];
 154          $actual = $userlist1b->get_userids();
 155          sort($expected);
 156          sort($actual);
 157          $this->assertEquals($expected, $actual);
 158  
 159          $this->assertCount(1, $userlist2a);
 160          $expected = [$u1->id];
 161          $actual = $userlist1a->get_userids();
 162          $this->assertEquals($expected, $actual);
 163      }
 164  
 165      public function test_delete_data_for_all_users_in_context() {
 166          global $DB;
 167          $dg = $this->getDataGenerator();
 168          $c1 = $dg->create_course();
 169  
 170          $u1 = $dg->create_user();
 171          $u2 = $dg->create_user();
 172  
 173          $chat1a = $dg->create_module('chat', ['course' => $c1]);
 174          $chat1b = $dg->create_module('chat', ['course' => $c1]);
 175          $chat1actx = context_module::instance($chat1a->cmid);
 176          $chat1bctx = context_module::instance($chat1b->cmid);
 177  
 178          $u1chat1a = $this->login_user_in_course_chat($u1, $c1, $chat1a);
 179          $u2chat1a = $this->login_user_in_course_chat($u2, $c1, $chat1a);
 180          chat_send_chatmessage($u1chat1a, 'Ça va ?');
 181          chat_send_chatmessage($u2chat1a, 'Oui, et toi ?');
 182          chat_send_chatmessage($u1chat1a, 'Bien merci.');
 183          chat_send_chatmessage($u2chat1a, 'Pourquoi ils disent omelette "du" fromage ?!');
 184          chat_send_chatmessage($u1chat1a, 'Aucune idée');
 185          $this->assert_has_data_in_chat($u1, $chat1a);
 186          $this->assert_has_data_in_chat($u2, $chat1a);
 187  
 188          $u1chat1b = $this->login_user_in_course_chat($u1, $c1, $chat1b);
 189          $u2chat1b = $this->login_user_in_course_chat($u2, $c1, $chat1b);
 190          chat_send_chatmessage($u1chat1b, 'How are you going?');
 191          chat_send_chatmessage($u2chat1b, 'Alright, you?');
 192          chat_send_chatmessage($u1chat1b, 'Good, thanks.');
 193          chat_send_chatmessage($u2chat1b, 'Sacre bleu!');
 194          chat_send_chatmessage($u1chat1b, '\ö/');
 195          $this->assert_has_data_in_chat($u1, $chat1b);
 196          $this->assert_has_data_in_chat($u2, $chat1b);
 197  
 198          // No change.
 199          provider::delete_data_for_all_users_in_context(context_course::instance($c1->id));
 200          $this->assert_has_data_in_chat($u1, $chat1a);
 201          $this->assert_has_data_in_chat($u2, $chat1a);
 202          $this->assert_has_data_in_chat($u1, $chat1b);
 203          $this->assert_has_data_in_chat($u2, $chat1b);
 204  
 205          // Deletinge first chat does not affect other chat.
 206          provider::delete_data_for_all_users_in_context($chat1actx);
 207          $this->assert_has_no_data_in_chat($u1, $chat1a);
 208          $this->assert_has_no_data_in_chat($u2, $chat1a);
 209          $this->assert_has_data_in_chat($u1, $chat1b);
 210          $this->assert_has_data_in_chat($u2, $chat1b);
 211      }
 212  
 213      public function test_delete_data_for_user() {
 214          global $DB;
 215          $dg = $this->getDataGenerator();
 216          $c1 = $dg->create_course();
 217  
 218          $u1 = $dg->create_user();
 219          $u2 = $dg->create_user();
 220  
 221          $chat1a = $dg->create_module('chat', ['course' => $c1]);
 222          $chat1b = $dg->create_module('chat', ['course' => $c1]);
 223          $chat1actx = context_module::instance($chat1a->cmid);
 224          $chat1bctx = context_module::instance($chat1b->cmid);
 225  
 226          $u1chat1a = $this->login_user_in_course_chat($u1, $c1, $chat1a);
 227          $u2chat1a = $this->login_user_in_course_chat($u2, $c1, $chat1a);
 228          chat_send_chatmessage($u1chat1a, 'Ça va ?');
 229          chat_send_chatmessage($u2chat1a, 'Oui, et toi ?');
 230          chat_send_chatmessage($u1chat1a, 'Bien merci.');
 231          chat_send_chatmessage($u2chat1a, 'Pourquoi ils disent omelette "du" fromage ?!');
 232          chat_send_chatmessage($u1chat1a, 'Aucune idée');
 233          $this->assert_has_data_in_chat($u1, $chat1a);
 234          $this->assert_has_data_in_chat($u2, $chat1a);
 235  
 236          $u1chat1b = $this->login_user_in_course_chat($u1, $c1, $chat1b);
 237          $u2chat1b = $this->login_user_in_course_chat($u2, $c1, $chat1b);
 238          chat_send_chatmessage($u1chat1b, 'How are you going?');
 239          chat_send_chatmessage($u2chat1b, 'Alright, you?');
 240          chat_send_chatmessage($u1chat1b, 'Good, thanks.');
 241          chat_send_chatmessage($u2chat1b, 'Sacre bleu!');
 242          chat_send_chatmessage($u1chat1b, '\ö/');
 243          $this->assert_has_data_in_chat($u1, $chat1b);
 244          $this->assert_has_data_in_chat($u2, $chat1b);
 245  
 246          provider::delete_data_for_user(new approved_contextlist($u1, 'mod_chat', [$chat1actx->id]));
 247          $this->assert_has_no_data_in_chat($u1, $chat1a);
 248          $this->assert_has_data_in_chat($u2, $chat1a);
 249          $this->assert_has_data_in_chat($u1, $chat1b);
 250          $this->assert_has_data_in_chat($u2, $chat1b);
 251  
 252          provider::delete_data_for_user(new approved_contextlist($u2, 'mod_chat', [$chat1actx->id, $chat1bctx->id]));
 253          $this->assert_has_no_data_in_chat($u1, $chat1a);
 254          $this->assert_has_no_data_in_chat($u2, $chat1a);
 255          $this->assert_has_data_in_chat($u1, $chat1b);
 256          $this->assert_has_no_data_in_chat($u2, $chat1b);
 257      }
 258  
 259      /**
 260       * Test that data for users in approved userlist is deleted.
 261       */
 262      public function test_delete_data_for_users() {
 263          global $DB;
 264          $component = 'mod_chat';
 265          $dg = $this->getDataGenerator();
 266          $c1 = $dg->create_course();
 267  
 268          $u1 = $dg->create_user();
 269          $u2 = $dg->create_user();
 270          $u3 = $dg->create_user();
 271  
 272          $chat1 = $dg->create_module('chat', ['course' => $c1]);
 273          $chat1context = context_module::instance($chat1->cmid);
 274  
 275          $u1chat1 = $this->login_user_in_course_chat($u1, $c1, $chat1);
 276          $u2chat1 = $this->login_user_in_course_chat($u2, $c1, $chat1);
 277          $u3chat1 = $this->login_user_in_course_chat($u3, $c1, $chat1);
 278          chat_send_chatmessage($u1chat1, 'Ça va ?');
 279          chat_send_chatmessage($u2chat1, 'Oui, et toi ?');
 280          chat_send_chatmessage($u1chat1, 'Bien merci.');
 281          chat_send_chatmessage($u2chat1, 'Pourquoi ils disent omelette "du" fromage ?!');
 282          chat_send_chatmessage($u1chat1, 'Aucune idée');
 283          chat_send_chatmessage($u3chat1, 'Je ne comprends pas');
 284          $this->assert_has_data_in_chat($u1, $chat1);
 285          $this->assert_has_data_in_chat($u2, $chat1);
 286          $this->assert_has_data_in_chat($u3, $chat1);
 287  
 288          $chat2 = $dg->create_module('chat', ['course' => $c1]);
 289  
 290          $u1chat2 = $this->login_user_in_course_chat($u1, $c1, $chat2);
 291          $u2chat2 = $this->login_user_in_course_chat($u2, $c1, $chat2);
 292          $u3chat2 = $this->login_user_in_course_chat($u3, $c1, $chat2);
 293          chat_send_chatmessage($u1chat2, 'Why do we have a separate chat?');
 294          chat_send_chatmessage($u2chat2, 'I have no idea!');
 295          chat_send_chatmessage($u3chat2, 'Me either.');
 296          $this->assert_has_data_in_chat($u1, $chat2);
 297          $this->assert_has_data_in_chat($u2, $chat2);
 298          $this->assert_has_data_in_chat($u3, $chat2);
 299  
 300          // Delete user 1 and 2 data from chat 1 context only.
 301          $approveduserids = [$u1->id, $u2->id];
 302          $approvedlist = new approved_userlist($chat1context, $component, $approveduserids);
 303          provider::delete_data_for_users($approvedlist);
 304  
 305          // Ensure correct chat data is deleted.
 306          $this->assert_has_no_data_in_chat($u1, $chat1);
 307          $this->assert_has_no_data_in_chat($u2, $chat1);
 308          $this->assert_has_data_in_chat($u3, $chat1);
 309  
 310          $this->assert_has_data_in_chat($u1, $chat2);
 311          $this->assert_has_data_in_chat($u2, $chat2);
 312          $this->assert_has_data_in_chat($u3, $chat2);
 313      }
 314  
 315      public function test_export_data_for_user() {
 316          global $DB;
 317          $dg = $this->getDataGenerator();
 318          $c1 = $dg->create_course();
 319  
 320          $u1 = $dg->create_user();
 321          $u2 = $dg->create_user();
 322  
 323          $chat1a = $dg->create_module('chat', ['course' => $c1]);
 324          $chat1b = $dg->create_module('chat', ['course' => $c1]);
 325          $chat1actx = context_module::instance($chat1a->cmid);
 326          $chat1bctx = context_module::instance($chat1b->cmid);
 327  
 328          $u1chat1a = $this->login_user_in_course_chat($u1, $c1, $chat1a);
 329          $u2chat1a = $this->login_user_in_course_chat($u2, $c1, $chat1a);
 330          chat_send_chatmessage($u1chat1a, 'Ça va ?');
 331          chat_send_chatmessage($u2chat1a, 'Oui, et toi ?');
 332          chat_send_chatmessage($u1chat1a, 'Bien merci.');
 333          chat_send_chatmessage($u2chat1a, 'Pourquoi ils disent omelette "du" fromage ?!');
 334          chat_send_chatmessage($u1chat1a, 'Aucune idée');
 335          chat_send_chatmessage($u1chat1a, 'exit', true);
 336  
 337          $u1chat1b = $this->login_user_in_course_chat($u1, $c1, $chat1b);
 338          $u2chat1b = $this->login_user_in_course_chat($u2, $c1, $chat1b);
 339          chat_send_chatmessage($u1chat1b, 'How are you going?');
 340          chat_send_chatmessage($u2chat1b, 'Alright, you?');
 341          chat_send_chatmessage($u1chat1b, 'Good, thanks.');
 342          chat_send_chatmessage($u2chat1b, 'Sacre bleu!');
 343          chat_send_chatmessage($u1chat1b, '\ö/');
 344  
 345          // Export for user 1 in chat 1.
 346          provider::export_user_data(new approved_contextlist($u1, 'mod_chat', [$chat1actx->id]));
 347          $data = writer::with_context($chat1actx)->get_data([]);
 348          $this->assertNotEmpty($data);
 349          $this->assertCount(5, $data->messages);
 350          $this->assertEquals(get_string('messageenter', 'mod_chat', fullname($u1)), $data->messages[0]['message']);
 351          $this->assertEquals(transform::yesno(true), $data->messages[0]['is_system_generated']);
 352          $this->assertEquals('Ça va ?', $data->messages[1]['message']);
 353          $this->assertEquals(transform::yesno(false), $data->messages[1]['is_system_generated']);
 354          $this->assertEquals('Bien merci.', $data->messages[2]['message']);
 355          $this->assertEquals(transform::yesno(false), $data->messages[2]['is_system_generated']);
 356          $this->assertEquals('Aucune idée', $data->messages[3]['message']);
 357          $this->assertEquals(transform::yesno(false), $data->messages[3]['is_system_generated']);
 358          $this->assertEquals(get_string('messageexit', 'mod_chat', fullname($u1)), $data->messages[4]['message']);
 359          $this->assertEquals(transform::yesno(true), $data->messages[4]['is_system_generated']);
 360          $data = writer::with_context($chat1bctx)->get_data([]);
 361          $this->assertEmpty($data);
 362  
 363          // Export for user2 in chat 1 and 2.
 364          writer::reset();
 365          provider::export_user_data(new approved_contextlist($u2, 'mod_chat', [$chat1actx->id, $chat1bctx->id]));
 366          $data = writer::with_context($chat1actx)->get_data([]);
 367          $this->assertNotEmpty($data);
 368          $this->assertCount(3, $data->messages);
 369          $this->assertEquals(get_string('messageenter', 'mod_chat', fullname($u2)), $data->messages[0]['message']);
 370          $this->assertEquals('Oui, et toi ?', $data->messages[1]['message']);
 371          $this->assertEquals('Pourquoi ils disent omelette "du" fromage ?!', $data->messages[2]['message']);
 372          $data = writer::with_context($chat1bctx)->get_data([]);
 373          $this->assertNotEmpty($data);
 374          $this->assertCount(3, $data->messages);
 375          $this->assertEquals(get_string('messageenter', 'mod_chat', fullname($u2)), $data->messages[0]['message']);
 376          $this->assertEquals('Alright, you?', $data->messages[1]['message']);
 377          $this->assertEquals('Sacre bleu!', $data->messages[2]['message']);
 378      }
 379  
 380      /**
 381       * Assert that there is data for a user in a chat.
 382       *
 383       * @param object $user The user.
 384       * @param object $chat The chat.
 385       * @return void
 386       */
 387      protected function assert_has_data_in_chat($user, $chat) {
 388          $this->assertTrue($this->has_data_in_chat($user, $chat));
 389      }
 390  
 391      /**
 392       * Assert that there isn't any data for a user in a chat.
 393       *
 394       * @param object $user The user.
 395       * @param object $chat The chat.
 396       * @return void
 397       */
 398      protected function assert_has_no_data_in_chat($user, $chat) {
 399          $this->assertFalse($this->has_data_in_chat($user, $chat));
 400      }
 401  
 402      /**
 403       * Check whether a user has data in a chat.
 404       *
 405       * @param object $user The user.
 406       * @param object $chat The chat.
 407       * @return bool
 408       */
 409      protected function has_data_in_chat($user, $chat) {
 410          global $DB;
 411          return $DB->record_exists('chat_messages', ['chatid' => $chat->id, 'userid' => $user->id]);
 412      }
 413  
 414      /**
 415       * Login a user in a chat.
 416       *
 417       * @param object $user The user.
 418       * @param object $course The course.
 419       * @param object $chat The chat.
 420       * @param int $group The group number.
 421       * @param bool $silent Whether we should advertise that the user logs in.
 422       * @return object The chat user.
 423       */
 424      protected function login_user_in_course_chat($user, $course, $chat, $group = 0, $silent = false) {
 425          global $DB, $USER;
 426          $origuser = $USER;
 427          $this->setUser($user);
 428          chat_login_user($chat->id, $silent ? 'sockets' : 'basic', 0, $course);
 429          $chatuser = $DB->get_record('chat_users', ['userid' => $user->id, 'chatid' => $chat->id, 'groupid' => 0]);
 430          $this->setUser($origuser);
 431          return $chatuser;
 432      }
 433  }