Skip to content

Commit

Permalink
MSFTMPP-748: Update privacy providers
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesmcq committed Apr 12, 2019
1 parent 0e3a764 commit bb33fb9
Show file tree
Hide file tree
Showing 3 changed files with 411 additions and 23 deletions.
129 changes: 108 additions & 21 deletions classes/privacy/provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,16 @@
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\writer;

if (interface_exists('\core_privacy\local\request\core_userlist_provider')) {
interface auth_oidc_userlist extends \core_privacy\local\request\core_userlist_provider {}
} else {
interface auth_oidc_userlist {};
}

class provider implements
\core_privacy\local\request\plugin\provider,
\core_privacy\local\metadata\provider {
\core_privacy\local\metadata\provider,
auth_oidc_userlist {

/**
* Returns meta data about this system.
Expand Down Expand Up @@ -84,10 +91,58 @@ public static function get_metadata(collection $collection): collection {
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
$contextlist = new \core_privacy\local\request\contextlist();
$contextlist->add_system_context();

$sql = "SELECT ctx.id
FROM {auth_oidc_token} tk
JOIN {context} ctx ON ctx.instanceid = tk.userid AND ctx.contextlevel = :contextlevel
WHERE tk.userid = :userid";
$params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER];
$contextlist->add_from_sql($sql, $params);

$sql = "SELECT ctx.id
FROM {auth_oidc_prevlogin} pv
JOIN {context} ctx ON ctx.instanceid = pv.userid AND ctx.contextlevel = :contextlevel
WHERE pv.userid = :userid";
$params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER];
$contextlist->add_from_sql($sql, $params);

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(\core_privacy\local\request\userlist $userlist) {
$context = $userlist->get_context();

if (!$context instanceof \context_user) {
return;
}

$params = [
'contextuser' => CONTEXT_USER,
'contextid' => $context->id
];

$sql = "SELECT ctx.instanceid as userid
FROM {auth_oidc_prevlogin} pl
JOIN {context} ctx
ON ctx.instanceid = pl.userid
AND ctx.contextlevel = :contextuser
WHERE ctx.id = :contextid";
$userlist->add_from_sql('userid', $sql, $params);

$sql = "SELECT ctx.instanceid as userid
FROM {auth_oidc_token} tk
JOIN {context} ctx
ON ctx.instanceid = tk.userid
AND ctx.contextlevel = :contextuser
WHERE ctx.id = :contextid";
$userlist->add_from_sql('userid', $sql, $params);
}

/**
* Export all user data for the specified user, in the specified contexts.
*
Expand All @@ -96,50 +151,82 @@ public static function get_contexts_for_userid(int $userid) : contextlist {
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
$user = $contextlist->get_user();
$context = \context_system::instance();
$context = \context_user::instance($contextlist->get_user()->id);
$tables = static::get_table_user_map($user);
foreach ($tables as $table => $filterparams) {
$records = $DB->get_recordset($table, $filterparams);
foreach ($records as $record) {
writer::with_context($context)->export_data([], $record);
writer::with_context($context)->export_data([
get_string('privacy:metadata:auth_oidc', 'auth_oidc'),
get_string('privacy:metadata:'.$table, 'auth_oidc')
], $record);
}
}
}

/**
* Get a map of database tables that contain user data, and the filters to get records for a user.
*
* @param \stdClass $user The user to get the map for.
* @return array The table user map.
*/
protected static function get_table_user_map(\stdClass $user): array {
$tables = [
'auth_oidc_prevlogin' => ['userid' => $user->id],
'auth_oidc_token' => ['userid' => $user->id],
];
return $tables;
}

/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
// We only have data at the system context.
if ($context->contextlevel == CONTEXT_USER) {
self::delete_user_data($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.
* @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;
$user = $contextlist->get_user();
$tables = static::get_table_user_map($user);
foreach ($tables as $table => $filterparams) {
$DB->delete_records($table, $filterparams);
if (empty($contextlist->count())) {
return;
}
foreach ($contextlist->get_contexts() as $context) {
if ($context->contextlevel == CONTEXT_USER) {
self::delete_user_data($context->instanceid);
}
}
}

/**
* Get a map of database tables that contain user data, and the filters to get records for a user.
* This does the deletion of user data given a userid.
*
* @param \stdClass $user The user to get the map for.
* @return array The table user map.
* @param int $userid The user ID
*/
protected static function get_table_user_map(\stdClass $user): array {
$tables = [
'auth_oidc_prevlogin' => ['userid' => $user->id],
'auth_oidc_token' => ['userid' => $user->id],
];
return $tables;
private static function delete_user_data(int $userid) {
global $DB;
$DB->delete_records('auth_oidc_prevlogin', ['userid' => $userid]);
$DB->delete_records('auth_oidc_token', ['userid' => $userid]);
}

/**
* Delete multiple users within a single context.
*
* @param \core_privacy\local\request\approved_userlist $userlist The approved context and user information to delete
* information for.
*/
public static function delete_data_for_users(\core_privacy\local\request\approved_userlist $userlist) {
$context = $userlist->get_context();
// Because we only use user contexts the instance ID is the user ID.
if ($context instanceof \context_user) {
self::delete_user_data($context->instanceid);
}
}
}
5 changes: 3 additions & 2 deletions lang/en/auth_oidc.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,12 @@
$string['oidc:manageconnectionconnect'] = 'Allow OpenID Connection';
$string['oidc:manageconnectiondisconnect'] = 'Allow OpenID Disconnection';

$string['privacy:metadata:auth_oidc_prevlogin'] = 'Information about users previous login methods to undo Office 365 connections';
$string['privacy:metadata:auth_oidc'] = 'OpenID Connect Authentication';
$string['privacy:metadata:auth_oidc_prevlogin'] = 'Previous login methods to undo Office 365 connections';
$string['privacy:metadata:auth_oidc_prevlogin:userid'] = 'The ID of the Moodle user';
$string['privacy:metadata:auth_oidc_prevlogin:method'] = 'The previous login method';
$string['privacy:metadata:auth_oidc_prevlogin:password'] = 'The previous (encrypted) user password field.';
$string['privacy:metadata:auth_oidc_token'] = 'Information about OpenID Connect tokens for users';
$string['privacy:metadata:auth_oidc_token'] = 'OpenID Connect tokens';
$string['privacy:metadata:auth_oidc_token:oidcuniqid'] = 'The OIDC unique user identifier.';
$string['privacy:metadata:auth_oidc_token:username'] = 'The username of the Moodle user';
$string['privacy:metadata:auth_oidc_token:userid'] = 'The user ID of the Moodle user';
Expand Down
Loading

0 comments on commit bb33fb9

Please sign in to comment.