MDL-63664 tool_policy: Add support for removal of context users
[moodle.git] / admin / tool / policy / tests / privacy_provider_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/>.
17 /**
18  * Privacy provider tests.
19  *
20  * @package    tool_policy
21  * @category   test
22  * @copyright  2018 Sara Arjona <sara@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 use core_privacy\local\metadata\collection;
27 use tool_policy\privacy\provider;
28 use tool_policy\api;
29 use tool_policy\policy_version;
30 use core_privacy\local\request\approved_contextlist;
31 use core_privacy\local\request\writer;
33 defined('MOODLE_INTERNAL') || die();
35 /**
36  * Privacy provider tests class.
37  *
38  * @copyright  2018 Sara Arjona <sara@moodle.com>
39  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40  */
41 class tool_policy_privacy_provider_testcase extends \core_privacy\tests\provider_testcase {
42     /** @var stdClass The user object. */
43     protected $user;
45     /** @var stdClass The manager user object. */
46     protected $manager;
48 /** @var context_system The system context instance. */
49     protected $syscontext;
51     /**
52      * Setup function. Will create a user.
53      */
54     protected function setUp() {
55         $this->resetAfterTest();
57         $generator = $this->getDataGenerator();
58         $this->user = $generator->create_user();
60         // Create manager user.
61         $this->manager = $generator->create_user();
62         $this->syscontext = context_system::instance();
63         $rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
64         assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $this->syscontext->id);
65         assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $this->syscontext->id);
66         role_assign($rolemanagerid, $this->manager->id, $this->syscontext->id);
67         accesslib_clear_all_caches_for_unit_testing();
68     }
70     /**
71      * Test getting the context for the user ID related to this plugin.
72      */
73     public function test_get_contexts_for_userid() {
74         global $CFG;
76         // When there are no policies or agreements context list is empty.
77         $contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->manager->id);
78         $this->assertEmpty($contextlist);
79         $contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
80         $this->assertEmpty($contextlist);
82         // Create a policy.
83         $this->setUser($this->manager);
84         $CFG->sitepolicyhandler = 'tool_policy';
85         $policy = $this->add_policy();
86         api::make_current($policy->get('id'));
88         // After creating a policy, there should be manager context.
89         $contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->manager->id);
90         $this->assertEquals(1, $contextlist->count());
92         // But when there are no agreements, user context list is empty.
93         $contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
94         $this->assertEmpty($contextlist);
96         // Agree to the policy.
97         $this->setUser($this->user);
98         api::accept_policies([$policy->get('id')]);
100         // There should be user context.
101         $contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
102         $this->assertEquals(1, $contextlist->count());
103     }
105     /**
106      * Test getting the user IDs within the context related to this plugin.
107      */
108     public function test_get_users_in_context() {
109         global $CFG;
110         $component = 'tool_policy';
112         // System context should have nothing before a policy is added.
113         $userlist = new \core_privacy\local\request\userlist($this->syscontext, $component);
114         provider::get_users_in_context($userlist);
115         $this->assertEmpty($userlist);
117         // Create parent and child users.
118         $generator = $this->getDataGenerator();
119         $parentuser = $generator->create_user();
120         $childuser = $generator->create_user();
122         // Fetch relevant contexts.
123         $managercontext = \context_user::instance($this->manager->id);
124         $usercontext = $managercontext = \context_user::instance($this->user->id);
125         $parentcontext = $managercontext = \context_user::instance($parentuser->id);
126         $childcontext = $managercontext = \context_user::instance($childuser->id);
128         // Assign parent to accept on behalf of the child.
129         $roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
130         assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $this->syscontext->id);
131         role_assign($roleparentid, $parentuser->id, $childcontext->id);
133         // Create a policy.
134         $this->setUser($this->manager);
135         $CFG->sitepolicyhandler = 'tool_policy';
136         $policy = $this->add_policy();
137         api::make_current($policy->get('id'));
139         // Manager should exist in system context now they have created a policy.
140         $userlist = new \core_privacy\local\request\userlist($this->syscontext, $component);
141         provider::get_users_in_context($userlist);
142         $this->assertCount(1, $userlist);
143         $this->assertEquals([$this->manager->id], $userlist->get_userids());
145         // User contexts should be empty before policy acceptances.
146         $userlist = new \core_privacy\local\request\userlist($usercontext, $component);
147         provider::get_users_in_context($userlist);
148         $this->assertEmpty($userlist);
150         $userlist = new \core_privacy\local\request\userlist($parentcontext, $component);
151         provider::get_users_in_context($userlist);
152         $this->assertEmpty($userlist);
154         $userlist = new \core_privacy\local\request\userlist($childcontext, $component);
155         provider::get_users_in_context($userlist);
156         $this->assertEmpty($userlist);
158         // User accepts policy, parent accepts on behalf of child only.
159         $this->setUser($this->user);
160         api::accept_policies([$policy->get('id')]);
162         $this->setUser($parentuser);
163         api::accept_policies([$policy->get('id')], $childuser->id);
165         // Ensure user is fetched within its user context.
166         $userlist = new \core_privacy\local\request\userlist($usercontext, $component);
167         provider::get_users_in_context($userlist);
168         $this->assertCount(1, $userlist);
169         $this->assertEquals([$this->user->id], $userlist->get_userids());
171         // Ensure parent and child are both found within child's user context.
172         $userlist = new \core_privacy\local\request\userlist($childcontext, $component);
173         provider::get_users_in_context($userlist);
174         $this->assertCount(2, $userlist);
175         $expected = [$parentuser->id, $childuser->id];
176         $actual = $userlist->get_userids();
177         sort($expected);
178         sort($actual);
179         $this->assertEquals($expected, $actual);
181         // Parent has not accepted for itself, so should not be found within its user context.
182         $userlist = new \core_privacy\local\request\userlist($parentcontext, $component);
183         provider::get_users_in_context($userlist);
184         $this->assertCount(0, $userlist);
185     }
187     public function test_export_agreements() {
188         global $CFG;
190         $otheruser = $this->getDataGenerator()->create_user();
191         $otherusercontext = \context_user::instance($otheruser->id);
193         // Create policies and agree to them as manager.
194         $this->setUser($this->manager);
195         $managercontext = \context_user::instance($this->manager->id);
196         $systemcontext = \context_system::instance();
197         $agreementsubcontext = [
198             get_string('privacyandpolicies', 'admin'),
199             get_string('useracceptances', 'tool_policy')
200         ];
201         $versionsubcontext = [
202             get_string('policydocuments', 'tool_policy')
203         ];
204         $CFG->sitepolicyhandler = 'tool_policy';
205         $policy1 = $this->add_policy();
206         api::make_current($policy1->get('id'));
207         $policy2 = $this->add_policy();
208         api::make_current($policy2->get('id'));
209         api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
211         // Agree to the policies for oneself.
212         $this->setUser($this->user);
213         $usercontext = \context_user::instance($this->user->id);
214         api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
216         // Request export for this user.
217         $contextlist = provider::get_contexts_for_userid($this->user->id);
218         $this->assertCount(1, $contextlist);
219         $this->assertEquals([$usercontext->id], $contextlist->get_contextids());
221         $approvedcontextlist = new approved_contextlist($this->user, 'tool_policy', [$usercontext->id]);
222         provider::export_user_data($approvedcontextlist);
224         // User can not see manager's agreements but can see his own.
225         $writer = writer::with_context($managercontext);
226         $this->assertFalse($writer->has_any_data());
228         $writer = writer::with_context($usercontext);
229         $this->assertTrue($writer->has_any_data());
231         // Test policy 1.
232         $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
233         $datauser = $writer->get_data($subcontext);
234         $this->assertEquals($policy1->get('name'), $datauser->name);
235         $this->assertEquals($this->user->id, $datauser->agreedby);
236         $this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
237         $this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
239         // Test policy 2.
240         $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
241         $datauser = $writer->get_data($subcontext);
242         $this->assertEquals($policy2->get('name'), $datauser->name);
243         $this->assertEquals($this->user->id, $datauser->agreedby);
244         $this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
245         $this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
246     }
248     public function test_export_agreements_for_other() {
249         global $CFG;
251         $managercontext = \context_user::instance($this->manager->id);
252         $systemcontext = \context_system::instance();
253         $usercontext = \context_user::instance($this->user->id);
255         // Create policies and agree to them as manager.
256         $this->setUser($this->manager);
257         $agreementsubcontext = [
258             get_string('privacyandpolicies', 'admin'),
259             get_string('useracceptances', 'tool_policy')
260         ];
261         $versionsubcontext = [
262             get_string('policydocuments', 'tool_policy')
263         ];
264         $CFG->sitepolicyhandler = 'tool_policy';
265         $policy1 = $this->add_policy();
266         api::make_current($policy1->get('id'));
267         $policy2 = $this->add_policy();
268         api::make_current($policy2->get('id'));
269         api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
271         // Agree to the other user's policies.
272         api::accept_policies([$policy1->get('id'), $policy2->get('id')], $this->user->id, 'My note');
274         // Request export for the manager.
275         $contextlist = provider::get_contexts_for_userid($this->manager->id);
276         $this->assertCount(3, $contextlist);
277         $this->assertEquals(
278             [$managercontext->id, $usercontext->id, $systemcontext->id],
279             $contextlist->get_contextids(),
280             '',
281             0.0,
282             1,
283             true
284         );
286         $approvedcontextlist = new approved_contextlist($this->user, 'tool_policy', [$usercontext->id]);
287         provider::export_user_data($approvedcontextlist);
289         // The user context has data.
290         $writer = writer::with_context($usercontext);
291         $this->assertTrue($writer->has_any_data());
293         // Test policy 1.
294         $writer = writer::with_context($usercontext);
295         $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
296         $datauser = $writer->get_data($subcontext);
297         $this->assertEquals($policy1->get('name'), $datauser->name);
298         $this->assertEquals($this->manager->id, $datauser->agreedby);
299         $this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
300         $this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
302         // Test policy 2.
303         $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
304         $datauser = $writer->get_data($subcontext);
305         $this->assertEquals($policy2->get('name'), $datauser->name);
306         $this->assertEquals($this->manager->id, $datauser->agreedby);
307         $this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
308         $this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
309     }
311     public function test_export_created_policies() {
312         global $CFG;
314         // Create policies and agree to them as manager.
315         $this->setUser($this->manager);
316         $managercontext = \context_user::instance($this->manager->id);
317         $systemcontext = \context_system::instance();
318         $agreementsubcontext = [
319             get_string('privacyandpolicies', 'admin'),
320             get_string('useracceptances', 'tool_policy')
321         ];
322         $versionsubcontext = [
323             get_string('policydocuments', 'tool_policy')
324         ];
325         $CFG->sitepolicyhandler = 'tool_policy';
326         $policy1 = $this->add_policy();
327         api::make_current($policy1->get('id'));
328         $policy2 = $this->add_policy();
329         api::make_current($policy2->get('id'));
330         api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
332         // Agree to the policies for oneself.
333         $contextlist = provider::get_contexts_for_userid($this->manager->id);
334         $this->assertCount(2, $contextlist);
335         $this->assertEquals([$managercontext->id, $systemcontext->id], $contextlist->get_contextids(), '', 0.0, 1, true);
337         $approvedcontextlist = new approved_contextlist($this->manager, 'tool_policy', $contextlist->get_contextids());
338         provider::export_user_data($approvedcontextlist);
340         // User has agreed to policies.
341         $writer = writer::with_context($managercontext);
342         $this->assertTrue($writer->has_any_data());
344         // Test policy 1.
345         $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
346         $datauser = $writer->get_data($subcontext);
347         $this->assertEquals($policy1->get('name'), $datauser->name);
348         $this->assertEquals($this->manager->id, $datauser->agreedby);
349         $this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
350         $this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
352         // Test policy 2.
353         $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
354         $datauser = $writer->get_data($subcontext);
355         $this->assertEquals($policy2->get('name'), $datauser->name);
356         $this->assertEquals($this->manager->id, $datauser->agreedby);
357         $this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
358         $this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
360         // User can see policy documents.
361         $writer = writer::with_context($systemcontext);
362         $this->assertTrue($writer->has_any_data());
364         $subcontext = array_merge($versionsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
365         $dataversion = $writer->get_data($subcontext);
366         $this->assertEquals($policy1->get('name'), $dataversion->name);
367         $this->assertEquals(get_string('yes'), $dataversion->createdbyme);
369         $subcontext = array_merge($versionsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
370         $dataversion = $writer->get_data($subcontext);
371         $this->assertEquals($policy2->get('name'), $dataversion->name);
372         $this->assertEquals(get_string('yes'), $dataversion->createdbyme);
373     }
375     /**
376      * Helper method that creates a new policy for testing
377      *
378      * @param array $params
379      * @return policy_version
380      */
381     protected function add_policy($params = []) {
382         static $counter = 0;
383         $counter++;
385         $defaults = [
386             'name' => 'Policy '.$counter,
387             'summary_editor' => ['text' => "P$counter summary", 'format' => FORMAT_HTML, 'itemid' => 0],
388             'content_editor' => ['text' => "P$counter content", 'format' => FORMAT_HTML, 'itemid' => 0],
389         ];
391         $params = (array)$params + $defaults;
392         $formdata = \tool_policy\api::form_policydoc_data(new policy_version(0));
393         foreach ($params as $key => $value) {
394             $formdata->$key = $value;
395         }
396         return api::form_policydoc_add($formdata);
397     }