MDL-63656 tool_messageinbound: Add support for removal of context users
authorMichael Hawkins <michaelh@moodle.com>
Mon, 15 Oct 2018 04:17:27 +0000 (12:17 +0800)
committerMichael Hawkins <michaelh@moodle.com>
Mon, 29 Oct 2018 06:13:45 +0000 (14:13 +0800)
This issue is a part of the MDL-62560 Epic.

admin/tool/messageinbound/classes/privacy/provider.php
admin/tool/messageinbound/tests/privacy_test.php

index 53be916..33dc481 100644 (file)
@@ -30,7 +30,9 @@ use context;
 use context_user;
 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\transform;
+use core_privacy\local\request\userlist;
 use core_privacy\local\request\writer;
 
 /**
@@ -43,6 +45,7 @@ use core_privacy\local\request\writer;
  */
 class provider implements
     \core_privacy\local\metadata\provider,
+    \core_privacy\local\request\core_userlist_provider,
     \core_privacy\local\request\plugin\provider {
 
     /**
@@ -81,6 +84,30 @@ class provider implements
         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) {
+        global $DB;
+
+        $context = $userlist->get_context();
+
+        if (!is_a($context, \context_user::class)) {
+            return;
+        }
+
+        // Add user if any messagelist data exists.
+        if ($DB->record_exists('messageinbound_messagelist', ['userid' => $context->instanceid])) {
+            // Only using user context, so instance ID will be the only user ID.
+            $userlist->add_user($context->instanceid);
+        }
+
+        // Add users based on userkey (since we also delete those).
+        \core_userkey\privacy\provider::get_user_contexts_with_script($userlist, $context, 'messageinbound_handler');
+    }
+
     /**
      * Export all user data for the specified user, in the specified contexts.
      *
@@ -142,6 +169,23 @@ class provider implements
         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();
+
+        // Since this falls within a user context, only that user should be valid.
+        if ($context->contextlevel != CONTEXT_USER || count($userids) != 1 || $context->instanceid != $userids[0]) {
+            return;
+        }
+
+        static::delete_user_data($userids[0]);
+    }
+
     /**
      * Delete a user's data.
      *
index 5be172c..e98c027 100644 (file)
@@ -29,7 +29,9 @@ global $CFG;
 
 use core_privacy\tests\provider_testcase;
 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_messageinbound\privacy\provider;
 
@@ -70,6 +72,51 @@ class tool_messageinbound_privacy_testcase extends provider_testcase {
         $this->assertEquals($u2ctx->id, $contexts[0]->id);
     }
 
+    /**
+     * Test for provider::test_get_users_in_context().
+     */
+    public function test_get_users_in_context() {
+        $component = 'tool_messageinbound';
+        $dg = $this->getDataGenerator();
+        $u1 = $dg->create_user();
+        $u2 = $dg->create_user();
+        $u3 = $dg->create_user();
+        $u1ctx = context_user::instance($u1->id);
+        $u2ctx = context_user::instance($u2->id);
+        $u3ctx = context_user::instance($u3->id);
+
+        $addressmanager = new \core\message\inbound\address_manager();
+        $addressmanager->set_handler('\tool_messageinbound\message\inbound\invalid_recipient_handler');
+        $addressmanager->set_data(123);
+
+        // Create a user key for user 1.
+        $addressmanager->generate($u1->id);
+
+        // Create a messagelist for user 2.
+        $this->create_messagelist(['userid' => $u2->id, 'address' => 'u2@example1.com']);
+
+        $userlist1 = new userlist($u1ctx, $component);
+        provider::get_users_in_context($userlist1);
+        $userlist2 = new userlist($u2ctx, $component);
+        provider::get_users_in_context($userlist2);
+        $userlist3 = new userlist($u3ctx, $component);
+        provider::get_users_in_context($userlist3);
+
+        // Ensure user 1 is found from userkey.
+        $userids = $userlist1->get_userids();
+        $this->assertCount(1, $userids);
+        $this->assertEquals($u1->id, $userids[0]);
+
+        // Ensure user 2 is found from messagelist.
+        $userids = $userlist2->get_userids();
+        $this->assertCount(1, $userids);
+        $this->assertEquals($u2->id, $userids[0]);
+
+        // User 3 has neither, so should not be found.
+        $userids = $userlist3->get_userids();
+        $this->assertCount(0, $userids);
+    }
+
     public function test_delete_data_for_user() {
         global $DB;
         $dg = $this->getDataGenerator();
@@ -110,6 +157,58 @@ class tool_messageinbound_privacy_testcase extends provider_testcase {
         $this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
     }
 
+    /**
+     * Test for provider::test_delete_data_for_users().
+     */
+    public function test_delete_data_for_users() {
+        global $DB;
+        $component = 'tool_messageinbound';
+        $dg = $this->getDataGenerator();
+        $u1 = $dg->create_user();
+        $u2 = $dg->create_user();
+        $u1ctx = context_user::instance($u1->id);
+        $u2ctx = context_user::instance($u2->id);
+
+        $addressmanager = new \core\message\inbound\address_manager();
+        $addressmanager->set_handler('\tool_messageinbound\message\inbound\invalid_recipient_handler');
+        $addressmanager->set_data(123);
+
+        // Create a user key for both users.
+        $addressmanager->generate($u1->id);
+        $addressmanager->generate($u2->id);
+
+        // Create a messagelist for both users.
+        $this->create_messagelist(['userid' => $u1->id]);
+        $this->create_messagelist(['userid' => $u2->id]);
+
+        // Ensure data exists for both users.
+        $this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u1->id, 'script' => 'messageinbound_handler']));
+        $this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u2->id, 'script' => 'messageinbound_handler']));
+        $this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u1->id]));
+        $this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
+
+        // Ensure passing another user's ID does not do anything.
+        $approveduserids = [$u2->id];
+        $approvedlist = new approved_userlist($u1ctx, $component, $approveduserids);
+        provider::delete_data_for_users($approvedlist);
+
+        $this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u1->id, 'script' => 'messageinbound_handler']));
+        $this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u2->id, 'script' => 'messageinbound_handler']));
+        $this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u1->id]));
+        $this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
+
+        // Delete u1's data.
+        $approveduserids = [$u1->id];
+        $approvedlist = new approved_userlist($u1ctx, $component, $approveduserids);
+        provider::delete_data_for_users($approvedlist);
+
+        // Confirm only u1's data is deleted.
+        $this->assertFalse($DB->record_exists('user_private_key', ['userid' => $u1->id, 'script' => 'messageinbound_handler']));
+        $this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u2->id, 'script' => 'messageinbound_handler']));
+        $this->assertFalse($DB->record_exists('messageinbound_messagelist', ['userid' => $u1->id]));
+        $this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
+    }
+
     public function test_delete_data_for_all_users_in_context() {
         global $DB;
         $dg = $this->getDataGenerator();