Skip to content

Commit

Permalink
MDL-62356 enrol_meta: Add privacy implementation for enrol_meta
Browse files Browse the repository at this point in the history
  • Loading branch information
cescobedo committed May 14, 2018
1 parent ab65b87 commit 267effa
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 8 deletions.
92 changes: 85 additions & 7 deletions enrol/meta/classes/privacy/provider.php
Expand Up @@ -22,20 +22,98 @@
*/
namespace enrol_meta\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\contextlist;
use \core_privacy\local\request\approved_contextlist;

/**
* Privacy Subsystem for enrol_meta implementing null_provider.
* Privacy provider for enrol_meta.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\plugin\provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
* Returns meta data about this system.
*
* @return string
* @param collection $collection The initialised item collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_reason() : string {
return 'privacy:metadata';
public static function get_metadata(collection $collection) : collection {

$collection->add_subsystem_link('core_group', [], 'privacy:metadata:core_group');
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 {
$contextlist = new contextlist();

$sql = "SELECT ctx.id
FROM {groups_members} gm
JOIN {groups} g ON gm.groupid = g.id
JOIN {context} ctx ON g.courseid = ctx.instanceid AND ctx.contextlevel = :contextlevel
WHERE gm.userid = :userid
AND gm.component = 'enrol_meta'";

$params = [
'contextlevel' => CONTEXT_COURSE,
'userid' => $userid
];

$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) {
if (empty($contextlist)) {
return;
}
foreach ($contextlist as $context) {
if ($context->contextlevel == CONTEXT_COURSE) {
\core_group\privacy\provider::export_groups(
$context,
'enrol_meta',
[get_string('pluginname', 'enrol_meta')]
);
}
}
}

/**
* 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) {
if (empty($context)) {
return;
}
if ($context->contextlevel == CONTEXT_COURSE) {
// Delete all the associated groups.
\core_group\privacy\provider::delete_groups_for_all_users($context, 'enrol_meta');
}
}
/**
* 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) {
if (empty($contextlist->count())) {
return;
}
\core_group\privacy\provider::delete_groups_for_user($contextlist, 'enrol_meta');
}
}
2 changes: 1 addition & 1 deletion enrol/meta/lang/en/enrol_meta.php
Expand Up @@ -38,4 +38,4 @@
$string['pluginname_desc'] = 'Course meta link enrolment plugin synchronises enrolments and roles in two different courses.';
$string['syncall'] = 'Synchronise all enrolled users';
$string['syncall_desc'] = 'If enabled all enrolled users are synchronised even if they have no role in parent course, if disabled only users that have at least one synchronised role are enrolled in child course.';
$string['privacy:metadata'] = 'The Course meta link enrolment plugin does not store any personal data.';
$string['privacy:metadata:core_group'] = 'Enrol meta plugin can create a new group or use an existing group to add all the participants of the course linked.';
198 changes: 198 additions & 0 deletions enrol/meta/tests/privacy_test.php
@@ -0,0 +1,198 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Base class for unit tests for enrol_meta.
*
* @package enrol_meta
* @category test
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\request\writer;
use \core_privacy\local\request\approved_contextlist;
use \enrol_meta\privacy\provider;
/**
* Unit tests for the enrol_meta implementation of the privacy API.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class enrol_meta_privacy_testcase extends \core_privacy\tests\provider_testcase {
/**
* Enable enrol_meta plugin.
*/
protected function enable_plugin() {
$enabled = enrol_get_plugins(true);
$enabled['meta'] = true;
$enabled = array_keys($enabled);
set_config('enrol_plugins_enabled', implode(',', $enabled));
}
/**
* Test getting the context for the user ID related to this plugin.
*/
public function test_get_contexts_for_userid() {
global $DB;

$this->resetAfterTest();
$metaplugin = enrol_get_plugin('meta');
$user1 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id));
$studentrole = $DB->get_record('role', array('shortname' => 'student'));

$this->enable_plugin();
$metaplugin->add_instance($course1, array('customint1' => $course2->id, 'customint2' => $group1->id));
$this->getDataGenerator()->enrol_user($user1->id, $course2->id, $studentrole->id);
// Check if user1 is enrolled into course1 in group 1.
$this->assertTrue(groups_is_member($group1->id, $user1->id));
$this->assertTrue($DB->record_exists('groups_members',
array(
'groupid' => $group1->id,
'userid' => $user1->id,
'component' => 'enrol_meta'
)
));
// Check context course fro provider to user1.
$context = \context_course::instance($course1->id);
$contextlist = provider::get_contexts_for_userid($user1->id);
$this->assertEquals($context->id, $contextlist->current()->id);
}

/**
* Test that user data is exported correctly.
*/
public function test_export_user_data() {
global $DB;

$this->resetAfterTest();
$metaplugin = enrol_get_plugin('meta');
$user1 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id));
$studentrole = $DB->get_record('role', array('shortname' => 'student'));

$this->enable_plugin();
$metaplugin->add_instance($course1, array('customint1' => $course2->id, 'customint2' => $group1->id));
$this->getDataGenerator()->enrol_user($user1->id, $course2->id, $studentrole->id);

$this->setUser($user1);
$contextlist = provider::get_contexts_for_userid($user1->id);
$approvedcontextlist = new approved_contextlist($user1, 'enrol_meta', $contextlist->get_contextids());
provider::export_user_data($approvedcontextlist);
foreach ($contextlist as $context) {
$writer = writer::with_context($context);
$data = $writer->get_data([
get_string('pluginname', 'enrol_meta'),
get_string('groups', 'core_group')
]);
$this->assertTrue($writer->has_any_data());
if ($context->contextlevel == CONTEXT_COURSE) {
$exportedgroups = $data->groups;
// User1 only belongs to group1 via enrol_meta.
$this->assertCount(1, $exportedgroups);
$exportedgroup = reset($exportedgroups);
$this->assertEquals($group1->name, $exportedgroup->name);
}
}
}
/**
* Test for provider::delete_data_for_all_users_in_context().
*/
public function test_delete_data_for_all_users_in_context() {
global $DB;

$this->resetAfterTest();
$metaplugin = enrol_get_plugin('meta');
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id));
$studentrole = $DB->get_record('role', array('shortname' => 'student'));

$this->enable_plugin();
$metaplugin->add_instance($course1, array('customint1' => $course2->id, 'customint2' => $group1->id));
$this->getDataGenerator()->enrol_user($user1->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user2->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user3->id, $course2->id, $studentrole->id);
$this->assertEquals(
3,
$DB->count_records_sql("SELECT COUNT(gm.id)
FROM {groups_members} gm
JOIN {groups} g ON gm.groupid = g.id
WHERE g.courseid = ?", [$course1->id])
);

$coursecontext1 = context_course::instance($course1->id);
provider::delete_data_for_all_users_in_context($coursecontext1);
$this->assertEquals(
0,
$DB->count_records_sql("SELECT COUNT(gm.id)
FROM {groups_members} gm
JOIN {groups} g ON gm.groupid = g.id
WHERE g.courseid = ?", [$course1->id])
);
}
/**
* Test for provider::delete_data_for_user().
*/
public function test_delete_data_for_user() {
global $DB;

$this->resetAfterTest();
$metaplugin = enrol_get_plugin('meta');
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id));
$studentrole = $DB->get_record('role', array('shortname' => 'student'));

$this->enable_plugin();
$metaplugin->add_instance($course1, array('customint1' => $course2->id, 'customint2' => $group1->id));
$this->getDataGenerator()->enrol_user($user1->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user2->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user3->id, $course2->id, $studentrole->id);

$this->assertEquals(
3,
$DB->count_records_sql("SELECT COUNT(gm.id)
FROM {groups_members} gm
JOIN {groups} g ON gm.groupid = g.id
WHERE g.courseid = ?", [$course1->id])
);

$this->setUser($user1);
$coursecontext1 = context_course::instance($course1->id);
$coursecontext2 = context_course::instance($course2->id);
$approvedcontextlist = new \core_privacy\tests\request\approved_contextlist($user1, 'enrol_meta',
[$coursecontext1->id]);
provider::delete_data_for_user($approvedcontextlist);
// Check we have 2 users in groups because we are deleted user1.
$this->assertEquals(
2,
$DB->count_records_sql("SELECT COUNT(gm.id)
FROM {groups_members} gm
JOIN {groups} g ON gm.groupid = g.id
WHERE g.courseid = ?", [$course1->id])
);
}
}

0 comments on commit 267effa

Please sign in to comment.