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 mod_lti 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_privacy\local\metadata\collection; 26 use mod_lti\privacy\provider; 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 /** 31 * Privacy provider tests class. 32 * 33 * @package mod_lti 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 mod_lti_privacy_provider_testcase extends \core_privacy\tests\provider_testcase { 38 39 /** 40 * Test for provider::get_metadata(). 41 */ 42 public function test_get_metadata() { 43 $collection = new collection('mod_lti'); 44 $newcollection = provider::get_metadata($collection); 45 $itemcollection = $newcollection->get_collection(); 46 $this->assertCount(4, $itemcollection); 47 48 $ltiproviderexternal = array_shift($itemcollection); 49 $this->assertEquals('lti_provider', $ltiproviderexternal->get_name()); 50 51 $ltisubmissiontable = array_shift($itemcollection); 52 $this->assertEquals('lti_submission', $ltisubmissiontable->get_name()); 53 54 $ltitoolproxies = array_shift($itemcollection); 55 $this->assertEquals('lti_tool_proxies', $ltitoolproxies->get_name()); 56 57 $ltitypestable = array_shift($itemcollection); 58 $this->assertEquals('lti_types', $ltitypestable->get_name()); 59 60 $privacyfields = $ltisubmissiontable->get_privacy_fields(); 61 $this->assertArrayHasKey('userid', $privacyfields); 62 $this->assertArrayHasKey('datesubmitted', $privacyfields); 63 $this->assertArrayHasKey('dateupdated', $privacyfields); 64 $this->assertArrayHasKey('gradepercent', $privacyfields); 65 $this->assertArrayHasKey('originalgrade', $privacyfields); 66 $this->assertEquals('privacy:metadata:lti_submission', $ltisubmissiontable->get_summary()); 67 68 $privacyfields = $ltitoolproxies->get_privacy_fields(); 69 $this->assertArrayHasKey('name', $privacyfields); 70 $this->assertArrayHasKey('createdby', $privacyfields); 71 $this->assertArrayHasKey('timecreated', $privacyfields); 72 $this->assertArrayHasKey('timemodified', $privacyfields); 73 $this->assertEquals('privacy:metadata:lti_tool_proxies', $ltitoolproxies->get_summary()); 74 75 $privacyfields = $ltitypestable->get_privacy_fields(); 76 $this->assertArrayHasKey('name', $privacyfields); 77 $this->assertArrayHasKey('createdby', $privacyfields); 78 $this->assertArrayHasKey('timecreated', $privacyfields); 79 $this->assertArrayHasKey('timemodified', $privacyfields); 80 $this->assertEquals('privacy:metadata:lti_types', $ltitypestable->get_summary()); 81 } 82 83 /** 84 * Test for provider::get_contexts_for_userid(). 85 */ 86 public function test_get_contexts_for_userid() { 87 $this->resetAfterTest(); 88 89 $course = $this->getDataGenerator()->create_course(); 90 91 // The LTI activity the user will have submitted something for. 92 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 93 94 // Another LTI activity that has no user activity. 95 $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 96 97 // Create a user which will make a submission. 98 $user = $this->getDataGenerator()->create_user(); 99 100 $this->create_lti_submission($lti->id, $user->id); 101 102 // Check the contexts supplied are correct. 103 $contextlist = provider::get_contexts_for_userid($user->id); 104 $this->assertCount(2, $contextlist); 105 106 $contextformodule = $contextlist->current(); 107 $cmcontext = context_module::instance($lti->cmid); 108 $this->assertEquals($cmcontext->id, $contextformodule->id); 109 110 $contextlist->next(); 111 $contextforsystem = $contextlist->current(); 112 $this->assertEquals(SYSCONTEXTID, $contextforsystem->id); 113 } 114 115 /** 116 * Test for provider::test_get_users_in_context() 117 */ 118 public function test_get_users_in_context() { 119 $this->resetAfterTest(); 120 121 $course = $this->getDataGenerator()->create_course(); 122 $component = 'mod_lti'; 123 124 // The LTI activity the user will have submitted something for. 125 $lti1 = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 126 127 // Another LTI activity that has no user activity. 128 $lti2 = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 129 130 // Create user which will make a submission each. 131 $user1 = $this->getDataGenerator()->create_user(); 132 $user2 = $this->getDataGenerator()->create_user(); 133 134 $this->create_lti_submission($lti1->id, $user1->id); 135 $this->create_lti_submission($lti1->id, $user2->id); 136 137 $context = context_module::instance($lti1->cmid); 138 $userlist = new \core_privacy\local\request\userlist($context, $component); 139 provider::get_users_in_context($userlist); 140 141 $this->assertCount(2, $userlist); 142 $expected = [$user1->id, $user2->id]; 143 $actual = $userlist->get_userids(); 144 sort($expected); 145 sort($actual); 146 147 $this->assertEquals($expected, $actual); 148 149 $context = context_module::instance($lti2->cmid); 150 $userlist = new \core_privacy\local\request\userlist($context, $component); 151 provider::get_users_in_context($userlist); 152 153 $this->assertEmpty($userlist); 154 } 155 156 /** 157 * Test for provider::export_user_data(). 158 */ 159 public function test_export_for_context_submissions() { 160 $this->resetAfterTest(); 161 162 $course = $this->getDataGenerator()->create_course(); 163 164 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 165 166 // Create users which will make submissions. 167 $user1 = $this->getDataGenerator()->create_user(); 168 $user2 = $this->getDataGenerator()->create_user(); 169 170 $this->create_lti_submission($lti->id, $user1->id); 171 $this->create_lti_submission($lti->id, $user1->id); 172 $this->create_lti_submission($lti->id, $user2->id); 173 174 // Export all of the data for the context for user 1. 175 $cmcontext = context_module::instance($lti->cmid); 176 $this->export_context_data_for_user($user1->id, $cmcontext, 'mod_lti'); 177 $writer = \core_privacy\local\request\writer::with_context($cmcontext); 178 179 $this->assertTrue($writer->has_any_data()); 180 181 $data = $writer->get_data(); 182 $this->assertCount(2, $data->submissions); 183 } 184 185 /** 186 * Test for provider::export_user_data(). 187 */ 188 public function test_export_for_context_tool_types() { 189 $this->resetAfterTest(); 190 191 $course1 = $this->getDataGenerator()->create_course(); 192 $course2 = $this->getDataGenerator()->create_course(); 193 194 // Create a user which will make a tool type. 195 $user = $this->getDataGenerator()->create_user(); 196 $this->setUser($user); 197 198 // Create a user that will not make a tool type. 199 $this->getDataGenerator()->create_user(); 200 201 $type = new stdClass(); 202 $type->baseurl = 'http://moodle.org'; 203 $type->course = $course1->id; 204 lti_add_type($type, new stdClass()); 205 206 $type = new stdClass(); 207 $type->baseurl = 'http://moodle.org'; 208 $type->course = $course1->id; 209 lti_add_type($type, new stdClass()); 210 211 $type = new stdClass(); 212 $type->baseurl = 'http://moodle.org'; 213 $type->course = $course2->id; 214 lti_add_type($type, new stdClass()); 215 216 // Export all of the data for the context. 217 $coursecontext = context_course::instance($course1->id); 218 $this->export_context_data_for_user($user->id, $coursecontext, 'mod_lti'); 219 $writer = \core_privacy\local\request\writer::with_context($coursecontext); 220 221 $this->assertTrue($writer->has_any_data()); 222 223 $data = $writer->get_data(); 224 $this->assertCount(2, $data->lti_types); 225 226 $coursecontext = context_course::instance($course2->id); 227 $this->export_context_data_for_user($user->id, $coursecontext, 'mod_lti'); 228 $writer = \core_privacy\local\request\writer::with_context($coursecontext); 229 230 $this->assertTrue($writer->has_any_data()); 231 232 $data = $writer->get_data(); 233 $this->assertCount(1, $data->lti_types); 234 } 235 236 /** 237 * Test for provider::export_user_data(). 238 */ 239 public function test_export_for_context_tool_proxies() { 240 $this->resetAfterTest(); 241 242 // Create a user that will not make a tool proxy. 243 $user = $this->getDataGenerator()->create_user(); 244 $this->setUser($user); 245 246 $toolproxy = new stdClass(); 247 $toolproxy->createdby = $user; 248 lti_add_tool_proxy($toolproxy); 249 250 // Export all of the data for the context. 251 $systemcontext = context_system::instance(); 252 $this->export_context_data_for_user($user->id, $systemcontext, 'mod_lti'); 253 $writer = \core_privacy\local\request\writer::with_context($systemcontext); 254 255 $this->assertTrue($writer->has_any_data()); 256 257 $data = $writer->get_data(); 258 $this->assertCount(1, $data->lti_tool_proxies); 259 } 260 261 /** 262 * Test for provider::delete_data_for_all_users_in_context(). 263 */ 264 public function test_delete_data_for_all_users_in_context() { 265 global $DB; 266 267 $this->resetAfterTest(); 268 269 $course = $this->getDataGenerator()->create_course(); 270 271 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 272 273 // Create users that will make submissions. 274 $user1 = $this->getDataGenerator()->create_user(); 275 $user2 = $this->getDataGenerator()->create_user(); 276 277 $this->create_lti_submission($lti->id, $user1->id); 278 $this->create_lti_submission($lti->id, $user2->id); 279 280 // Before deletion, we should have 2 responses. 281 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id]); 282 $this->assertEquals(2, $count); 283 284 // Delete data based on context. 285 $cmcontext = context_module::instance($lti->cmid); 286 provider::delete_data_for_all_users_in_context($cmcontext); 287 288 // After deletion, the lti submissions for that lti activity should have been deleted. 289 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id]); 290 $this->assertEquals(0, $count); 291 } 292 293 /** 294 * Test for provider::delete_data_for_user(). 295 */ 296 public function test_delete_data_for_user() { 297 global $DB; 298 299 $this->resetAfterTest(); 300 301 $course = $this->getDataGenerator()->create_course(); 302 303 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 304 305 // Create users that will make submissions. 306 $user1 = $this->getDataGenerator()->create_user(); 307 $user2 = $this->getDataGenerator()->create_user(); 308 309 $this->create_lti_submission($lti->id, $user1->id); 310 $this->create_lti_submission($lti->id, $user2->id); 311 312 // Before deletion we should have 2 responses. 313 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id]); 314 $this->assertEquals(2, $count); 315 316 $context = \context_module::instance($lti->cmid); 317 $contextlist = new \core_privacy\local\request\approved_contextlist($user1, 'lti', 318 [context_system::instance()->id, $context->id]); 319 provider::delete_data_for_user($contextlist); 320 321 // After deletion the lti submission for the first user should have been deleted. 322 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id, 'userid' => $user1->id]); 323 $this->assertEquals(0, $count); 324 325 // Check the submission for the other user is still there. 326 $ltisubmission = $DB->get_records('lti_submission'); 327 $this->assertCount(1, $ltisubmission); 328 $lastsubmission = reset($ltisubmission); 329 $this->assertEquals($user2->id, $lastsubmission->userid); 330 } 331 332 /** 333 * Test for provider::delete_data_for_users(). 334 */ 335 public function test_delete_data_for_users() { 336 global $DB; 337 $component = 'mod_lti'; 338 339 $this->resetAfterTest(); 340 341 $course = $this->getDataGenerator()->create_course(); 342 343 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id)); 344 345 // Create users that will make submissions. 346 $user1 = $this->getDataGenerator()->create_user(); 347 $user2 = $this->getDataGenerator()->create_user(); 348 $user3 = $this->getDataGenerator()->create_user(); 349 350 $this->create_lti_submission($lti->id, $user1->id); 351 $this->create_lti_submission($lti->id, $user2->id); 352 $this->create_lti_submission($lti->id, $user3->id); 353 354 // Before deletion we should have 2 responses. 355 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id]); 356 $this->assertEquals(3, $count); 357 358 $context = \context_module::instance($lti->cmid); 359 $approveduserids = [$user1->id, $user2->id]; 360 $approvedlist = new core_privacy\local\request\approved_userlist($context, $component, $approveduserids); 361 provider::delete_data_for_users($approvedlist); 362 363 // After deletion the lti submission for the first two users should have been deleted. 364 list($insql, $inparams) = $DB->get_in_or_equal($approveduserids, SQL_PARAMS_NAMED); 365 $sql = "ltiid = :ltiid AND userid {$insql}"; 366 $params = array_merge($inparams, ['ltiid' => $lti->id]); 367 $count = $DB->count_records_select('lti_submission', $sql, $params); 368 $this->assertEquals(0, $count); 369 370 // Check the submission for the third user is still there. 371 $ltisubmission = $DB->get_records('lti_submission'); 372 $this->assertCount(1, $ltisubmission); 373 $lastsubmission = reset($ltisubmission); 374 $this->assertEquals($user3->id, $lastsubmission->userid); 375 } 376 377 /** 378 * Mimicks the creation of an LTI submission. 379 * 380 * There is no API we can use to insert an LTI submission, so we 381 * will simply insert directly into the database. 382 * 383 * @param int $ltiid 384 * @param int $userid 385 */ 386 protected function create_lti_submission(int $ltiid, int $userid) { 387 global $DB; 388 389 $ltisubmissiondata = [ 390 'ltiid' => $ltiid, 391 'userid' => $userid, 392 'datesubmitted' => time(), 393 'dateupdated' => time(), 394 'gradepercent' => 65, 395 'originalgrade' => 70, 396 'launchid' => 3, 397 'state' => 1 398 ]; 399 400 $DB->insert_record('lti_submission', $ltisubmissiondata); 401 } 402 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body