Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://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
 * Contains class mod_zoom\privacy\provider
19
 *
20
 * @package    mod_zoom
21
 * @copyright  2018 UC Regents
22
 * @author     Kubilay Agi
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
namespace mod_zoom\privacy;
27
 
28
use context;
29
use context_module;
30
use core_privacy\local\metadata\collection;
31
use core_privacy\local\metadata\provider as metadata_provider;
32
use core_privacy\local\request\approved_contextlist;
33
use core_privacy\local\request\approved_userlist;
34
use core_privacy\local\request\contextlist;
35
use core_privacy\local\request\core_userlist_provider;
36
use core_privacy\local\request\helper;
37
use core_privacy\local\request\plugin\provider as request_plugin_provider;
38
use core_privacy\local\request\transform;
39
use core_privacy\local\request\userlist;
40
use core_privacy\local\request\writer;
41
 
42
/**
43
 * Ad hoc task that performs the actions for approved data privacy requests.
44
 */
45
class provider implements core_userlist_provider, metadata_provider, request_plugin_provider {
46
    /**
47
     * Returns meta data about this system.
48
     *
49
     * @param   collection $coll The collection to add metadata to.
50
     * @return  collection  The array of metadata
51
     */
52
    public static function get_metadata(collection $coll): collection {
53
        // Add all user data fields to the collection.
54
 
55
        $coll->add_database_table('zoom_meeting_participants', [
56
            'name' => 'privacy:metadata:zoom_meeting_participants:name',
57
            'user_email' => 'privacy:metadata:zoom_meeting_participants:user_email',
58
            'join_time' => 'privacy:metadata:zoom_meeting_participants:join_time',
59
            'leave_time' => 'privacy:metadata:zoom_meeting_participants:leave_time',
60
            'duration' => 'privacy:metadata:zoom_meeting_participants:duration',
61
        ], 'privacy:metadata:zoom_meeting_participants');
62
 
63
        $coll->add_database_table(
64
            'zoom_meeting_details',
65
            ['topic' => 'privacy:metadata:zoom_meeting_details:topic'],
66
            'privacy:metadata:zoom_meeting_details'
67
        );
68
 
69
        $coll->add_database_table(
70
            'zoom_meeting_recordings_view',
71
            ['userid' => 'privacy:metadata:zoom_meeting_view:userid'],
72
            'privacy:metadata:zoom_meeting_view'
73
        );
74
 
75
        $coll->add_database_table(
76
            'zoom_breakout_participants',
77
            ['userid' => 'privacy:metadata:zoom_breakout_participants:userid'],
78
            'privacy:metadata:zoom_breakout_participants'
79
        );
80
 
81
        return $coll;
82
    }
83
 
84
    /**
85
     * Get the list of contexts that contain user information for the specified user.
86
     *
87
     * @param   int $userid The user to search.
88
     * @return  contextlist   $contextlist  The list of contexts used in this plugin.
89
     */
90
    public static function get_contexts_for_userid(int $userid): contextlist {
91
        // Query the database for context IDs give a specific user ID and return these to the user.
92
 
93
        $contextlist = new contextlist();
94
 
95
        $sql = 'SELECT c.id
96
                  FROM {context} c
97
            INNER JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
98
            INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
99
            INNER JOIN {zoom} z ON z.id = cm.instance
100
            LEFT JOIN {zoom_meeting_details} zmd ON zmd.zoomid = z.id
101
            LEFT JOIN {zoom_meeting_participants} zmp ON zmp.detailsid = zmd.id
102
            LEFT JOIN {zoom_meeting_recordings} zmr ON zmr.zoomid = z.id
103
            LEFT JOIN {zoom_meeting_recordings_view} zmrv ON zmrv.recordingsid = zmr.id
104
                 WHERE zmp.userid = :userid1 OR zmrv.userid = :userid2
105
        ';
106
 
107
        $params = [
108
            'modname' => 'zoom',
109
            'contextlevel' => CONTEXT_MODULE,
110
            'userid1' => $userid,
111
            'userid2' => $userid,
112
        ];
113
 
114
        $contextlist->add_from_sql($sql, $params);
115
 
116
        return $contextlist;
117
    }
118
 
119
    /**
120
     * Get the list of users who have data within a context.
121
     *
122
     * @param   userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
123
     */
124
    public static function get_users_in_context(userlist $userlist) {
125
        $context = $userlist->get_context();
126
 
127
        if (!($context instanceof context_module)) {
128
            return;
129
        }
130
 
131
        $params = [
132
            'instanceid' => $context->instanceid,
133
            'modulename' => 'zoom',
134
        ];
135
 
136
        $sql = "SELECT zmp.userid
137
                  FROM {zoom_meeting_participants} zmp
138
                  JOIN {zoom_meeting_details} zmd ON zmd.id = zmp.detailsid
139
                  JOIN {zoom} z ON zmd.zoomid = z.id
140
                  JOIN {modules} m ON m.name = :modulename
141
                  JOIN {course_modules} cm ON z.id = cm.instance AND m.id = cm.module
142
                 WHERE cm.id = :instanceid";
143
 
144
        $userlist->add_from_sql('userid', $sql, $params);
145
 
146
        $sql = "SELECT zmrv.userid
147
                  FROM {zoom_meeting_recordings_view} zmrv
148
                  JOIN {zoom_meeting_recordings} zmr ON zmr.id = zmrv.recordingsid
149
                  JOIN {zoom} z ON zmr.zoomid = z.id
150
                  JOIN {modules} m ON m.name = :modulename
151
                  JOIN {course_modules} cm ON z.id = cm.instance AND m.id = cm.module
152
                 WHERE cm.id = :instanceid";
153
 
154
        $userlist->add_from_sql('userid', $sql, $params);
155
 
156
        $sql = "SELECT zbp.userid
157
                  FROM {zoom_breakout_participants} zbp
158
                  JOIN {zoom_meeting_breakout_rooms} zmbr ON zbp.breakoutroomid = zmbr.id
159
                  JOIN {zoom} z ON zmbr.zoomid = z.id
160
                  JOIN {modules} m ON m.name = :modulename
161
                  JOIN {course_modules} cm ON z.id = cm.instance AND m.id = cm.module
162
                 WHERE cm.id = :instanceid";
163
 
164
        $userlist->add_from_sql('userid', $sql, $params);
165
    }
166
 
167
    /**
168
     * Export all user data for the specified user, in the specified contexts, using the supplied exporter instance.
169
     *
170
     * @param   approved_contextlist    $contextlist    The approved contexts to export information for.
171
     * @link http://tandl.churchward.ca/2018/06/implementing-moodles-privacy-api-in.html
172
     */
173
    public static function export_user_data(approved_contextlist $contextlist) {
174
        global $DB;
175
 
176
        if (empty($contextlist->count())) {
177
            return;
178
        }
179
 
180
        $user = $contextlist->get_user();
181
 
182
        [$contextsql, $contextparams] = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
183
 
184
        $sql = "SELECT zmp.id,
185
                       zmd.topic,
186
                       zmp.name,
187
                       zmp.user_email,
188
                       zmp.join_time,
189
                       zmp.leave_time,
190
                       zmp.duration,
191
                       cm.id AS cmid
192
                  FROM {context} c
193
            INNER JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
194
            INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
195
            INNER JOIN {zoom} z ON z.id = cm.instance
196
            INNER JOIN {zoom_meeting_details} zmd ON zmd.zoomid = z.id
197
            INNER JOIN {zoom_meeting_participants} zmp ON zmp.detailsid = zmd.id
198
                 WHERE c.id $contextsql
199
                       AND zmp.userid = :userid
200
              ORDER BY cm.id ASC
201
        ";
202
 
203
        $params = [
204
            'modname' => 'zoom',
205
            'contextlevel' => CONTEXT_MODULE,
206
            'userid' => $user->id,
207
        ] + $contextparams;
208
 
209
        $participantinstances = $DB->get_recordset_sql($sql, $params);
210
        foreach ($participantinstances as $participantinstance) {
211
            $context = context_module::instance($participantinstance->cmid);
212
            $contextdata = helper::get_context_data($context, $user);
213
 
214
            $instancedata = [
215
                'topic' => $participantinstance->topic,
216
                'participant_name' => $participantinstance->name,
217
                'user_email' => $participantinstance->user_email,
218
                'join_time' => transform::datetime($participantinstance->join_time),
219
                'leave_time' => transform::datetime($participantinstance->leave_time),
220
                'duration' => $participantinstance->duration,
221
            ];
222
 
223
            $contextdata = (object) array_merge((array) $contextdata, $instancedata);
224
            writer::with_context($context)->export_data([], $contextdata);
225
        }
226
 
227
        $participantinstances->close();
228
 
229
        $sql = "SELECT zmrv.id,
230
                       zmr.name,
231
                       zmrv.userid,
232
                       zmrv.viewed,
233
                       zmrv.timemodified,
234
                       cm.id AS cmid
235
                  FROM {context} c
236
            INNER JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
237
            INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
238
            INNER JOIN {zoom} z ON z.id = cm.instance
239
            INNER JOIN {zoom_meeting_recordings} zmr ON zmr.zoomid = z.id
240
            INNER JOIN {zoom_meeting_recordings_view} zmrv ON zmrv.recordingsid = zmr.id
241
                 WHERE c.id $contextsql
242
                       AND zmrv.userid = :userid
243
              ORDER BY cm.id ASC
244
        ";
245
 
246
        $params = [
247
            'modname' => 'zoom',
248
            'contextlevel' => CONTEXT_MODULE,
249
            'userid' => $user->id,
250
        ] + $contextparams;
251
 
252
        $recordingviewinstances = $DB->get_recordset_sql($sql, $params);
253
        foreach ($recordingviewinstances as $recordingviewinstance) {
254
            $context = context_module::instance($recordingviewinstance->cmid);
255
            $contextdata = helper::get_context_data($context, $user);
256
 
257
            $instancedata = [
258
                'recording_name' => $recordingviewinstance->name,
259
                'userid' => $recordingviewinstance->userid,
260
                'viewed' => $recordingviewinstance->viewed,
261
                'timemodified' => transform::datetime($recordingviewinstance->timemodified),
262
            ];
263
 
264
            $contextdata = (object) array_merge((array) $contextdata, $instancedata);
265
            writer::with_context($context)->export_data([], $contextdata);
266
        }
267
 
268
        $recordingviewinstances->close();
269
    }
270
 
271
    /**
272
     * Delete all personal data for all users in the specified context.
273
     *
274
     * @param context $context Context to delete data from.
275
     */
276
    public static function delete_data_for_all_users_in_context(context $context) {
277
        global $DB;
278
 
279
        if (!($context instanceof context_module)) {
280
            return;
281
        }
282
 
283
        // We delete each participant entry manually because deletes do not cascade.
284
        if ($cm = get_coursemodule_from_id('zoom', $context->instanceid)) {
285
            $meetingdetails = $DB->get_records('zoom_meeting_details', ['zoomid' => $cm->instance]);
286
            foreach ($meetingdetails as $meetingdetail) {
287
                $DB->delete_records('zoom_meeting_participants', ['detailsid' => $meetingdetail->id]);
288
            }
289
 
290
            $DB->delete_records('zoom_meeting_details', ['zoomid' => $cm->instance]);
291
 
292
            $meetingrecordings = $DB->get_records('zoom_meeting_recordings', ['zoomid' => $cm->instance]);
293
            foreach ($meetingrecordings as $recording) {
294
                $DB->delete_records('zoom_meeting_recordings_view', ['recordingsid' => $recording->id]);
295
            }
296
 
297
            $DB->delete_records('zoom_meeting_recordings', ['zoomid' => $cm->instance]);
298
 
299
            $breakoutrooms = $DB->get_records('zoom_meeting_breakout_rooms', ['zoomid' => $cm->instance]);
300
            foreach ($breakoutrooms as $room) {
301
                $DB->delete_records('zoom_breakout_participants', ['breakoutroomid' => $room->id]);
302
            }
303
 
304
            $DB->delete_records('zoom_meeting_breakout_rooms', ['zoomid' => $cm->instance]);
305
        }
306
    }
307
 
308
    /**
309
     * Delete all user data for the specified user, in the specified contexts.
310
     *
311
     * @param   approved_contextlist    $contextlist    The approved contexts and user information to delete information for.
312
     */
313
    public static function delete_data_for_user(approved_contextlist $contextlist) {
314
        global $DB;
315
 
316
        if (empty($contextlist->count())) {
317
            return;
318
        }
319
 
320
        $user = $contextlist->get_user();
321
 
322
        foreach ($contextlist->get_contexts() as $context) {
323
            if (!($context instanceof context_module)) {
324
                continue;
325
            }
326
 
327
            if ($cm = get_coursemodule_from_id('zoom', $context->instanceid)) {
328
                $meetingdetails = $DB->get_records('zoom_meeting_details', ['zoomid' => $cm->instance]);
329
                foreach ($meetingdetails as $meetingdetail) {
330
                    $DB->delete_records('zoom_meeting_participants', ['detailsid' => $meetingdetail->id, 'userid' => $user->id]);
331
                }
332
 
333
                $meetingrecordings = $DB->get_records('zoom_meeting_recordings', ['zoomid' => $cm->instance]);
334
                foreach ($meetingrecordings as $recording) {
335
                    $DB->delete_records('zoom_meeting_recordings_view', ['recordingsid' => $recording->id, 'userid' => $user->id]);
336
                }
337
 
338
                $breakoutrooms = $DB->get_records('zoom_meeting_breakout_rooms', ['zoomid' => $cm->instance]);
339
                foreach ($breakoutrooms as $room) {
340
                    $DB->delete_records('zoom_breakout_participants', ['breakoutroomid' => $room->id, 'userid' => $user->id]);
341
                }
342
            }
343
        }
344
    }
345
 
346
    /**
347
     * Delete multiple users within a single context.
348
     *
349
     * @param   approved_userlist       $userlist The approved context and user information to delete information for.
350
     */
351
    public static function delete_data_for_users(approved_userlist $userlist) {
352
        global $DB;
353
        $context = $userlist->get_context();
354
 
355
        if (!($context instanceof context_module)) {
356
            return;
357
        }
358
 
359
        // Prepare SQL to gather all completed IDs.
360
        $userids = $userlist->get_userids();
361
        [$insql, $inparams] = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
362
        $params = array_merge($inparams, ['contextid' => $context->id, 'modlevel' => CONTEXT_MODULE]);
363
 
364
        $sql = "SELECT zmd.id
365
                  FROM {zoom_meeting_details} zmd
366
                  JOIN {zoom} z ON zmd.zoomid = z.id
367
                  JOIN {modules} m ON m.name = 'zoom'
368
                  JOIN {course_modules} cm ON z.id = cm.instance AND m.id = cm.module
369
                  JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :modlevel
370
                 WHERE ctx.id = :contextid";
371
 
372
        $DB->delete_records_select('zoom_meeting_participants', "userid $insql AND detailsid IN ($sql)", $params);
373
 
374
        $sql = "SELECT zmr.id
375
                  FROM {zoom_meeting_recordings} zmr
376
                  JOIN {zoom} z ON zmr.zoomid = z.id
377
                  JOIN {modules} m ON m.name = 'zoom'
378
                  JOIN {course_modules} cm ON z.id = cm.instance AND m.id = cm.module
379
                  JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :modlevel
380
                 WHERE ctx.id = :contextid";
381
 
382
        $DB->delete_records_select('zoom_meeting_recordings_view', "userid $insql AND recordingsid IN ($sql)", $params);
383
 
384
        $sql = "SELECT zmbr.id
385
                  FROM {zoom_meeting_breakout_rooms} zmbr
386
                  JOIN {zoom} z ON zmbr.zoomid = z.id
387
                  JOIN {modules} m ON m.name = 'zoom'
388
                  JOIN {course_modules} cm ON z.id = cm.instance AND m.id = cm.module
389
                  JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :modlevel
390
                 WHERE ctx.id = :contextid";
391
 
392
        $DB->delete_records_select('zoom_breakout_participants', "userid $insql AND breakoutroomid IN ($sql)", $params);
393
    }
394
}