Skip to content

Commit

Permalink
Merge branch 'MDL-63664-35' of git://github.com/mickhawkins/moodle in…
Browse files Browse the repository at this point in the history
…to MOODLE_35_STABLE
  • Loading branch information
andrewnicols committed Oct 23, 2018
2 parents d54cbaf + a7ebe98 commit 68f64fe
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 4 deletions.
43 changes: 43 additions & 0 deletions admin/tool/policy/classes/privacy/provider.php
Expand Up @@ -26,8 +26,10 @@

use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\moodle_content_writer;
use core_privacy\local\request\userlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;

Expand All @@ -43,6 +45,9 @@ class provider implements
// This tool stores user data.
\core_privacy\local\metadata\provider,

// This plugin is capable of determining which users have data within it.
\core_privacy\local\request\core_userlist_provider,

// This tool may provide access to and deletion of user data.
\core_privacy\local\request\plugin\provider {

Expand Down Expand Up @@ -132,6 +137,33 @@ public static function get_contexts_for_userid(int $userid) : contextlist {
return $contextlist;
}

/**
* Get the list of users who have data within a context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
$context = $userlist->get_context();

// Users that have modified any policies, if fetching for system context.
if (is_a($context, \context_system::class)) {
$sql = "SELECT v.usermodified AS userid
FROM {tool_policy_versions} v";
$userlist->add_from_sql('userid', $sql, []);
}

// Users that have accepted any policies, if fetching for user context.
if (is_a($context, \context_user::class)) {
$sql = "SELECT a.userid, a.usermodified
FROM {tool_policy_acceptances} a
WHERE a.userid = :instanceid";
$params = ['instanceid' => $context->instanceid];

$userlist->add_from_sql('userid', $sql, $params);
$userlist->add_from_sql('usermodified', $sql, $params);
}
}

/**
* Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
*
Expand Down Expand Up @@ -172,6 +204,17 @@ public static function delete_data_for_all_users_in_context(\context $context) {
public static function delete_data_for_user(approved_contextlist $contextlist) {
}

/**
* Delete multiple users within a single context.
*
* We never delete user agreements to the policies because they are part of privacy data.
* We never delete policy versions because they are part of privacy data.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
}

/**
* Export all policy agreements relating to the specified user context.
*
Expand Down
93 changes: 89 additions & 4 deletions admin/tool/policy/tests/privacy_provider_test.php
Expand Up @@ -45,6 +45,9 @@ class tool_policy_privacy_provider_testcase extends \core_privacy\tests\provider
/** @var stdClass The manager user object. */
protected $manager;

/** @var context_system The system context instance. */
protected $syscontext;

/**
* Setup function. Will create a user.
*/
Expand All @@ -56,11 +59,11 @@ protected function setUp() {

// Create manager user.
$this->manager = $generator->create_user();
$syscontext = context_system::instance();
$this->syscontext = context_system::instance();
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $syscontext->id);
role_assign($rolemanagerid, $this->manager->id, $syscontext->id);
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $this->syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $this->syscontext->id);
role_assign($rolemanagerid, $this->manager->id, $this->syscontext->id);
accesslib_clear_all_caches_for_unit_testing();
}

Expand Down Expand Up @@ -99,6 +102,88 @@ public function test_get_contexts_for_userid() {
$this->assertEquals(1, $contextlist->count());
}

/**
* Test getting the user IDs within the context related to this plugin.
*/
public function test_get_users_in_context() {
global $CFG;
$component = 'tool_policy';

// System context should have nothing before a policy is added.
$userlist = new \core_privacy\local\request\userlist($this->syscontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);

// Create parent and child users.
$generator = $this->getDataGenerator();
$parentuser = $generator->create_user();
$childuser = $generator->create_user();

// Fetch relevant contexts.
$managercontext = \context_user::instance($this->manager->id);
$usercontext = $managercontext = \context_user::instance($this->user->id);
$parentcontext = $managercontext = \context_user::instance($parentuser->id);
$childcontext = $managercontext = \context_user::instance($childuser->id);

// Assign parent to accept on behalf of the child.
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $this->syscontext->id);
role_assign($roleparentid, $parentuser->id, $childcontext->id);

// Create a policy.
$this->setUser($this->manager);
$CFG->sitepolicyhandler = 'tool_policy';
$policy = $this->add_policy();
api::make_current($policy->get('id'));

// Manager should exist in system context now they have created a policy.
$userlist = new \core_privacy\local\request\userlist($this->syscontext, $component);
provider::get_users_in_context($userlist);
$this->assertCount(1, $userlist);
$this->assertEquals([$this->manager->id], $userlist->get_userids());

// User contexts should be empty before policy acceptances.
$userlist = new \core_privacy\local\request\userlist($usercontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);

$userlist = new \core_privacy\local\request\userlist($parentcontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);

$userlist = new \core_privacy\local\request\userlist($childcontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);

// User accepts policy, parent accepts on behalf of child only.
$this->setUser($this->user);
api::accept_policies([$policy->get('id')]);

$this->setUser($parentuser);
api::accept_policies([$policy->get('id')], $childuser->id);

// Ensure user is fetched within its user context.
$userlist = new \core_privacy\local\request\userlist($usercontext, $component);
provider::get_users_in_context($userlist);
$this->assertCount(1, $userlist);
$this->assertEquals([$this->user->id], $userlist->get_userids());

// Ensure parent and child are both found within child's user context.
$userlist = new \core_privacy\local\request\userlist($childcontext, $component);
provider::get_users_in_context($userlist);
$this->assertCount(2, $userlist);
$expected = [$parentuser->id, $childuser->id];
$actual = $userlist->get_userids();
sort($expected);
sort($actual);
$this->assertEquals($expected, $actual);

// Parent has not accepted for itself, so should not be found within its user context.
$userlist = new \core_privacy\local\request\userlist($parentcontext, $component);
provider::get_users_in_context($userlist);
$this->assertCount(0, $userlist);
}

public function test_export_agreements() {
global $CFG;

Expand Down

0 comments on commit 68f64fe

Please sign in to comment.