diff --git a/ChangeLog b/ChangeLog index c154bc4..7d480a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,10 @@ Make selection session window 80% of window width +2020-03-13 Nick Charles + + GDPR compliance + 2020-03-11 Nick Charles Replace starburst icons with open sourced versions diff --git a/backup/moodle2/backup_equella_stepslib.php b/backup/moodle2/backup_equella_stepslib.php index 66d284a..f2a4ebe 100644 --- a/backup/moodle2/backup_equella_stepslib.php +++ b/backup/moodle2/backup_equella_stepslib.php @@ -18,7 +18,7 @@ class backup_equella_activity_structure_step extends backup_activity_structure_s protected function define_structure() { $equella = new backup_nested_element('equella', array('id'), - array('course','name','intro','introformat','timecreated','timemodified','url','mimetype','popup','activation','uuid','version','path','attachmentuuid','ltisalt') + array('course','name','intro','introformat','timecreated','timemodified','url','mimetype','popup','activation','uuid','version','path','attachmentuuid','ltisalt','filename','metadata') ); $equella->set_source_table('equella', array('id' => backup::VAR_ACTIVITYID)); $equella->annotate_files('mod_equella', 'intro', null); diff --git a/callbackmulti.php b/callbackmulti.php index 834c8fd..d9e0104 100644 --- a/callbackmulti.php +++ b/callbackmulti.php @@ -36,7 +36,7 @@ $mod->name = htmlspecialchars($link['name'], ENT_COMPAT, 'UTF-8'); $mod->intro = htmlspecialchars($link['description']); $mod->introformat = FORMAT_HTML; - $mod->attachmentuuid = clean_param($link['attachmentUuid'], PARAM_ALPHAEXT); + $mod->attachmentuuid = clean_param($link['attachmentUuid'], PARAM_ALPHANUMEXT); $mod->url = clean_param($link['url'], PARAM_URL); $mod->metadata = serialize($link); $targetsection = $sectionnum; @@ -57,7 +57,7 @@ } if (isset($link['activationUuid'])) { - $mod->activation = clean_param($link['activationUuid'], PARAM_ALPHAEXT); + $mod->activation = clean_param($link['activationUuid'], PARAM_ALPHANUMEXT); } $equellaid = equella_add_instance($mod); diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php new file mode 100644 index 0000000..a5e3a66 --- /dev/null +++ b/classes/privacy/provider.php @@ -0,0 +1,90 @@ +add_external_location_link('lti_client', [ + 'userid' => 'privacy:metadata:lti_client:userid', + 'roles' => 'privacy:metadata:lti_client:roles', + 'fullname' => 'privacy:metadata:lti_client:fullname', + 'givenname' => 'privacy:metadata:lti_client:givenname', + 'familyname' => 'privacy:metadata:lti_client:familyname', + 'email' => 'privacy:metadata:lti_client:email', + + ], 'privacy:metadata:lti_client'); + + return $collection; + + } + + /** + * Get the list of contexts that contain user information for the specified user. + * + * @param int $userid The user to search. + * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. + */ + public static function get_contexts_for_userid(int $userid) : contextlist { + return new 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(userlist $userlist) { + } + + /** + * Export all user data for the specified user, in the specified contexts. + * + * @param approved_contextlist $contextlist The approved contexts to export information for. + */ + public static function export_user_data(approved_contextlist $contextlist) { + } + + /** + * Delete all data for all users in the specified context. + * + * @param context $context The specific context to delete data for. + */ + public static function delete_data_for_all_users_in_context(\context $context) { + } + + /** + * 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) { + } + + /** + * Delete multiple users within a single context. + * + * @param approved_userlist $userlist The approved context and user information to delete information for. + */ + public static function delete_data_for_users(approved_userlist $userlist) { + } +} diff --git a/externallib.php b/externallib.php index 445ae8e..956d755 100644 --- a/externallib.php +++ b/externallib.php @@ -230,24 +230,31 @@ public static function get_course_code_returns() { public static function list_courses_for_user($username, $modifiable, $archived) { global $DB, $CFG; - $courselist = array(); - $params = self::validate_parameters(self::list_courses_for_user_parameters(), array('user' => $username,'modifiable' => $modifiable,'archived' => $archived)); + $params = self::validate_parameters(self::list_courses_for_user_parameters(), + array('user' => $username, 'modifiable' => $modifiable, 'archived' => $archived)); + $userobj = self::get_user_by_username($params['user']); + + $fields = 'fullname, visible, idnumber'; if ($modifiable) { - $userobj = self::get_user_by_username($params['user']); + $courses = get_user_capability_course(self::WRITE_PERMISSION, $userobj->id, true, $fields); } else { - $userobj = null; + // The courses enrolled within. + $enrolledcourses = enrol_get_users_courses($userobj->id, true, $fields); + + // The courses viewable without participation. + $viewcourses = get_user_capability_course(self::READ_PERMISSION, $userobj->id, true, $fields); + if ($viewcourses === false) { + $viewcourses = array(); + } else { + // Reindex with the course id. + $viewcourses = array_column($viewcourses, null, 'id'); + } + + $courses = $enrolledcourses + $viewcourses; } - $coursefields = "c.id,c.fullname,c.visible,c.idnumber"; - $contextfields = "ctx.id AS contextid,ctx.contextlevel,ctx.instanceid,ctx.path,ctx.depth"; - $sql = "SELECT $coursefields,$contextfields - FROM {context} ctx - JOIN {course} c ON c.id=ctx.instanceid - WHERE ctx.contextlevel=? "; - - $courses = $DB->get_recordset_sql($sql, array(CONTEXT_COURSE)); - foreach($courses as $course) { - // Ignore site level course + $courselist = array(); + foreach ($courses as $course) { if ($course->id == SITEID) { continue; } @@ -270,7 +277,7 @@ public static function list_courses_for_user($username, $modifiable, $archived) 'courseid' => $course->id, 'coursecode' => $course->idnumber, 'coursename' => $course->fullname, - 'archived' => !($course->visible) + 'archived' => !($course->visible), ); } } diff --git a/lang/en/equella.php b/lang/en/equella.php index 05d0bdf..02dc7fa 100644 --- a/lang/en/equella.php +++ b/lang/en/equella.php @@ -164,4 +164,15 @@ $string['push.attachment'] = 'Selected attachment'; */ -$string['webserviceerror'] = '{$a}'; \ No newline at end of file +$string['webserviceerror'] = '{$a}'; + +//////////////////////////////////////////////////////// +// GDPR compliance + +$string['privacy:metadata:lti_client'] = 'In order to integrate with a remote openEQUELLA LTI service, user data needs to be exchanged with that service. Contact your openEQUELLA administrator for more information.'; +$string['privacy:metadata:lti_client:userid'] = 'The userid is sent from Moodle to allow you to access your data on the remote system.'; +$string['privacy:metadata:lti_client:givenname'] = 'Your given name is sent to the openEQUELLA system for SSO login'; +$string['privacy:metadata:lti_client:familyname'] = 'Your family name is sent to the openEQUELLA system for SSO login'; +$string['privacy:metadata:lti_client:fullname'] = 'Your full name is sent to the openEQUELLA system for SSO login'; +$string['privacy:metadata:lti_client:email'] = 'Your email address is sent to the openEQUELLA system for SSO login'; +$string['privacy:metadata:lti_client:roles'] = 'Your Moodle roles are sent to the openEQUELLA system, which allows you to access your data on the remote system.';