From 89266764c0c9093ce5d4aee48a5785842da9c426 Mon Sep 17 00:00:00 2001 From: Victor Deniz Date: Wed, 9 May 2018 10:00:13 +0100 Subject: [PATCH] MDL-62269 auth_mnet: Implement privacy API AMOS BEGIN CPY [privacy:metadata:address,core_user],[privacy:metadata:mnet_external:address,auth_mnet] CPY [privacy:metadata:aim,core_user],[privacy:metadata:mnet_external:aim,auth_mnet] CPY [privacy:metadata:aim,core_user],[privacy:metadata:mnet_external:aim,auth_mnet] CPY [privacy:metadata:alternatename,core_user],[privacy:metadata:mnet_external:alternatename,auth_mnet] CPY [privacy:metadata:autosubscribe,core_user],[privacy:metadata:mnet_external:autosubscribe,auth_mnet] CPY [privacy:metadata:calendartype,core_user],[privacy:metadata:mnet_external:calendartype,auth_mnet] CPY [privacy:metadata:city,core_user],[privacy:metadata:mnet_external:city,auth_mnet] CPY [privacy:metadata:country,core_user],[privacy:metadata:mnet_external:country,auth_mnet] CPY [privacy:metadata:currentlogin,core_user],[privacy:metadata:mnet_external:currentlogin,auth_mnet] CPY [privacy:metadata:department,core_user],[privacy:metadata:mnet_external:department,auth_mnet] CPY [privacy:metadata:description,core_user],[privacy:metadata:mnet_external:description,auth_mnet] CPY [privacy:metadata:email,core_user],[privacy:metadata:mnet_external:email,auth_mnet] CPY [privacy:metadata:emailstop,core_user],[privacy:metadata:mnet_external:emailstop,auth_mnet] CPY [privacy:metadata:firstaccess,core_user],[privacy:metadata:mnet_external:firstaccess,auth_mnet] CPY [privacy:metadata:firstname,core_user],[privacy:metadata:mnet_external:firstname,auth_mnet] CPY [privacy:metadata:firstnamephonetic,core_user],[privacy:metadata:mnet_external:firstnamephonetic,auth_mnet] CPY [privacy:metadata:icq,core_user],[privacy:metadata:mnet_external:icq,auth_mnet] CPY [privacy:metadata:id,core_user],[privacy:metadata:mnet_external:id,auth_mnet] CPY [privacy:metadata:idnumber,core_user],[privacy:metadata:mnet_external:idnumber,auth_mnet] CPY [privacy:metadata:imagealt,core_user],[privacy:metadata:mnet_external:imagealt,auth_mnet] CPY [privacy:metadata:institution,core_user],[privacy:metadata:mnet_external:institution,auth_mnet] CPY [privacy:metadata:lang,core_user],[privacy:metadata:mnet_external:lang,auth_mnet] CPY [privacy:metadata:lastaccess,core_user],[privacy:metadata:mnet_external:lastaccess,auth_mnet] CPY [privacy:metadata:lastlogin,core_user],[privacy:metadata:mnet_external:lastlogin,auth_mnet] CPY [privacy:metadata:lastname,core_user],[privacy:metadata:mnet_external:lastname,auth_mnet] CPY [privacy:metadata:lastnamephonetic,core_user],[privacy:metadata:mnet_external:lastnamephonetic,auth_mnet] CPY [privacy:metadata:maildigest,core_user],[privacy:metadata:mnet_external:maildigest,auth_mnet] CPY [privacy:metadata:maildisplay,core_user],[privacy:metadata:mnet_external:maildisplay,auth_mnet] CPY [privacy:metadata:middlename,core_user],[privacy:metadata:mnet_external:middlename,auth_mnet] CPY [privacy:metadata:msn,core_user],[privacy:metadata:mnet_external:msn,auth_mnet] CPY [privacy:metadata:phone,core_user],[privacy:metadata:mnet_external:phone1,auth_mnet] CPY [privacy:metadata:picture,core_user],[privacy:metadata:mnet_external:picture,auth_mnet] CPY [privacy:metadata:policyagreed,core_user],[privacy:metadata:mnet_external:policyagreed,auth_mnet] CPY [privacy:metadata:skype,core_user],[privacy:metadata:mnet_external:skype,auth_mnet] CPY [privacy:metadata:suspended,core_user],[privacy:metadata:mnet_external:suspended,auth_mnet] CPY [privacy:metadata:timezone,core_user],[privacy:metadata:mnet_external:timezone,auth_mnet] CPY [privacy:metadata:trackforums,core_user],[privacy:metadata:mnet_external:trackforums,auth_mnet] CPY [privacy:metadata:trustbitmask,core_user],[privacy:metadata:mnet_external:trustbitmask,auth_mnet] CPY [privacy:metadata:url,core_user],[privacy:metadata:mnet_external:url,auth_mnet] CPY [privacy:metadata:username,core_user],[privacy:metadata:mnet_external:username,auth_mnet] CPY [privacy:metadata:yahoo,core_user],[privacy:metadata:mnet_external:yahoo,auth_mnet] AMOS END --- auth/mnet/classes/privacy/provider.php | 221 +++++++++++++++++++++- auth/mnet/lang/en/auth_mnet.php | 65 ++++++- auth/mnet/tests/privacy_provider_test.php | 214 +++++++++++++++++++++ 3 files changed, 491 insertions(+), 9 deletions(-) create mode 100644 auth/mnet/tests/privacy_provider_test.php diff --git a/auth/mnet/classes/privacy/provider.php b/auth/mnet/classes/privacy/provider.php index 93a1b45b467..63efd9bd3dd 100644 --- a/auth/mnet/classes/privacy/provider.php +++ b/auth/mnet/classes/privacy/provider.php @@ -21,21 +21,226 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace auth_mnet\privacy; + 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\transform; +use \core_privacy\local\request\writer; + /** - * Privacy Subsystem for auth_mnet implementing null_provider. + * Privacy provider for the mnet authentication * * @copyright 2018 Carlos Escobedo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class provider implements \core_privacy\local\metadata\null_provider { +class provider implements + \core_privacy\local\metadata\provider, + \core_privacy\local\request\plugin\provider { + + use \core_privacy\local\legacy_polyfill; + /** - * Get the language string identifier with the component's language - * file to explain why this plugin stores no data. + * Returns meta data about this system. * - * @return string + * @param collection $collection The initialised item collection to add items to. + * @return collection A listing of user data stored through this system. */ - public static function get_reason() { - return 'privacy:metadata'; + public static function get_metadata(collection $collection) { + + $sessionfields = [ + 'userid' => 'privacy:metadata:mnet_session:userid', + 'username' => 'privacy:metadata:mnet_session:username', + 'token' => 'privacy:metadata:mnet_session:token', + 'mnethostid' => 'privacy:metadata:mnet_session:mnethostid', + 'useragent' => 'privacy:metadata:mnet_session:useragent', + 'expires' => 'privacy:metadata:mnet_session:expires' + ]; + + $collection->add_database_table('mnet_session', $sessionfields, 'privacy:metadata:mnet_session'); + + $logfields = [ + 'hostid' => 'privacy:metadata:mnet_log:hostid', + 'remoteid' => 'privacy:metadata:mnet_log:remoteid', + 'time' => 'privacy:metadata:mnet_log:time', + 'userid' => 'privacy:metadata:mnet_log:userid', + 'ip' => 'privacy:metadata:mnet_log:ip', + 'course' => 'privacy:metadata:mnet_log:course', + 'coursename' => 'privacy:metadata:mnet_log:coursename', + 'module' => 'privacy:metadata:mnet_log:module', + 'cmid' => 'privacy:metadata:mnet_log:cmid', + 'action' => 'privacy:metadata:mnet_log:action', + 'url' => 'privacy:metadata:mnet_log:url', + 'info' => 'privacy:metadata:mnet_log:info' + ]; + + $collection->add_database_table('mnet_log', $logfields, 'privacy:metadata:mnet_log'); + + $externalfields = [ + 'address' => 'privacy:metadata:mnet_external:address', + 'aim' => 'privacy:metadata:mnet_external:aim', + 'alternatename' => 'privacy:metadata:mnet_external:alternatename', + 'autosubscribe' => 'privacy:metadata:mnet_external:autosubscribe', + 'calendartype' => 'privacy:metadata:mnet_external:calendartype', + 'city' => 'privacy:metadata:mnet_external:city', + 'country' => 'privacy:metadata:mnet_external:country', + 'currentlogin' => 'privacy:metadata:mnet_external:currentlogin', + 'department' => 'privacy:metadata:mnet_external:department', + 'description' => 'privacy:metadata:mnet_external:description', + 'email' => 'privacy:metadata:mnet_external:email', + 'emailstop' => 'privacy:metadata:mnet_external:emailstop', + 'firstaccess' => 'privacy:metadata:mnet_external:firstaccess', + 'firstname' => 'privacy:metadata:mnet_external:firstname', + 'firstnamephonetic' => 'privacy:metadata:mnet_external:firstnamephonetic', + 'icq' => 'privacy:metadata:mnet_external:icq', + 'id' => 'privacy:metadata:mnet_external:id', + 'idnumber' => 'privacy:metadata:mnet_external:idnumber', + 'imagealt' => 'privacy:metadata:mnet_external:imagealt', + 'institution' => 'privacy:metadata:mnet_external:institution', + 'lang' => 'privacy:metadata:mnet_external:lang', + 'lastaccess' => 'privacy:metadata:mnet_external:lastaccess', + 'lastlogin' => 'privacy:metadata:mnet_external:lastlogin', + 'lastname' => 'privacy:metadata:mnet_external:lastname', + 'lastnamephonetic' => 'privacy:metadata:mnet_external:lastnamephonetic', + 'maildigest' => 'privacy:metadata:mnet_external:maildigest', + 'maildisplay' => 'privacy:metadata:mnet_external:maildisplay', + 'middlename' => 'privacy:metadata:mnet_external:middlename', + 'msn' => 'privacy:metadata:mnet_external:msn', + 'phone1' => 'privacy:metadata:mnet_external:phone1', + 'pnone2' => 'privacy:metadata:mnet_external:phone2', + 'picture' => 'privacy:metadata:mnet_external:picture', + 'policyagreed' => 'privacy:metadata:mnet_external:policyagreed', + 'skype' => 'privacy:metadata:mnet_external:skype', + 'suspended' => 'privacy:metadata:mnet_external:suspended', + 'timezone' => 'privacy:metadata:mnet_external:timezone', + 'trackforums' => 'privacy:metadata:mnet_external:trackforums', + 'trustbitmask' => 'privacy:metadata:mnet_external:trustbitmask', + 'url' => 'privacy:metadata:mnet_external:url', + 'username' => 'privacy:metadata:mnet_external:username', + 'yahoo' => 'privacy:metadata:mnet_external:yahoo', + ]; + + $collection->add_external_location_link('moodle', $externalfields, 'privacy:metadata:external:moodle'); + + $collection->add_external_location_link('mahara', $externalfields, 'privacy:metadata:external:mahara'); + + return $collection; } -} \ No newline at end of file + + /** + * Get the list of contexts that contain user information for the specified user. + * + * @param int $userid The user to search. + * @return contextlist $contextlist The list of contexts used in this plugin. + */ + public static function get_contexts_for_userid($userid) { + $sql = "SELECT ctx.id + FROM {mnet_log} ml + JOIN {context} ctx ON ctx.instanceid = ml.userid AND ctx.contextlevel = :contextlevel + WHERE ml.userid = :userid"; + $params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER]; + + $contextlist = new contextlist(); + $contextlist->add_from_sql($sql, $params); + + return $contextlist; + } + + /** + * Export all user data for the specified user, in the specified contexts, using the supplied exporter instance. + * + * @param approved_contextlist $contextlist The approved contexts to export information for. + */ + public static function export_user_data(approved_contextlist $contextlist) { + global $DB; + + $context = \context_user::instance($contextlist->get_user()->id); + + $sql = "SELECT ml.id, mh.wwwroot, mh.name, ml.remoteid, ml.time, ml.userid, ml.ip, ml.course, + ml.coursename, ml.module, ml.cmid, ml.action, ml.url, ml.info + FROM {mnet_log} ml + JOIN {mnet_host} mh ON mh.id = ml.hostid + WHERE ml.userid = :userid + ORDER BY mh.name, ml.coursename"; + $params = ['userid' => $contextlist->get_user()->id]; + + $data = []; + $lastcourseid = null; + + $logentries = $DB->get_recordset_sql($sql, $params); + foreach ($logentries as $logentry) { + $item = (object) [ + 'time' => transform::datetime($logentry->time), + 'remoteid' => $logentry->remoteid, + 'ip' => $logentry->ip, + 'course' => $logentry->course, + 'coursename' => format_string($logentry->coursename), + 'module' => $logentry->module, + 'cmid' => $logentry->cmid, + 'action' => $logentry->action, + 'url' => $logentry->url, + 'info' => format_string($logentry->info) + ]; + + $item->externalhost = + ($logentry->name == '') ? preg_replace('#^https?://#', '', $logentry->wwwroot) : + preg_replace('#^https?://#', '', $logentry->name); + + if ($lastcourseid && $lastcourseid != $logentry->course) { + $path = [get_string('pluginname', 'auth_mnet'), $data[0]->externalhost, $data[0]->coursename]; + writer::with_context($context)->export_data($path, (object) $data); + $data = []; + } + + $data[] = $item; + $lastcourseid = $logentry->course; + } + $logentries->close(); + + $path = [get_string('pluginname', 'auth_mnet'), $item->externalhost, $item->coursename]; + writer::with_context($context)->export_data($path, (object) $data); + } + + /** + * Delete all personal data for all users in the specified context. + * + * @param context $context Context to delete data from. + */ + public static function delete_data_for_all_users_in_context(\context $context) { + global $DB; + + if (empty($context)) { + return; + } + + if ($context->contextlevel != CONTEXT_USER) { + return; + } + + $DB->delete_records('mnet_log', ['userid' => $context->instanceid]); + } + + /** + * Delete all user data for the specified user, in the specified contexts. + * + * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. + */ + public static function delete_data_for_user(approved_contextlist $contextlist) { + global $DB; + + if (empty($contextlist->count())) { + return; + } + + foreach ($contextlist->get_contexts() as $context) { + if ($context->contextlevel != CONTEXT_USER) { + return; + } + + // Because we only use user contexts the instance ID is the user ID. + $DB->delete_records('mnet_log', ['userid' => $context->instanceid]); + } + } +} diff --git a/auth/mnet/lang/en/auth_mnet.php b/auth/mnet/lang/en/auth_mnet.php index 6fa6ff10156..9caa2e74879 100644 --- a/auth/mnet/lang/en/auth_mnet.php +++ b/auth/mnet/lang/en/auth_mnet.php @@ -35,4 +35,67 @@ $string['sso_mnet_login_refused'] = 'Username {$a->user} is not permitted to log $string['sso_sp_description'] = 'Publish this service to allow authenticated users from {$a} to access your site without having to re-login.
Subscribe to this service to allow your users to roam to the {$a} site without having to re-login there.
'; $string['sso_sp_name'] = 'SSO (Service Provider)'; $string['pluginname'] = 'MNet authentication'; -$string['privacy:metadata'] = 'The MNet authentication plugin does not store any personal data.'; +$string['privacy:metadata:external:mahara'] = 'This plugin can send data externally to a linked Mahara application.'; +$string['privacy:metadata:external:moodle'] = 'This plugin can send data externally to a linked Moodle application.'; +$string['privacy:metadata:mnet_external:address'] = 'The address of the user.'; +$string['privacy:metadata:mnet_external:aim'] = 'The AIM identifier of the user.'; +$string['privacy:metadata:mnet_external:alternatename'] = 'An alternative name for the user.'; +$string['privacy:metadata:mnet_external:autosubscribe'] = 'A preference as to if the user should be auto-subscribed to forums the user posts in.'; +$string['privacy:metadata:mnet_external:calendartype'] = 'A user preference for the type of calendar to use.'; +$string['privacy:metadata:mnet_external:city'] = 'The city of the user.'; +$string['privacy:metadata:mnet_external:country'] = 'The country that the user is in.'; +$string['privacy:metadata:mnet_external:currentlogin'] = 'The current login for this user.'; +$string['privacy:metadata:mnet_external:department'] = 'The department that this user can be found in.'; +$string['privacy:metadata:mnet_external:description'] = 'General details about this user.'; +$string['privacy:metadata:mnet_external:email'] = 'An email address for contact.'; +$string['privacy:metadata:mnet_external:emailstop'] = 'A preference to stop email being sent to the user.'; +$string['privacy:metadata:mnet_external:firstaccess'] = 'The time that this user first accessed the site.'; +$string['privacy:metadata:mnet_external:firstname'] = 'The first name of the user.'; +$string['privacy:metadata:mnet_external:firstnamephonetic'] = 'The phonetic details about the user\'s first name.'; +$string['privacy:metadata:mnet_external:icq'] = 'The ICQ number of the user.'; +$string['privacy:metadata:mnet_external:id'] = 'The identifier for the user.'; +$string['privacy:metadata:mnet_external:idnumber'] = 'An identification number given by the institution.'; +$string['privacy:metadata:mnet_external:imagealt'] = 'Alternative text for the user\'s image.'; +$string['privacy:metadata:mnet_external:institution'] = 'The institution that this user is a member of.'; +$string['privacy:metadata:mnet_external:lang'] = 'A user preference for the language shown.'; +$string['privacy:metadata:mnet_external:lastaccess'] = 'The time that the user last accessed the site.'; +$string['privacy:metadata:mnet_external:lastlogin'] = 'The last login of this user.'; +$string['privacy:metadata:mnet_external:lastname'] = 'The surname of the user.'; +$string['privacy:metadata:mnet_external:lastnamephonetic'] = 'The phonetic details about the user\'s surname.'; +$string['privacy:metadata:mnet_external:maildigest'] = 'A setting for the mail digest for this user.'; +$string['privacy:metadata:mnet_external:maildisplay'] = 'A preference for the user about displaying their email address to other users.'; +$string['privacy:metadata:mnet_external:middlename'] = 'The middle name of the user.'; +$string['privacy:metadata:mnet_external:msn'] = 'The MSN identifier of the user.'; +$string['privacy:metadata:mnet_external:phone1'] = 'A phone number for the user.'; +$string['privacy:metadata:mnet_external:phone2'] = 'An additional phone number for the user.'; +$string['privacy:metadata:mnet_external:picture'] = 'The picture details associated with this user.'; +$string['privacy:metadata:mnet_external:policyagreed'] = 'A flag to determine if the user has agreed to the site policy.'; +$string['privacy:metadata:mnet_external:skype'] = 'The skype identifier of the user.'; +$string['privacy:metadata:mnet_external:suspended'] = 'A flag to show if the user has been suspended on this system.'; +$string['privacy:metadata:mnet_external:timezone'] = 'The timezone that the user resides in.'; +$string['privacy:metadata:mnet_external:trackforums'] = 'A preference for forums and tracking them.'; +$string['privacy:metadata:mnet_external:trustbitmask'] = 'The trust bit mask'; +$string['privacy:metadata:mnet_external:url'] = 'A URL related to this user.'; +$string['privacy:metadata:mnet_external:username'] = 'The username for this user.'; +$string['privacy:metadata:mnet_external:yahoo'] = 'The yahoo identifier of the user.'; +$string['privacy:metadata:mnet_log'] = 'Details of remote actions carried out by a local user logged in a remote system'; +$string['privacy:metadata:mnet_log:action'] = 'Action carried out by the user'; +$string['privacy:metadata:mnet_log:cmid'] = 'ID of the course module'; +$string['privacy:metadata:mnet_log:course'] = 'Remote system course ID where the action occurred'; +$string['privacy:metadata:mnet_log:coursename'] = 'Remote system course full name where the action occurred'; +$string['privacy:metadata:mnet_log:hostid'] = 'Remote system MNet ID'; +$string['privacy:metadata:mnet_log:info'] = 'Additional information about the action'; +$string['privacy:metadata:mnet_log:ip'] = 'The IP address used at the time of the action occurred'; +$string['privacy:metadata:mnet_log:module'] = 'Remote system module where the event the action occurred'; +$string['privacy:metadata:mnet_log:remoteid'] = 'Remote ID of the user who carried out the action in the remote system'; +$string['privacy:metadata:mnet_log:time'] = 'Time when the action occurred'; +$string['privacy:metadata:mnet_log:url'] = 'Remote system URL where the action occurred'; +$string['privacy:metadata:mnet_log:userid'] = 'Local ID of the user who carried out the action in the remote system'; +$string['privacy:metadata:mnet_session'] = 'The details of each MNet user session in a remote system is stored temporarily'; +$string['privacy:metadata:mnet_session:expires'] = 'Time when the session expires'; +$string['privacy:metadata:mnet_session:mnethostid'] = 'Remote system MNet ID'; +$string['privacy:metadata:mnet_session:token'] = 'Unique session identifier'; +$string['privacy:metadata:mnet_session:useragent'] = 'String denoting the user agent being which is accessing the page.'; +$string['privacy:metadata:mnet_session:userid'] = 'ID of the user jumping to remote system'; +$string['privacy:metadata:mnet_session:username'] = 'Username of the user jumping to remote system'; +$string['unknownhost'] = 'Unknown host'; \ No newline at end of file diff --git a/auth/mnet/tests/privacy_provider_test.php b/auth/mnet/tests/privacy_provider_test.php new file mode 100644 index 00000000000..2c7292b3e3f --- /dev/null +++ b/auth/mnet/tests/privacy_provider_test.php @@ -0,0 +1,214 @@ +. +/** + * Privacy test for the authentication mnet + * + * @package auth_mnet + * @category test + * @copyright 2018 Victor Deniz + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use \auth_mnet\privacy\provider; +use \core_privacy\local\request\approved_contextlist; +use \core_privacy\local\request\writer; +use \core_privacy\tests\provider_testcase; +use core_privacy\local\request\transform; + +/** + * Privacy test for the authentication mnet + * + * @package auth_mnet + * @category test + * @copyright 2018 Victor Deniz + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class auth_mnet_privacy_testcase extends provider_testcase { + /** + * Set up method. + */ + public function setUp() { + $this->resetAfterTest(); + $this->setAdminUser(); + } + + /** + * Check that a user context is returned if there is any user data for this user. + */ + public function test_get_contexts_for_userid() { + global $DB; + + $user = $this->getDataGenerator()->create_user(['auth' => 'mnet']); + $this->assertEmpty(provider::get_contexts_for_userid($user->id)); + + // Insert mnet_log record. + $logrecord = new stdClass(); + $logrecord->hostid = ''; + $logrecord->remoteid = 65; + $logrecord->time = time(); + $logrecord->userid = $user->id; + + $DB->insert_record('mnet_log', $logrecord); + + $contextlist = provider::get_contexts_for_userid($user->id); + + // Check that we only get back one context. + $this->assertCount(1, $contextlist); + + // Check that a context is returned is the expected. + $usercontext = \context_user::instance($user->id); + $this->assertEquals($usercontext->id, $contextlist->get_contextids()[0]); + } + + /** + * Test that user data is exported correctly. + */ + public function test_export_user_data() { + global $DB; + + $user = $this->getDataGenerator()->create_user(['auth' => 'mnet']); + + // Insert mnet_host record. + $hostrecord = new stdClass(); + $hostrecord->wwwroot = 'https://external.moodle.com'; + $hostrecord->name = 'External Moodle'; + $hostrecord->public_key = '-----BEGIN CERTIFICATE-----'; + + $hostid = $DB->insert_record('mnet_host', $hostrecord); + + // Insert mnet_log record. + $logrecord = new stdClass(); + $logrecord->hostid = $hostid; + $logrecord->remoteid = 65; + $logrecord->time = time(); + $logrecord->userid = $user->id; + $logrecord->course = 3; + $logrecord->coursename = 'test course'; + + $DB->insert_record('mnet_log', $logrecord); + + $usercontext = \context_user::instance($user->id); + + $writer = writer::with_context($usercontext); + $this->assertFalse($writer->has_any_data()); + $approvedlist = new approved_contextlist($user, 'auth_mnet', [$usercontext->id]); + provider::export_user_data($approvedlist); + + $data = $writer->get_data([get_string('pluginname', 'auth_mnet'), $hostrecord->name, $logrecord->coursename]); + + $this->assertEquals($logrecord->remoteid, reset($data)->remoteid); + $this->assertEquals(transform::datetime($logrecord->time), reset($data)->time); + } + + /** + * Test deleting all user data for a specific context. + */ + public function test_delete_data_for_all_users_in_context() { + global $DB; + + $user1 = $this->getDataGenerator()->create_user(['auth' => 'mnet']); + + // Insert mnet_log record. + $logrecord1 = new stdClass(); + $logrecord1->hostid = ''; + $logrecord1->remoteid = 65; + $logrecord1->time = time(); + $logrecord1->userid = $user1->id; + + $DB->insert_record('mnet_log', $logrecord1); + + $user1context = \context_user::instance($user1->id); + + $user2 = $this->getDataGenerator()->create_user(['auth' => 'mnet']); + + // Insert mnet_log record. + $logrecord2 = new stdClass(); + $logrecord2->hostid = ''; + $logrecord2->remoteid = 65; + $logrecord2->time = time(); + $logrecord2->userid = $user2->id; + + $DB->insert_record('mnet_log', $logrecord2); + + // Get all mnet log records. + $mnetlogrecords = $DB->get_records('mnet_log', array()); + // There should be two. + $this->assertCount(2, $mnetlogrecords); + + // Delete everything for the first user context. + provider::delete_data_for_all_users_in_context($user1context); + + // Get all user1 mnet log records. + $mnetlogrecords = $DB->get_records('mnet_log', ['userid' => $user1->id]); + $this->assertCount(0, $mnetlogrecords); + + // Get all mnet log records. + $mnetlogrecords = $DB->get_records('mnet_log', array()); + // There should be one (user2). + $this->assertCount(1, $mnetlogrecords); + } + + /** + * This should work identical to the above test. + */ + public function test_delete_data_for_user() { + global $DB; + + $user1 = $this->getDataGenerator()->create_user(['auth' => 'mnet']); + + // Insert mnet_log record. + $logrecord1 = new stdClass(); + $logrecord1->hostid = ''; + $logrecord1->remoteid = 65; + $logrecord1->time = time(); + $logrecord1->userid = $user1->id; + + $DB->insert_record('mnet_log', $logrecord1); + + $user1context = \context_user::instance($user1->id); + + $user2 = $this->getDataGenerator()->create_user(['auth' => 'mnet']); + + // Insert mnet_log record. + $logrecord2 = new stdClass(); + $logrecord2->hostid = ''; + $logrecord2->remoteid = 65; + $logrecord2->time = time(); + $logrecord2->userid = $user2->id; + + $DB->insert_record('mnet_log', $logrecord2); + + // Get all mnet log records. + $mnetlogrecords = $DB->get_records('mnet_log', array()); + // There should be two. + $this->assertCount(2, $mnetlogrecords); + + // Delete everything for the first user. + $approvedlist = new approved_contextlist($user1, 'auth_mnet', [$user1context->id]); + provider::delete_data_for_user($approvedlist); + + // Get all user1 mnet log records. + $mnetlogrecords = $DB->get_records('mnet_log', ['userid' => $user1->id]); + $this->assertCount(0, $mnetlogrecords); + + // Get all mnet log records. + $mnetlogrecords = $DB->get_records('mnet_log', array()); + // There should be one (user2). + $this->assertCount(1, $mnetlogrecords); + } +}