MDL-61920 mod_lti: implement privacy provider
[moodle.git] / mod / lti / tests / privacy_provider_test.php
CommitLineData
3467e8ce
MN
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
25use core_privacy\local\metadata\collection;
26use mod_lti\privacy\provider;
27
28defined('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 */
37class 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(3, $itemcollection);
47
48 $ltisubmissiontable = array_shift($itemcollection);
49 $this->assertEquals('lti_submission', $ltisubmissiontable->get_name());
50
51 $ltitoolproxies = array_shift($itemcollection);
52 $this->assertEquals('lti_tool_proxies', $ltitoolproxies->get_name());
53
54 $ltitypestable = array_shift($itemcollection);
55 $this->assertEquals('lti_types', $ltitypestable->get_name());
56
57 $privacyfields = $ltisubmissiontable->get_privacy_fields();
58 $this->assertArrayHasKey('userid', $privacyfields);
59 $this->assertArrayHasKey('datesubmitted', $privacyfields);
60 $this->assertArrayHasKey('dateupdated', $privacyfields);
61 $this->assertArrayHasKey('gradepercent', $privacyfields);
62 $this->assertArrayHasKey('originalgrade', $privacyfields);
63 $this->assertEquals('privacy:metadata:lti_submission', $ltisubmissiontable->get_summary());
64
65 $privacyfields = $ltitoolproxies->get_privacy_fields();
66 $this->assertArrayHasKey('name', $privacyfields);
67 $this->assertArrayHasKey('createdby', $privacyfields);
68 $this->assertArrayHasKey('timecreated', $privacyfields);
69 $this->assertArrayHasKey('timemodified', $privacyfields);
70 $this->assertEquals('privacy:metadata:lti_tool_proxies', $ltitoolproxies->get_summary());
71
72 $privacyfields = $ltitypestable->get_privacy_fields();
73 $this->assertArrayHasKey('name', $privacyfields);
74 $this->assertArrayHasKey('createdby', $privacyfields);
75 $this->assertArrayHasKey('timecreated', $privacyfields);
76 $this->assertArrayHasKey('timemodified', $privacyfields);
77 $this->assertEquals('privacy:metadata:lti_types', $ltitypestable->get_summary());
78 }
79
80 /**
81 * Test for provider::get_contexts_for_userid().
82 */
83 public function test_get_contexts_for_userid() {
84 $this->resetAfterTest();
85
86 $course = $this->getDataGenerator()->create_course();
87
88 // The LTI activity the user will have submitted something for.
89 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id));
90
91 // Another LTI activity that has no user activity.
92 $this->getDataGenerator()->create_module('lti', array('course' => $course->id));
93
94 // Create a user which will make a submission.
95 $user = $this->getDataGenerator()->create_user();
96
97 $this->create_lti_submission($lti->id, $user->id);
98
99 // Check the contexts supplied are correct.
100 $contextlist = provider::get_contexts_for_userid($user->id);
101 $this->assertCount(2, $contextlist);
102
103 $contextformodule = $contextlist->current();
104 $cmcontext = context_module::instance($lti->cmid);
105 $this->assertEquals($cmcontext->id, $contextformodule->id);
106
107 $contextlist->next();
108 $contextforsystem = $contextlist->current();
109 $this->assertEquals(SYSCONTEXTID, $contextforsystem->id);
110 }
111
112 /**
113 * Test for provider::export_user_data().
114 */
115 public function test_export_for_context_submissions() {
116 $this->resetAfterTest();
117
118 $course = $this->getDataGenerator()->create_course();
119
120 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id));
121
122 // Create users which will make submissions.
123 $user1 = $this->getDataGenerator()->create_user();
124 $user2 = $this->getDataGenerator()->create_user();
125
126 $this->create_lti_submission($lti->id, $user1->id);
127 $this->create_lti_submission($lti->id, $user1->id);
128 $this->create_lti_submission($lti->id, $user2->id);
129
130 // Export all of the data for the context for user 1.
131 $cmcontext = context_module::instance($lti->cmid);
132 $this->export_context_data_for_user($user1->id, $cmcontext, 'mod_lti');
133 $writer = \core_privacy\local\request\writer::with_context($cmcontext);
134
135 $this->assertTrue($writer->has_any_data());
136
137 $data = $writer->get_data();
138 $this->assertCount(2, $data->submissions);
139 }
140
141 /**
142 * Test for provider::export_user_data().
143 */
144 public function test_export_for_context_tool_types() {
145 $this->resetAfterTest();
146
147 $course1 = $this->getDataGenerator()->create_course();
148 $course2 = $this->getDataGenerator()->create_course();
149
150 // Create a user which will make a tool type.
151 $user = $this->getDataGenerator()->create_user();
152 $this->setUser($user);
153
154 // Create a user that will not make a tool type.
155 $this->getDataGenerator()->create_user();
156
157 $type = new stdClass();
158 $type->baseurl = 'http://moodle.org';
159 $type->course = $course1->id;
160 lti_add_type($type, new stdClass());
161
162 $type = new stdClass();
163 $type->baseurl = 'http://moodle.org';
164 $type->course = $course1->id;
165 lti_add_type($type, new stdClass());
166
167 $type = new stdClass();
168 $type->baseurl = 'http://moodle.org';
169 $type->course = $course2->id;
170 lti_add_type($type, new stdClass());
171
172 // Export all of the data for the context.
173 $coursecontext = context_course::instance($course1->id);
174 $this->export_context_data_for_user($user->id, $coursecontext, 'mod_lti');
175 $writer = \core_privacy\local\request\writer::with_context($coursecontext);
176
177 $this->assertTrue($writer->has_any_data());
178
179 $data = $writer->get_data();
180 $this->assertCount(2, $data->lti_types);
181
182 $coursecontext = context_course::instance($course2->id);
183 $this->export_context_data_for_user($user->id, $coursecontext, 'mod_lti');
184 $writer = \core_privacy\local\request\writer::with_context($coursecontext);
185
186 $this->assertTrue($writer->has_any_data());
187
188 $data = $writer->get_data();
189 $this->assertCount(1, $data->lti_types);
190 }
191
192 /**
193 * Test for provider::export_user_data().
194 */
195 public function test_export_for_context_tool_proxies() {
196 $this->resetAfterTest();
197
198 // Create a user that will not make a tool proxy.
199 $user = $this->getDataGenerator()->create_user();
200 $this->setUser($user);
201
202 $toolproxy = new stdClass();
203 $toolproxy->createdby = $user;
204 lti_add_tool_proxy($toolproxy);
205
206 // Export all of the data for the context.
207 $systemcontext = context_system::instance();
208 $this->export_context_data_for_user($user->id, $systemcontext, 'mod_lti');
209 $writer = \core_privacy\local\request\writer::with_context($systemcontext);
210
211 $this->assertTrue($writer->has_any_data());
212
213 $data = $writer->get_data();
214 $this->assertCount(1, $data->lti_tool_proxies);
215 }
216
217 /**
218 * Test for provider::delete_data_for_all_users_in_context().
219 */
220 public function test_delete_data_for_all_users_in_context() {
221 global $DB;
222
223 $this->resetAfterTest();
224
225 $course = $this->getDataGenerator()->create_course();
226
227 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id));
228
229 // Create users that will make submissions.
230 $user1 = $this->getDataGenerator()->create_user();
231 $user2 = $this->getDataGenerator()->create_user();
232
233 $this->create_lti_submission($lti->id, $user1->id);
234 $this->create_lti_submission($lti->id, $user2->id);
235
236 // Before deletion, we should have 2 responses.
237 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id]);
238 $this->assertEquals(2, $count);
239
240 // Delete data based on context.
241 $cmcontext = context_module::instance($lti->cmid);
242 provider::delete_data_for_all_users_in_context($cmcontext);
243
244 // After deletion, the lti submissions for that lti activity should have been deleted.
245 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id]);
246 $this->assertEquals(0, $count);
247 }
248
249 /**
250 * Test for provider::delete_data_for_user().
251 */
252 public function test_delete_data_for_user() {
253 global $DB;
254
255 $this->resetAfterTest();
256
257 $course = $this->getDataGenerator()->create_course();
258
259 $lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id));
260
261 // Create users that will make submissions.
262 $user1 = $this->getDataGenerator()->create_user();
263 $user2 = $this->getDataGenerator()->create_user();
264
265 $this->create_lti_submission($lti->id, $user1->id);
266 $this->create_lti_submission($lti->id, $user2->id);
267
268 // Before deletion we should have 2 responses.
269 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id]);
270 $this->assertEquals(2, $count);
271
272 $context = \context_module::instance($lti->cmid);
273 $contextlist = new \core_privacy\local\request\approved_contextlist($user1, 'lti',
274 [$context->id]);
275 provider::delete_data_for_user($contextlist);
276
277 // After deletion the lti submission for the first user should have been deleted.
278 $count = $DB->count_records('lti_submission', ['ltiid' => $lti->id, 'userid' => $user1->id]);
279 $this->assertEquals(0, $count);
280
281 // Check the submission for the other user is still there.
282 $ltisubmission = $DB->get_records('lti_submission');
283 $this->assertCount(1, $ltisubmission);
284 $lastsubmission = reset($ltisubmission);
285 $this->assertEquals($user2->id, $lastsubmission->userid);
286 }
287
288 /**
289 * Mimicks the creation of an LTI submission.
290 *
291 * There is no API we can use to insert an LTI submission, so we
292 * will simply insert directly into the database.
293 *
294 * @param int $ltiid
295 * @param int $userid
296 */
297 protected function create_lti_submission(int $ltiid, int $userid) {
298 global $DB;
299
300 $ltisubmissiondata = [
301 'ltiid' => $ltiid,
302 'userid' => $userid,
303 'datesubmitted' => time(),
304 'dateupdated' => time(),
305 'gradepercent' => 65,
306 'originalgrade' => 70,
307 'launchid' => 3,
308 'state' => 1
309 ];
310
311 $DB->insert_record('lti_submission', $ltisubmissiondata);
312 }
313}