MDL-63659 tool_monitor: Add support for removal of context users

This issue is a part of the MDL-62560 Epic.
This commit is contained in:
Michael Hawkins 2018-10-15 17:35:54 +08:00 committed by David Monllao
parent 325d9b50e2
commit 46bb823e04
2 changed files with 182 additions and 1 deletions

View File

@ -27,7 +27,9 @@ defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\contextlist;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\approved_userlist;
use \core_privacy\local\request\transform;
use \core_privacy\local\request\userlist;
use \core_privacy\local\request\writer;
use \tool_monitor\subscription_manager;
use \tool_monitor\rule_manager;
@ -39,7 +41,10 @@ use \tool_monitor\rule_manager;
* @copyright 2018 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\plugin\provider {
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\core_userlist_provider,
\core_privacy\local\request\plugin\provider {
/**
* Get information about the user data stored by this plugin.
@ -101,6 +106,40 @@ class provider implements \core_privacy\local\metadata\provider, \core_privacy\l
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();
if (!is_a($context, \context_user::class)) {
return;
}
$params = [
'contextid' => $context->id,
'contextuser' => CONTEXT_USER,
];
$sql = "SELECT mr.userid
FROM {context} ctx
JOIN {tool_monitor_rules} mr ON ctx.instanceid = mr.userid
AND ctx.contextlevel = :contextuser
WHERE ctx.id = :contextid";
$userlist->add_from_sql('userid', $sql, $params);
$sql = "SELECT ms.userid
FROM {context} ctx
LEFT JOIN {tool_monitor_subscriptions} ms ON ctx.instanceid = ms.userid
AND ctx.contextlevel = :contextuser
WHERE ctx.id = :contextid";
$userlist->add_from_sql('userid', $sql, $params);
}
/**
* Export all event monitor information for the list of contexts and this user.
*
@ -142,6 +181,22 @@ class provider implements \core_privacy\local\metadata\provider, \core_privacy\l
static::delete_user_data($contextlist->get_user()->id);
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
$context = $userlist->get_context();
$userids = $userlist->get_userids();
$userid = reset($userids);
// Only delete data for user context, which should be a single user.
if ($context->contextlevel == CONTEXT_USER && count($userids) == 1 && $userid == $context->instanceid) {
static::delete_user_data($userid);
}
}
/**
* This does the deletion of user data for the event monitor.
*

View File

@ -27,6 +27,7 @@ defined('MOODLE_INTERNAL') || die();
use \tool_monitor\privacy\provider;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\approved_userlist;
/**
* Privacy test for the event monitor
@ -128,6 +129,55 @@ class tool_monitor_privacy_testcase extends advanced_testcase {
$this->assertEquals($usercontext2->id, $contextlist->get_contextids()[0]);
}
/**
* Check that the correct userlist is returned if there is any user data for this context.
*/
public function test_get_users_in_context() {
$component = 'tool_monitor';
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$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($usercontext2, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Create a rule with user.
$this->setUser($user);
$rule = $monitorgenerator->create_rule();
$userlist = new \core_privacy\local\request\userlist($usercontext, $component);
provider::get_users_in_context($userlist);
// Check that we only get back user.
$userids = $userlist->get_userids();
$this->assertCount(1, $userlist);
$this->assertEquals($user->id, $userids[0]);
// Create a subscription with user2.
$this->setUser($user2);
$record = new stdClass();
$record->courseid = 0;
$record->userid = $user2->id;
$record->ruleid = $rule->id;
$subscription = $monitorgenerator->create_subscription($record);
$userlist = new \core_privacy\local\request\userlist($usercontext2, $component);
provider::get_users_in_context($userlist);
// Check that user2 is returned for just subscribing to a rule.
$userids = $userlist->get_userids();
$this->assertCount(1, $userlist);
$this->assertEquals($user2->id, $userids[0]);
}
/**
* Test that user data is exported correctly.
*/
@ -286,4 +336,80 @@ class tool_monitor_privacy_testcase extends advanced_testcase {
$this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
$this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
}
/**
* Test deleting user data for an approved userlist in a context.
*/
public function test_delete_data_for_users() {
global $DB;
$component = 'tool_monitor';
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->setUser($user);
// Need to give user one the ability to manage rules.
$this->assign_user_capability('tool/monitor:managerules', \context_system::instance());
$rulerecord = (object)['name' => 'privacy rule'];
$rule = $monitorgenerator->create_rule($rulerecord);
$secondrulerecord = (object)['name' => 'privacy rule2'];
$rule2 = $monitorgenerator->create_rule($secondrulerecord);
$subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
$subscription = $monitorgenerator->create_subscription($subscription);
// Have user 2 subscribe to the second rule created by user 1.
$subscription2 = (object)['ruleid' => $rule2->id, 'userid' => $user2->id];
$subscription2 = $monitorgenerator->create_subscription($subscription2);
$this->setUser($user2);
$thirdrulerecord = (object)['name' => 'privacy rule for second user'];
$rule3 = $monitorgenerator->create_rule($thirdrulerecord);
$subscription3 = (object)['ruleid' => $rule3->id, 'userid' => $user2->id];
$subscription3 = $monitorgenerator->create_subscription($subscription3);
// Get all of the monitor rules, ensure all exist.
$dbrules = $DB->get_records('tool_monitor_rules');
$this->assertCount(3, $dbrules);
// Delete for user2 in first user's context, should have no effect.
$approveduserids = [$user2->id];
$approvedlist = new approved_userlist($usercontext, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
$dbrules = $DB->get_records('tool_monitor_rules');
$this->assertCount(3, $dbrules);
// Delete for user in usercontext.
$approveduserids = [$user->id];
$approvedlist = new approved_userlist($usercontext, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
// Only the rules for user 1 that does not have any more subscriptions should be deleted (the first rule).
$dbrules = $DB->get_records('tool_monitor_rules');
$this->assertCount(2, $dbrules);
$this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
$this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
// There should be two subscriptions left, both for user 2.
$dbsubs = $DB->get_records('tool_monitor_subscriptions');
$this->assertCount(2, $dbsubs);
$this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
$this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
// Delete for user2 in context 2.
$approveduserids = [$user2->id];
$approvedlist = new approved_userlist($usercontext2, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
// There should be no subscriptions left.
$dbsubs = $DB->get_records('tool_monitor_subscriptions');
$this->assertEmpty($dbsubs);
}
}