From 8d3238d8587fc4895b9a2ba5bb969bc1bfbdb1fa Mon Sep 17 00:00:00 2001 From: David Monllao Date: Wed, 18 Apr 2018 17:22:13 +0200 Subject: [PATCH] Merge branch 'MDL-61958-master' of git://github.com/sarjona/moodle --- lang/en/moodle.php | 2 +- lang/en/rss.php | 32 ++++++++ rss/classes/privacy/provider.php | 137 +++++++++++++++++++++++++++++++ rss/renderer.php | 2 +- rss/tests/privacy_test.php | 74 +++++++++++++++++ 5 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 lang/en/rss.php create mode 100644 rss/classes/privacy/provider.php create mode 100644 rss/tests/privacy_test.php diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 7d34286e3e4..3d9055f4bdd 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -1291,7 +1291,6 @@ $string['mustchangepassword'] = 'The new password must be different than the cur $string['mycourses'] = 'My courses'; $string['myfiles'] = 'My private files'; $string['myfilesmanage'] = 'Manage my private files'; -$string['privatefilesmanage'] = 'Manage private files'; $string['myhome'] = 'Dashboard'; $string['mymoodledashboard'] = 'My Moodle dashboard'; $string['myprofile'] = 'My profile'; @@ -1553,6 +1552,7 @@ $string['previouslyselectedusers'] = 'Previously selected users not matching \'{ $string['previoussection'] = 'Previous section'; $string['primaryadminsetup'] = 'Setup administrator account'; $string['privatefiles'] = 'Private files'; +$string['privatefilesmanage'] = 'Manage private files'; $string['private_files_handler'] = 'Store attachments to an e-mail in the user\'s private files storage space.'; $string['private_files_handler_name'] = 'Email to Private files'; $string['proceed'] = 'Proceed'; diff --git a/lang/en/rss.php b/lang/en/rss.php new file mode 100644 index 00000000000..3ed277a7776 --- /dev/null +++ b/lang/en/rss.php @@ -0,0 +1,32 @@ +. + +/** + * RSS language file. + * + * @package core_rss + * @copyright 2018 Sara Arjona + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$string['privacy:metadata:user_private_key'] = 'Information about the user\'s access keys used in cookieless scripts, such as RSS.'; +$string['privacy:metadata:user_private_key:timecreated'] = 'The timestamp indicating when the key was created'; +$string['privacy:metadata:user_private_key:userid'] = 'The ID of the user which is associated to this key'; +$string['privacy:metadata:user_private_key:validuntil'] = 'The timestamp indicating when the key will expire'; +$string['privacy:metadata:user_private_key:value'] = 'The token used for getting the ID of the user'; +$string['rss'] = 'RSS'; diff --git a/rss/classes/privacy/provider.php b/rss/classes/privacy/provider.php new file mode 100644 index 00000000000..b405647c0a8 --- /dev/null +++ b/rss/classes/privacy/provider.php @@ -0,0 +1,137 @@ +. + +/** + * Privacy class for requesting user data. + * + * @package core_rss + * @copyright 2018 Sara Arjona + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_rss\privacy; + +defined('MOODLE_INTERNAL') || die(); + +use \core_privacy\local\metadata\collection; +use \core_privacy\local\request\contextlist; +use \core_privacy\local\request\approved_contextlist; +use \core_privacy\local\request\transform; +use \core_privacy\local\request\writer; + +/** + * Privacy class for requesting user data. + * + * @copyright 2018 Sara Arjona + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements + \core_privacy\local\metadata\provider, + \core_privacy\local\request\plugin\provider { + + /** + * Return the fields which contain personal data. + * + * @param collection $collection The initialised collection to add items to. + * @return collection A listing of user data stored through this system. + */ + public static function get_metadata(collection $collection) : collection { + $collection->add_database_table('user_private_key', [ + 'value' => 'privacy:metadata:user_private_key:value', + 'userid' => 'privacy:metadata:user_private_key:userid', + 'validuntil' => 'privacy:metadata:user_private_key:validuntil', + 'timecreated' => 'privacy:metadata:user_private_key:timecreated' + ], 'privacy:metadata:user_private_key'); + 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 { + $sql = "SELECT ctx.id + FROM {user_private_key} k + JOIN {user} u ON k.userid = u.id + JOIN {context} ctx ON ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel + WHERE k.userid = :userid AND k.script = 'rss'"; + + $params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER]; + + $contextlist = new contextlist(); + $contextlist->add_from_sql($sql, $params); + return $contextlist; + } + + /** + * 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) { + $results = static::get_records($contextlist->get_user()->id); + $context = $contextlist->current(); + if ($context->contextlevel == CONTEXT_USER) { + foreach ($results as $result) { + $context = \context_user::instance($result->userid); + $subcontext = [ + get_string('rss', 'rss'), + transform::user($result->userid) + ]; + $name = 'user_private_key-' . $result->id; + $data = (object)[ + 'value' => $result->value, + 'iprestriction' => $result->iprestriction, + 'validuntil' => $result->validuntil, + 'timecreated' => transform::datetime($result->timecreated), + ]; + writer::with_context($context)->export_related_data($subcontext, $name, $data); + } + } + } + + /** + * Delete all use data which matches the specified deletion_criteria. + * + * @param context $context A user context. + */ + public static function delete_data_for_all_users_in_context(\context $context) { + // The information in user_private_key table is removed automaticaly when a user is deteled. + } + + /** + * 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) { + // The information in user_private_key table is removed automaticaly when a user is deteled. + } + + /** + * Get records related to this plugin and user. + * + * @param int $userid The user ID + * @return array An array of records. + */ + protected static function get_records(int $userid) : array { + global $DB; + + return $DB->get_records('user_private_key', ['userid' => $userid, 'script' => 'rss']); + } +} diff --git a/rss/renderer.php b/rss/renderer.php index fdc0def12ee..9954eec0f5d 100644 --- a/rss/renderer.php +++ b/rss/renderer.php @@ -57,7 +57,7 @@ class core_rss_renderer extends plugin_renderer_base { $stroperation = get_string('operation', 'webservice'); $strtoken = get_string('key', 'webservice'); - $return = $OUTPUT->heading(get_string('rss'), 3, 'main', true); + $return = $OUTPUT->heading(get_string('rss', 'rss'), 3, 'main', true); $return .= $OUTPUT->box_start('generalbox webservicestokenui'); $return .= get_string('rsskeyshelp'); diff --git a/rss/tests/privacy_test.php b/rss/tests/privacy_test.php new file mode 100644 index 00000000000..c3cc70303f9 --- /dev/null +++ b/rss/tests/privacy_test.php @@ -0,0 +1,74 @@ +. +/** + * Base class for unit tests for core_rss. + * + * @package core_rss + * @copyright 2018 Sara Arjona + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use \core_privacy\tests\provider_testcase; +use \core_rss\privacy\provider; +use \core_privacy\local\request\writer; + +/** + * Unit tests for rss\classes\privacy\provider.php + * + * @copyright 2018 Sara Arjona + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_rss_testcase extends provider_testcase { + + /** + * Basic setup for these tests. + */ + public function setUp() { + $this->resetAfterTest(true); + } + + /** + * Test getting the context for the user ID related to this plugin. + */ + public function test_get_contexts_for_userid() { + $user = $this->getDataGenerator()->create_user(); + $context = \context_user::instance($user->id); + $key = get_user_key('rss', $user->id); + + $contextlist = provider::get_contexts_for_userid($user->id); + $this->assertEquals($context->id, $contextlist->current()->id); + } + + /** + * Test that data is exported correctly for this plugin. + */ + public function test_export_user_data() { + global $DB; + + $user = $this->getDataGenerator()->create_user(); + $context = \context_user::instance($user->id); + $keyvalue = get_user_key('rss', $user->id); + $key = $DB->get_record('user_private_key', ['value' => $keyvalue]); + + $writer = writer::with_context($context); + $this->assertFalse($writer->has_any_data()); + $this->export_context_data_for_user($user->id, $context, 'core_rss'); + $data = $writer->get_related_data([get_string('rss', 'rss'), $user->id], 'user_private_key-' . $key->id); + $this->assertEquals($key->value, $data->value); + } +}