Skip to content

Commit 954696d

Browse files
Copilotndrwnaguib
andcommitted
Implement Privacy API for GDPR compliance
Co-authored-by: ndrwnaguib <24280372+ndrwnaguib@users.noreply.github.com>
1 parent 0c89f18 commit 954696d

File tree

4 files changed

+540
-0
lines changed

4 files changed

+540
-0
lines changed

classes/privacy/provider.php

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
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 <http://www.gnu.org/licenses/>.
16+
17+
/**
18+
* Privacy implementation for local_onlinejudge.
19+
*
20+
* @package local_onlinejudge
21+
* @copyright 2024 Online Judge Contributors
22+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23+
*/
24+
25+
namespace local_onlinejudge\privacy;
26+
27+
use core_privacy\local\metadata\collection;
28+
use core_privacy\local\request\approved_contextlist;
29+
use core_privacy\local\request\approved_userlist;
30+
use core_privacy\local\request\context;
31+
use core_privacy\local\request\contextlist;
32+
use core_privacy\local\request\userlist;
33+
use core_privacy\local\request\writer;
34+
use core_privacy\local\request\transform;
35+
36+
/**
37+
* Privacy provider for local_onlinejudge.
38+
*/
39+
class provider implements
40+
\core_privacy\local\metadata\provider,
41+
\core_privacy\local\request\plugin\provider,
42+
\core_privacy\local\request\core_userlist_provider {
43+
44+
/**
45+
* Get the language string identifier with the component's language
46+
* file to explain why this plugin stores no data.
47+
*
48+
* @param collection $collection The initialised collection to add items to.
49+
* @return collection A listing of user data stored through this system.
50+
*/
51+
public static function get_metadata(collection $collection): collection {
52+
$collection->add_database_table('onlinejudge_tasks', [
53+
'cmid' => 'privacy:metadata:onlinejudge_tasks:cmid',
54+
'userid' => 'privacy:metadata:onlinejudge_tasks:userid',
55+
'language' => 'privacy:metadata:onlinejudge_tasks:language',
56+
'input' => 'privacy:metadata:onlinejudge_tasks:input',
57+
'output' => 'privacy:metadata:onlinejudge_tasks:output',
58+
'stdout' => 'privacy:metadata:onlinejudge_tasks:stdout',
59+
'stderr' => 'privacy:metadata:onlinejudge_tasks:stderr',
60+
'compileroutput' => 'privacy:metadata:onlinejudge_tasks:compileroutput',
61+
'infoteacher' => 'privacy:metadata:onlinejudge_tasks:infoteacher',
62+
'infostudent' => 'privacy:metadata:onlinejudge_tasks:infostudent',
63+
'cpuusage' => 'privacy:metadata:onlinejudge_tasks:cpuusage',
64+
'memusage' => 'privacy:metadata:onlinejudge_tasks:memusage',
65+
'submittime' => 'privacy:metadata:onlinejudge_tasks:submittime',
66+
'judgetime' => 'privacy:metadata:onlinejudge_tasks:judgetime',
67+
'var1' => 'privacy:metadata:onlinejudge_tasks:var1',
68+
'var2' => 'privacy:metadata:onlinejudge_tasks:var2',
69+
'var3' => 'privacy:metadata:onlinejudge_tasks:var3',
70+
'var4' => 'privacy:metadata:onlinejudge_tasks:var4',
71+
'status' => 'privacy:metadata:onlinejudge_tasks:status',
72+
], 'privacy:metadata:onlinejudge_tasks');
73+
74+
return $collection;
75+
}
76+
77+
/**
78+
* Get the list of contexts that contain user information for the specified user.
79+
*
80+
* @param int $userid The user to search.
81+
* @return contextlist The contextlist containing the list of contexts used in this plugin.
82+
*/
83+
public static function get_contexts_for_userid(int $userid): contextlist {
84+
$contextlist = new contextlist();
85+
86+
// Find contexts where user has submitted tasks.
87+
$sql = "SELECT ctx.id
88+
FROM {context} ctx
89+
JOIN {course_modules} cm ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
90+
JOIN {onlinejudge_tasks} ojt ON ojt.cmid = cm.id
91+
WHERE ojt.userid = :userid";
92+
93+
$contextlist->add_from_sql($sql, [
94+
'userid' => $userid,
95+
'contextlevel' => CONTEXT_MODULE,
96+
]);
97+
98+
return $contextlist;
99+
}
100+
101+
/**
102+
* Get the list of users who have data within a context.
103+
*
104+
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
105+
*/
106+
public static function get_users_in_context(userlist $userlist) {
107+
$context = $userlist->get_context();
108+
109+
if (!$context instanceof \context_module) {
110+
return;
111+
}
112+
113+
$sql = "SELECT ojt.userid
114+
FROM {onlinejudge_tasks} ojt
115+
JOIN {course_modules} cm ON cm.id = ojt.cmid
116+
WHERE cm.id = :cmid";
117+
118+
$userlist->add_from_sql('userid', $sql, ['cmid' => $context->instanceid]);
119+
}
120+
121+
/**
122+
* Export all user data for the specified user, in the specified contexts.
123+
*
124+
* @param approved_contextlist $contextlist The approved contexts to export information for.
125+
*/
126+
public static function export_user_data(approved_contextlist $contextlist) {
127+
global $DB;
128+
129+
if (empty($contextlist->count())) {
130+
return;
131+
}
132+
133+
$user = $contextlist->get_user();
134+
$userid = $user->id;
135+
136+
foreach ($contextlist->get_contexts() as $context) {
137+
if (!$context instanceof \context_module) {
138+
continue;
139+
}
140+
141+
$cmid = $context->instanceid;
142+
143+
// Get all tasks for this user in this context.
144+
$tasks = $DB->get_records('onlinejudge_tasks', [
145+
'userid' => $userid,
146+
'cmid' => $cmid,
147+
]);
148+
149+
if (!empty($tasks)) {
150+
$taskdata = [];
151+
foreach ($tasks as $task) {
152+
$taskdata[] = [
153+
'language' => $task->language,
154+
'submittime' => transform::datetime($task->submittime),
155+
'judgetime' => $task->judgetime ? transform::datetime($task->judgetime) : null,
156+
'status' => $task->status,
157+
'cpuusage' => $task->cpuusage,
158+
'memusage' => $task->memusage,
159+
'compileroutput' => $task->compileroutput,
160+
'infostudent' => $task->infostudent,
161+
'var1' => $task->var1,
162+
'var2' => $task->var2,
163+
'var3' => $task->var3,
164+
'var4' => $task->var4,
165+
];
166+
}
167+
168+
writer::with_context($context)->export_data(
169+
[get_string('pluginname', 'local_onlinejudge')],
170+
(object) ['tasks' => $taskdata]
171+
);
172+
}
173+
}
174+
}
175+
176+
/**
177+
* Delete all data for all users in the specified context.
178+
*
179+
* @param context $context The context to delete in.
180+
*/
181+
public static function delete_data_for_all_users_in_context(\context $context) {
182+
global $DB;
183+
184+
if (!$context instanceof \context_module) {
185+
return;
186+
}
187+
188+
$cmid = $context->instanceid;
189+
$DB->delete_records('onlinejudge_tasks', ['cmid' => $cmid]);
190+
}
191+
192+
/**
193+
* Delete all user data for the specified user, in the specified contexts.
194+
*
195+
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
196+
*/
197+
public static function delete_data_for_user(approved_contextlist $contextlist) {
198+
global $DB;
199+
200+
if (empty($contextlist->count())) {
201+
return;
202+
}
203+
204+
$userid = $contextlist->get_user()->id;
205+
206+
foreach ($contextlist->get_contexts() as $context) {
207+
if (!$context instanceof \context_module) {
208+
continue;
209+
}
210+
211+
$cmid = $context->instanceid;
212+
$DB->delete_records('onlinejudge_tasks', [
213+
'userid' => $userid,
214+
'cmid' => $cmid,
215+
]);
216+
}
217+
}
218+
219+
/**
220+
* Delete multiple users within a single context.
221+
*
222+
* @param approved_userlist $userlist The approved context and user information to delete information for.
223+
*/
224+
public static function delete_data_for_users(approved_userlist $userlist) {
225+
global $DB;
226+
227+
$context = $userlist->get_context();
228+
229+
if (!$context instanceof \context_module) {
230+
return;
231+
}
232+
233+
$userids = $userlist->get_userids();
234+
if (empty($userids)) {
235+
return;
236+
}
237+
238+
$cmid = $context->instanceid;
239+
240+
list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
241+
$params = array_merge(['cmid' => $cmid], $userparams);
242+
243+
$DB->delete_records_select('onlinejudge_tasks', "cmid = :cmid AND userid $usersql", $params);
244+
}
245+
}

0 commit comments

Comments
 (0)