MDL-61943 core_role: Add privacy implementation for core_role
[moodle.git] / admin / roles / tests / privacy_test.php
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  * Privacy test for core_role
18  *
19  * @package    core_role
20  * @category   test
21  * @copyright  2018 Carlos Escobedo <carlos@moodle.com>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
24 defined('MOODLE_INTERNAL') || die();
25 use \core_role\privacy\provider;
26 use \core_privacy\local\request\approved_contextlist;
27 use \core_privacy\local\request\writer;
28 use \core_privacy\tests\provider_testcase;
29 use \core_privacy\local\request\transform;
30 use \tool_cohortroles\api;
32 /**
33  * Privacy test for core_role
34  *
35  * @copyright  2018 Carlos Escobedo <carlos@moodle.com>
36  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class core_role_privacy_testcase extends provider_testcase {
39     /**
40      * Test to check export_user_preferences.
41      * returns user preferences data.
42      */
43     public function test_export_user_preferences() {
44         $this->resetAfterTest();
45         $this->setAdminUser();
46         $user = $this->getDataGenerator()->create_user();
47         $this->setUser($user);
48         $showadvanced = 1;
49         set_user_preference('definerole_showadvanced', $showadvanced);
50         provider::export_user_preferences($user->id);
51         $writer = writer::with_context(\context_system::instance());
52         $prefs = $writer->get_user_preferences('core_role');
53         $this->assertEquals(transform::yesno($showadvanced), transform::yesno($prefs->definerole_showadvanced->value));
54         $this->assertEquals(get_string('privacy:metadata:preference:showadvanced', 'core_role'),
55             $prefs->definerole_showadvanced->description);
56     }
57     /**
58      * Check all contexts are returned if there is any user data for this user.
59      */
60     public function test_get_contexts_for_userid() {
61         global $DB;
63         $this->resetAfterTest();
64         $this->setAdminUser();
65         $user = $this->getDataGenerator()->create_user();
66         $this->assertEmpty(provider::get_contexts_for_userid($user->id));
68         $user2 = $this->getDataGenerator()->create_user();
69         $usercontext2 = \context_user::instance($user2->id);
70         $course = $this->getDataGenerator()->create_course();
71         $course2 = $this->getDataGenerator()->create_course();
72         $coursecat = $this->getDataGenerator()->create_category();
73         $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
74         $cmcontext = \context_module::instance($cm->cmid);
75         $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
76         $cmcontext2 = \context_module::instance($page->cmid);
77         $coursecontext = \context_course::instance($course->id);
78         $coursecontext2 = \context_course::instance($course2->id);
79         $coursecatcontext = \context_coursecat::instance($coursecat->id);
80         $systemcontext = \context_system::instance();
81         $block = $this->getDataGenerator()->create_block('online_users');
82         $blockcontext = \context_block::instance($block->id);
84         $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
85         $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
87         // Role assignments, where the user is assigned.
88         role_assign($student->id, $user->id, $cmcontext2->id);
89         role_assign($student->id, $user->id, $coursecontext2->id);
90         role_assign($student->id, $user->id, $blockcontext->id);
91         role_assign($manager->id, $user->id, $usercontext2->id);
92         // Role assignments, where the user makes assignments.
93         $this->setUser($user);
94         role_assign($student->id, $user2->id, $coursecontext->id);
95         role_assign($manager->id, $user2->id, $coursecatcontext->id);
96         role_assign($manager->id, $user2->id, $systemcontext->id);
98         // Role capabilities.
99         $this->setUser($user);
100         $result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $cmcontext->id);
102         $contextlist = provider::get_contexts_for_userid($user->id)->get_contextids();
103         $this->assertCount(8, $contextlist);
104         $this->assertTrue(in_array($cmcontext->id, $contextlist));
105     }
107     /**
108      * Test that user data is exported correctly.
109      */
110     public function test_export_user_data() {
111         global $DB;
113         $this->resetAfterTest();
114         $this->setAdminUser();
115         $user = $this->getDataGenerator()->create_user();
116         $user2 = $this->getDataGenerator()->create_user();
117         $usercontext2 = \context_user::instance($user2->id);
118         $course = $this->getDataGenerator()->create_course();
119         $course2 = $this->getDataGenerator()->create_course();
120         $coursecat = $this->getDataGenerator()->create_category();
121         $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
122         $cmcontext = \context_module::instance($cm->cmid);
123         $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
124         $cmcontext2 = \context_module::instance($page->cmid);
125         $coursecontext = \context_course::instance($course->id);
126         $coursecontext2 = \context_course::instance($course2->id);
127         $coursecatcontext = \context_coursecat::instance($coursecat->id);
128         $systemcontext = \context_system::instance();
129         $block = $this->getDataGenerator()->create_block('online_users');
130         $blockcontext = \context_block::instance($block->id);
132         $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
133         $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
134         $rolesnames = self::get_roles_name();
136         $subcontextstudent = [
137             get_string('privacy:metadata:role_assignments', 'core_role'),
138             $rolesnames[$student->id]
139         ];
140         $subcontextmanager = [
141             get_string('privacy:metadata:role_assignments', 'core_role'),
142             $rolesnames[$manager->id]
143         ];
144         $subcontextrc = [
145             get_string('privacy:metadata:role_capabilities', 'core_role'),
146             $rolesnames[$student->id]
147         ];
149         // Test over role assignments.
150         // Where the user is assigned.
151         role_assign($student->id, $user->id, $cmcontext2->id);
152         role_assign($student->id, $user->id, $coursecontext2->id);
153         role_assign($student->id, $user->id, $blockcontext->id);
154         role_assign($manager->id, $user->id, $usercontext2->id);
155         // Where the user makes assignments.
156         $this->setUser($user);
157         role_assign($manager->id, $user2->id, $coursecatcontext->id);
158         role_assign($manager->id, $user2->id, $systemcontext->id);
160         // Test overridable roles in module, course, category, user, system and block.
161         assign_capability('moodle/backup:backupactivity', CAP_ALLOW, $student->id, $cmcontext->id, true);
162         assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $coursecontext->id, true);
163         assign_capability('moodle/category:manage', CAP_ALLOW, $student->id, $coursecatcontext->id, true);
164         assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $systemcontext->id, true);
165         assign_capability('moodle/block:edit', CAP_ALLOW, $student->id, $blockcontext->id, true);
166         assign_capability('moodle/competency:evidencedelete', CAP_ALLOW, $student->id, $usercontext2->id, true);
168         // Retrieve the user's context ids.
169         $contextlist = provider::get_contexts_for_userid($user->id);
170         $approvedcontextlist = new approved_contextlist($user, 'core_role', $contextlist->get_contextids());
172         $strpermissions = array(
173             CAP_INHERIT => get_string('inherit', 'role'),
174             CAP_ALLOW => get_string('allow', 'role'),
175             CAP_PREVENT => get_string('prevent', 'role'),
176             CAP_PROHIBIT => get_string('prohibit', 'role')
177         );
178         // Retrieve role capabilities and role assignments.
179         provider::export_user_data($approvedcontextlist);
180         foreach ($contextlist as $context) {
181             $writer = writer::with_context($context);
182             $this->assertTrue($writer->has_any_data());
183             if ($context->contextlevel == CONTEXT_MODULE) {
184                 if ($data = $writer->get_data($subcontextstudent)) {
185                     $this->assertEquals($user->id, reset($data)->userid);
186                 }
187                 if ($data = $writer->get_data($subcontextrc)) {
188                     $this->assertEquals('moodle/backup:backupactivity', reset($data)->capability);
189                     $this->assertEquals($strpermissions[CAP_ALLOW], reset($data)->permission);
190                 }
191             }
192             if ($context->contextlevel == CONTEXT_COURSE) {
193                 if ($data = $writer->get_data($subcontextstudent)) {
194                     $this->assertEquals($user->id, reset($data)->userid);
195                 }
196                 if ($data = $writer->get_data($subcontextrc)) {
197                     $this->assertEquals('moodle/backup:backupcourse', reset($data)->capability);
198                 }
199             }
200             if ($context->contextlevel == CONTEXT_COURSECAT) {
201                 if ($data = $writer->get_data($subcontextmanager)) {
202                     $this->assertEquals($user->id, reset($data)->modifierid);
203                 }
204                 if ($data = $writer->get_data($subcontextrc)) {
205                     $this->assertEquals('moodle/category:manage', reset($data)->capability);
206                 }
207             }
208             if ($context->contextlevel == CONTEXT_SYSTEM) {
209                 if ($data = $writer->get_data($subcontextmanager)) {
210                     $this->assertEquals($user->id, reset($data)->modifierid);
211                 }
212                 if ($data = $writer->get_data($subcontextrc)) {
213                     $this->assertEquals('moodle/backup:backupcourse', reset($data)->capability);
214                 }
215             }
216             if ($context->contextlevel == CONTEXT_BLOCK) {
217                 if ($data = $writer->get_data($subcontextstudent)) {
218                     $this->assertEquals($user->id, reset($data)->userid);
219                 }
220                 if ($data = $writer->get_data($subcontextrc)) {
221                     $this->assertEquals('moodle/block:edit', reset($data)->capability);
222                 }
223             }
224             if ($context->contextlevel == CONTEXT_USER) {
225                 if ($data = $writer->get_data($subcontextmanager)) {
226                     $this->assertEquals($user->id, reset($data)->userid);
227                 }
228                 if ($data = $writer->get_data($subcontextrc)) {
229                     $this->assertEquals('moodle/competency:evidencedelete', reset($data)->capability);
230                 }
231             }
232         }
233     }
234     /**
235      * Test for provider::delete_data_for_all_users_in_context().
236      */
237     public function test_delete_data_for_all_users_in_context() {
238         global $DB;
240         $this->resetAfterTest();
241         $this->setAdminUser();
242         $user = $this->getDataGenerator()->create_user();
243         $user2 = $this->getDataGenerator()->create_user();
244         $usercontext2 = \context_user::instance($user2->id);
245         $user3 = $this->getDataGenerator()->create_user();
246         $course = $this->getDataGenerator()->create_course();
247         $coursecontext = \context_course::instance($course->id);
248         $coursecat = $this->getDataGenerator()->create_category();
249         $coursecatcontext = \context_coursecat::instance($coursecat->id);
250         $systemcontext = \context_system::instance();
251         $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
252         $cmcontext = \context_module::instance($cm->cmid);
253         $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
254         $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
255         $block = $this->getDataGenerator()->create_block('online_users');
256         $blockcontext = \context_block::instance($block->id);
258         // Role assignments CONTEXT_COURSE.
259         role_assign($student->id, $user->id, $coursecontext->id);
260         role_assign($student->id, $user2->id, $coursecontext->id);
261         role_assign($student->id, $user3->id, $coursecontext->id);
262         $count = $DB->count_records('role_assignments', ['contextid' => $coursecontext->id]);
263         $this->assertEquals(3, $count);
264         // Role assignments CONTEXT_COURSECAT.
265         role_assign($student->id, $user2->id, $coursecatcontext->id);
266         role_assign($student->id, $user3->id, $coursecatcontext->id);
267         $count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
268         $this->assertEquals(2, $count);
269         // Role assignments CONTEXT_SYSTEM.
270         role_assign($student->id, $user->id, $systemcontext->id);
271         $count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
272         $this->assertEquals(1, $count);
273         // Role assignments CONTEXT_MODULE.
274         role_assign($student->id, $user->id, $cmcontext->id);
275         $count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
276         $this->assertEquals(1, $count);
277         // Role assigments CONTEXT_BLOCK.
278         role_assign($student->id, $user->id, $blockcontext->id);
279         $count = $DB->count_records('role_assignments', ['contextid' => $blockcontext->id]);
280         $this->assertEquals(1, $count);
281         // Role assigments CONTEXT_USER.
282         role_assign($manager->id, $user->id, $usercontext2->id);
283         $count = $DB->count_records('role_assignments', ['contextid' => $usercontext2->id]);
284         $this->assertEquals(1, $count);
286         // Delete data based on CONTEXT_COURSE context.
287         provider::delete_data_for_all_users_in_context($coursecontext);
288         // After deletion, the role_assignments entries for this context should have been deleted.
289         $count = $DB->count_records('role_assignments', ['contextid' => $coursecontext->id]);
290         $this->assertEquals(0, $count);
291         // Check it is not removing data on other contexts.
292         $count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
293         $this->assertEquals(2, $count);
294         $count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
295         $this->assertEquals(1, $count);
296         $count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
297         $this->assertEquals(1, $count);
298         // Delete data based on CONTEXT_COURSECAT context.
299         provider::delete_data_for_all_users_in_context($coursecatcontext);
300         // After deletion, the role_assignments entries for this context should have been deleted.
301         $count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
302         $this->assertEquals(0, $count);
303         // Delete data based on CONTEXT_SYSTEM context.
304         provider::delete_data_for_all_users_in_context($systemcontext);
305         // After deletion, the role_assignments entries for this context should have been deleted.
306         $count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
307         $this->assertEquals(0, $count);
308         // Delete data based on CONTEXT_MODULE context.
309         provider::delete_data_for_all_users_in_context($cmcontext);
310         // After deletion, the role_assignments entries for this context should have been deleted.
311         $count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
312         $this->assertEquals(0, $count);
313         // Delete data based on CONTEXT_BLOCK context.
314         provider::delete_data_for_all_users_in_context($usercontext2);
315         // After deletion, the role_assignments entries for this context should have been deleted.
316         $count = $DB->count_records('role_assignments', ['contextid' => $usercontext2->id]);
317         $this->assertEquals(0, $count);
318     }
319     /**
320      * Test for provider::delete_data_for_user().
321      */
322     public function test_delete_data_for_user() {
323         global $DB;
325         $this->resetAfterTest();
326         $this->setAdminUser();
327         $user = $this->getDataGenerator()->create_user();
328         $user2 = $this->getDataGenerator()->create_user();
329         $usercontext2 = \context_user::instance($user2->id);
330         $user3 = $this->getDataGenerator()->create_user();
331         $usercontext3 = \context_user::instance($user3->id);
332         $course = $this->getDataGenerator()->create_course();
333         $course2 = $this->getDataGenerator()->create_course();
334         $course3 = $this->getDataGenerator()->create_course();
335         $coursecontext = \context_course::instance($course->id);
336         $coursecontext2 = \context_course::instance($course2->id);
337         $coursecontext3 = \context_course::instance($course3->id);
338         $coursecat = $this->getDataGenerator()->create_category();
339         $coursecatcontext = \context_coursecat::instance($coursecat->id);
340         $systemcontext = \context_system::instance();
341         $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
342         $cmcontext = \context_module::instance($cm->cmid);
343         $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
344         $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
345         $block = $this->getDataGenerator()->create_block('online_users');
346         $blockcontext = \context_block::instance($block->id);
348         // Role assignments, Where the user is assigned.
349         role_assign($student->id, $user->id, $coursecontext->id);
350         role_assign($student->id, $user->id, $coursecontext2->id);
351         role_assign($student->id, $user->id, $coursecatcontext->id);
352         role_assign($student->id, $user->id, $cmcontext->id);
353         role_assign($student->id, $user->id, $systemcontext->id);
354         role_assign($student->id, $user->id, $blockcontext->id);
355         role_assign($manager->id, $user->id, $usercontext2->id);
356         role_assign($manager->id, $user->id, $usercontext3->id);
357         $count = $DB->count_records('role_assignments', ['userid' => $user->id]);
358         $this->assertEquals(8, $count);
359         // Role assignments, where the user makes assignments.
360         $this->setUser($user);
361         role_assign($student->id, $user2->id, $coursecontext3->id);
362         role_assign($student->id, $user3->id, $coursecontext3->id);
363         $count = $DB->count_records('role_assignments', ['modifierid' => $user->id]);
364         $this->assertEquals(2, $count);
366         $contextlist = provider::get_contexts_for_userid($user->id);
367         $approvedcontextlist = new approved_contextlist($user, 'core_role', $contextlist->get_contextids());
368         provider::delete_data_for_user($approvedcontextlist);
369         // After deletion, the role_assignments assigned to the user should have been deleted.
370         $count = $DB->count_records('role_assignments', ['userid' => $user->id]);
371         $this->assertEquals(0, $count);
372         // After deletion, the role_assignments assigned by the user should not have been deleted.
373         $count = $DB->count_records('role_assignments', ['modifierid' => $user->id]);
374         $this->assertEquals(2, $count);
375     }
376     /**
377      * Export for a user with a key against a script where no instance is specified.
378      */
379     public function test_export_user_role_to_cohort() {
380         global $DB;
382         $this->resetAfterTest();
383         $this->setAdminUser();
384         // Assign user roles to cohort.
385         $user = $this->getDataGenerator()->create_user();
386         $contextuser = \context_user::instance($user->id);
387         $teacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
388         $cohort = $this->getDataGenerator()->create_cohort();
389         $userassignover = $this->getDataGenerator()->create_user();
390         $contextuserassignover = \context_user::instance($userassignover->id);
391         cohort_add_member($cohort->id, $userassignover->id);
392         $this->setAdminUser();
393         $params = (object) array(
394             'userid' => $user->id,
395             'roleid' => $teacher->id,
396             'cohortid' => $cohort->id
397         );
398         api::create_cohort_role_assignment($params);
399         api::sync_all_cohort_roles();
400         $rolesnames = self::get_roles_name();
401         $subcontextteacher = [
402             get_string('privacy:metadata:role_cohortroles', 'core_role'),
403             $rolesnames[$teacher->id]
404         ];
405         // Test User is assigned role teacher to cohort.
406         provider::export_user_role_to_cohort($user->id);
407         $writer = writer::with_context($contextuserassignover);
408         $this->assertTrue($writer->has_any_data());
409         $exported = $writer->get_related_data($subcontextteacher, 'cohortroles');
410         $this->assertEquals($user->id, reset($exported)->userid);
412         // Test User is member of a cohort which User2 is assigned to role to this cohort.
413         $user2 = $this->getDataGenerator()->create_user();
414         $cohort2 = $this->getDataGenerator()->create_cohort();
415         cohort_add_member($cohort2->id, $user->id);
416         $params = (object) array(
417             'userid' => $user2->id,
418             'roleid' => $teacher->id,
419             'cohortid' => $cohort2->id
420         );
421         api::create_cohort_role_assignment($params);
422         api::sync_all_cohort_roles();
423         provider::export_user_role_to_cohort($user->id);
424         $writer = writer::with_context($contextuser);
425         $this->assertTrue($writer->has_any_data());
426         $exported = $writer->get_related_data($subcontextteacher, 'cohortroles');
427         $this->assertEquals($user2->id, reset($exported)->userid);
428     }
429     /**
430      * Test for provider::delete_user_role_to_cohort().
431      */
432     public function test_delete_user_role_to_cohort() {
433         global $DB;
435         $this->resetAfterTest();
436         $this->setAdminUser();
437         // Assign user roles to cohort.
438         $user = $this->getDataGenerator()->create_user();
439         $user2 = $this->getDataGenerator()->create_user();
440         $user3 = $this->getDataGenerator()->create_user();
441         $user4 = $this->getDataGenerator()->create_user();
442         $teacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
443         $cohort = $this->getDataGenerator()->create_cohort();
444         cohort_add_member($cohort->id, $user2->id);
445         cohort_add_member($cohort->id, $user3->id);
446         cohort_add_member($cohort->id, $user4->id);
447         $this->setAdminUser();
448         $params = (object) array(
449             'userid' => $user->id,
450             'roleid' => $teacher->id,
451             'cohortid' => $cohort->id
452         );
453         api::create_cohort_role_assignment($params);
454         api::sync_all_cohort_roles();
456         $count = $DB->count_records('role_assignments', ['userid' => $user->id, 'component' => 'tool_cohortroles']);
457         $this->assertEquals(3, $count);
459         provider::delete_user_role_to_cohort($user->id);
460         $count = $DB->count_records('role_assignments', ['userid' => $user->id, 'component' => 'tool_cohortroles']);
461         $this->assertEquals(0, $count);
462     }
463     /**
464      * Supoort function to get all the localised roles name
465      * in a simple array for testing.
466      *
467      * @return array Array of name of the roles by roleid.
468      */
469     protected static function get_roles_name() {
470         $roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
471         $rolesnames = array();
472         foreach ($roles as $role) {
473             $rolesnames[$role->id] = $role->localname;
474         }
475         return $rolesnames;
476     }