Skip to content

Commit 40ed6f6

Browse files
committed
add privacy
1 parent 9063f62 commit 40ed6f6

File tree

3 files changed

+594
-33
lines changed

3 files changed

+594
-33
lines changed

classes/privacy/provider.php

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
<?php
2+
// This file is part of Moodle - https://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
16+
17+
/**
18+
* Plugin privicy provider
19+
*
20+
* @package local_oauth
21+
* @copyright 2024 Rens Sikma <r.sikma@atcomping.nl>
22+
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23+
*/
24+
namespace local_oauth\privacy;
25+
26+
use core_privacy\local\metadata\collection;
27+
use core_privacy\local\request\approved_contextlist;
28+
use core_privacy\local\request\approved_userlist;
29+
use core_privacy\local\request\userlist;
30+
use core_privacy\local\request\contextlist;
31+
use core_privacy\local\request\transform;
32+
use core_privacy\local\request\writer;
33+
34+
/**
35+
* Privacy Subsystem implementation for local_oauth.
36+
*
37+
*/
38+
class provider implements
39+
\core_privacy\local\metadata\provider,
40+
\core_privacy\local\request\plugin\provider,
41+
\core_privacy\local\request\core_userlist_provider {
42+
43+
/**
44+
* Return the fields which contain personal data.
45+
*
46+
* @param collection $collection reference to the collection to use to store the metadata.
47+
* @return collection the updated collection of metadata items.
48+
*/
49+
public static function get_metadata(collection $collection): collection {
50+
51+
$collection->add_database_table(
52+
'local_oauth_user_auth_scopes',
53+
[
54+
'id' => 'privacy:metadata:local_oauth:auth_scopes:id',
55+
'client_id' => 'privacy:metadata:local_oauth:auth_scopes:id',
56+
'user_id' => 'privacy:metadata:local_oauth:auth_scopes:id',
57+
'scope' => 'privacy:metadata:local_oauth:auth_scopes:id',
58+
59+
],
60+
'privacy:metadata:local_oauth:auth_scopes:tableexplanation'
61+
);
62+
63+
$collection->add_database_table(
64+
'local_oauth_refresh_tokens',
65+
[
66+
'id' => 'privacy:metadata:local_oauth:refresh_tokens:id',
67+
'refresh_token' => 'privacy:metadata:local_oauth:refresh_tokens:refresh_token',
68+
'client_id' => 'privacy:metadata:local_oauth:refresh_tokens:client_id',
69+
'user_id' => 'privacy:metadata:local_oauth:refresh_tokens:user_id',
70+
'expires' => 'privacy:metadata:local_oauth:refresh_tokens:expires',
71+
'scope' => 'privacy:metadata:local_oauth:refresh_tokens:scope',
72+
],
73+
'privacy:metadata:local_oauth:refresh_tokens:tableexplanation');
74+
75+
$collection->add_database_table(
76+
'local_oauth_auth_codes',
77+
[
78+
'id' => 'privacy:metadata:local_oauth:auth_codes:id',
79+
'authorization_code' => 'privacy:metadata:local_oauth:auth_codes:authorization_code',
80+
'client_id' => 'privacy:metadata:local_oauth:auth_codes:client_id',
81+
'user_id' => 'privacy:metadata:local_oauth:auth_codes:user_id',
82+
'redirect_uri' => 'privacy:metadata:local_oauth:auth_codes:redirect_uri',
83+
'expires' => 'privacy:metadata:local_oauth:auth_codes:expires',
84+
'scope' => 'privacy:metadata:local_oauth:auth_codes:scope',
85+
'id_token' => 'privacy:metadata:local_oauth:auth_codes:id_token',
86+
],
87+
'privacy:metadata:local_oauth:auth_codes:tableexplanation');
88+
89+
$collection->add_database_table('local_oauth_access_tokens',
90+
[
91+
'id' => 'privacy:metadata:local_oauth:access_tokens:id',
92+
'access_token' => 'privacy:metadata:local_oauth:access_tokens:access_token',
93+
'client_id' => 'privacy:metadata:local_oauth:access_tokens:client_id',
94+
'user_id' => 'privacy:metadata:local_oauth:access_tokens:user_id',
95+
'expires' => 'privacy:metadata:local_oauth:access_tokens:expires',
96+
'scope' => 'privacy:metadata:local_oauth:access_tokens:scope',
97+
],
98+
'privacy:metadata:local_oauth:access_tokens:tableexplanation');
99+
100+
$collection->add_external_location_link(
101+
'oauth_client',
102+
[
103+
'family_name' => 'privacy:metadata:oauth_client:family_name',
104+
'given_name' => 'privacy:metadata:oauth_client:given_name',
105+
'middle_name' => 'privacy:metadata:oauth_client:middle_name',
106+
'nickname' => 'privacy:metadata:oauth_client:nickname',
107+
'preferred_username' => 'privacy:metadata:oauth_client:preferred_username',
108+
'profile' => 'privacy:metadata:oauth_client:profile',
109+
'picture' => 'privacy:metadata:oauth_client:picture',
110+
'zoneinfo' => 'privacy:metadata:oauth_client:zoneinfo',
111+
'updated_at' => 'privacy:metadata:oauth_client:updated_at',
112+
'email' => 'privacy:metadata:oauth_client:email',
113+
'phone_number' => 'privacy:metadata:oauth_client:phone_number',
114+
'street_address' => 'privacy:metadata:oauth_client:street_address',
115+
'locality ' => 'privacy:metadata:oauth_client:locality',
116+
'country' => 'privacy:metadata:oauth_client:country',
117+
'enrolments' => 'privacy:metadata:oauth_client:enrolments',
118+
], 'privacy:metadata:oauth_client');
119+
120+
// Plugin also access user and enrolment data but does not store or modify it.
121+
// So we dont have to specify that.
122+
123+
return $collection;
124+
}
125+
126+
/**
127+
* Get the list of contexts that contain user information for the specified user.
128+
*
129+
* @param int $userid The user to search.
130+
* @return contextlist $contextlist The list of contexts used in this plugin.
131+
*/
132+
public static function get_contexts_for_userid(int $userid): contextlist {
133+
134+
$contextlist = new \core_privacy\local\request\contextlist();
135+
return $contextlist->add_user_context($userid);
136+
137+
}
138+
139+
/**
140+
* Get the list of users who have data within a context.
141+
*
142+
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
143+
*/
144+
public static function get_users_in_context(userlist $userlist) {
145+
global $DB;
146+
$context = $userlist->get_context();
147+
148+
if (!is_a($context, \context_user::class)) {
149+
return;
150+
}
151+
$userid = $context->instanceid;
152+
153+
$hasdata = false;
154+
155+
$hasdata = $hasdata || $DB->record_exists('local_oauth_user_auth_scopes', ['user_id' => $userid]);
156+
$hasdata = $hasdata || $DB->record_exists('local_oauth_refresh_tokens', ['user_id' => $userid]);
157+
$hasdata = $hasdata || $DB->record_exists('local_oauth_auth_codes', ['user_id' => $userid]);
158+
$hasdata = $hasdata || $DB->record_exists('local_oauth_access_tokens', ['user_id' => $userid]);
159+
160+
if ($hasdata) {
161+
$userlist->add_user($userid);
162+
}
163+
}
164+
165+
/**
166+
* Export all user data for the specified user, in the specified contexts, using the supplied exporter instance.
167+
*
168+
* @param approved_contextlist $contextlist The approved contexts to export information for.
169+
*/
170+
public static function export_user_data(approved_contextlist $contextlist) {
171+
global $DB;
172+
$user = $contextlist->get_user();
173+
$context = \context_user::instance($user->id);
174+
$subcontext = [
175+
get_string('plugin', 'local_oauth'),
176+
get_string('pluginname', 'local_oauth'),
177+
];
178+
$notexportedstr = get_string('privacy:request:notexportedsecurity', 'local_oauth');
179+
180+
$userauthscopes = $DB->get_records('local_oauth_user_auth_scopes', ['user_id' => $user->id]);
181+
foreach ($userauthscopes as $scope) {
182+
$scope->user_id = transform::user($scope->user_id);
183+
writer::with_context($context)->export_data( array_merge($subcontext, [
184+
$scope->client_id,
185+
$scope->scope,
186+
get_string('privacy:metadata:local_oauth:auth_scopes', 'local_oauth'),
187+
]), $scope);
188+
}
189+
190+
$refreshtokens = $DB->get_records('local_oauth_refresh_tokens', ['user_id' => $user->id]);
191+
foreach ($refreshtokens as $token) {
192+
$token->user_id = transform::user($token->user_id);
193+
$token->expires = transform::datetime($token->expires);
194+
$token->refresh_token = $notexportedstr;
195+
writer::with_context($context)->export_data(array_merge($subcontext, [
196+
$token->client_id,
197+
$token->scope,
198+
get_string('privacy:metadata:local_oauth:refresh_tokens', 'local_oauth'),
199+
]), $token);
200+
}
201+
202+
$oauthcodes = $DB->get_records('local_oauth_auth_codes', ['user_id' => $user->id]);
203+
foreach ($oauthcodes as $code) {
204+
$code->user_id = transform::user($code->user_id);
205+
$code->expires = transform::datetime($code->expires);
206+
$code->authorization_code = $notexportedstr;
207+
writer::with_context($context)->export_data(array_merge($subcontext, [
208+
$code->client_id,
209+
$code->scope,
210+
get_string('privacy:metadata:local_oauth:auth_codes', 'local_oauth'),
211+
]), $code);
212+
}
213+
214+
$accesstokens = $DB->get_records('local_oauth_access_tokens', ['user_id' => $user->id]);
215+
foreach ($accesstokens as $token) {
216+
$token->user_id = transform::user($token->user_id);
217+
$token->expires = transform::datetime($token->expires);
218+
$token->access_token = $notexportedstr;
219+
writer::with_context($context)->export_data( array_merge($subcontext, [
220+
$token->client_id,
221+
$token->scope,
222+
get_string('privacy:metadata:local_oauth:access_tokens', 'local_oauth'),
223+
]), $token);
224+
}
225+
}
226+
227+
228+
/**
229+
* Delete all personal data for all users in the specified context.
230+
*
231+
* @param context $context Context to delete data from.
232+
*/
233+
public static function delete_data_for_all_users_in_context(\context $context) {
234+
235+
if ($context->contextlevel != CONTEXT_USER) {
236+
return;
237+
}
238+
$userid = $context->instanceid;
239+
self::delete_user(userid);
240+
}
241+
242+
/**
243+
* Delete multiple users within a single context.
244+
*
245+
* @param approved_userlist $userlist The approved context and user information to delete information for.
246+
*/
247+
public static function delete_data_for_users(approved_userlist $userlist) {
248+
249+
$context = $userlist->get_context();
250+
if ($context->contextlevel != CONTEXT_USER) {
251+
return;
252+
}
253+
254+
foreach ($userlist->get_userids() as $userid) {
255+
self::delete_user($userid);
256+
}
257+
}
258+
259+
/**
260+
* Delete user data in the list of given contexts.
261+
*
262+
* @param approved_contextlist $contextlist the list of contexts.
263+
*/
264+
public static function delete_data_for_user(approved_contextlist $contextlist) {
265+
266+
if (empty($contextlist->count())) {
267+
return;
268+
}
269+
$userid = $contextlist->get_user()->id;
270+
271+
self::delete_user(userid);
272+
}
273+
274+
/**
275+
* Delete user in database
276+
*
277+
* @param int $userid The use to delete local_oauth data from
278+
*/
279+
private static function delete_user(int $userid) {
280+
global $DB;
281+
$DB->delete_records('local_oauth_user_auth_scopes', ['user_id' => $userid]);
282+
$DB->delete_records('local_oauth_refresh_tokens', ['user_id' => $userid]);
283+
$DB->delete_records('local_oauth_auth_codes', ['user_id' => $userid]);
284+
$DB->delete_records('local_oauth_access_tokens', ['user_id' => $userid]);
285+
286+
}
287+
288+
}
289+

0 commit comments

Comments
 (0)