From 89fbf2e874d01c4912e624bc69895fff9282ef81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20S=CC=8Ckoda?= Date: Sat, 15 Sep 2012 20:54:40 +0200 Subject: [PATCH] MDL-35381 limit teachers to do permissions checks of enrolled users only --- admin/roles/check.php | 15 ++--- admin/roles/lib.php | 128 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 10 deletions(-) diff --git a/admin/roles/check.php b/admin/roles/check.php index 470159ecc85..d3917b03882 100644 --- a/admin/roles/check.php +++ b/admin/roles/check.php @@ -59,16 +59,11 @@ $courseid = $course->id; $contextname = print_context_name($context); // Get the user_selector we will need. -// Teachers within a course just get to see the same list of people they can -// assign roles to. Admins (people with moodle/role:manage) can run this report for any user. -$options = array('context' => $context, 'roleid' => 0); -if (has_capability('moodle/role:manage', $context)) { - $userselector = new potential_assignees_course_and_above('reportuser', $options); -} else { - $userselector = roles_get_potential_user_selector($context, 'reportuser', $options); -} -$userselector->set_multiselect(false); -$userselector->set_rows(10); +// Teachers within a course just get to see the same list of enrolled users. +// Admins (people with moodle/role:manage) can run this report for any user. +$options = array('accesscontext' => $context); +$userselector = new role_check_users_selector('reportuser', $options); +$userselector->set_rows(20); // Work out an appropriate page title. $title = get_string('checkpermissionsin', 'role', $contextname); diff --git a/admin/roles/lib.php b/admin/roles/lib.php index 93703c8e659..c201d35b07a 100644 --- a/admin/roles/lib.php +++ b/admin/roles/lib.php @@ -1076,6 +1076,134 @@ class potential_assignees_below_course extends role_assign_user_selector_base { } } +/** + * User selector subclass for the selection of users in the check permissions page. + * + * @copyright 2012 Petr Skoda {@link http://skodak.org} + */ +class role_check_users_selector extends user_selector_base { + const MAX_ENROLLED_PER_PAGE = 100; + const MAX_POTENTIAL_PER_PAGE = 100; + + /** @var bool limit listing of users to enrolled only */ + var $onlyenrolled; + + /** + * Constructor. + * + * @param string $name the control name/id for use in the HTML. + * @param array $options other options needed to construct this selector. + * You must be able to clone a userselector by doing new get_class($us)($us->get_name(), $us->get_options()); + */ + public function __construct($name, $options) { + if (!isset($options['multiselect'])) { + $options['multiselect'] = false; + } + parent::__construct($name, $options); + + $coursecontext = $this->accesscontext->get_course_context(false); + if ($coursecontext and $coursecontext->id != SITEID and !has_capability('moodle/role:manage', $coursecontext)) { + // Prevent normal teachers from looking up all users. + $this->onlyenrolled = true; + } else { + $this->onlyenrolled = false; + } + } + + public function find_users($search) { + global $DB; + + list($wherecondition, $params) = $this->search_sql($search, 'u'); + + $fields = 'SELECT ' . $this->required_fields_sql('u'); + $countfields = 'SELECT COUNT(1)'; + + $coursecontext = $this->accesscontext->get_course_context(false); + + if ($coursecontext and $coursecontext != SITEID) { + $sql1 = " FROM {user} u + JOIN {user_enrolments} ue ON (ue.userid = u.id) + JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid1) + WHERE $wherecondition"; + $params['courseid1'] = $coursecontext->instanceid; + + if ($this->onlyenrolled) { + $sql2 = null; + } else { + $sql2 = " FROM {user} u + LEFT JOIN ({user_enrolments} ue + JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid2)) ON (ue.userid = u.id) + WHERE $wherecondition + AND ue.id IS NULL"; + $params['courseid2'] = $coursecontext->instanceid; + } + + } else { + if ($this->onlyenrolled) { + // Bad luck, current user may not view only enrolled users. + return array(); + } + $sql1 = null; + $sql2 = " FROM {user} u + WHERE $wherecondition"; + } + + $order = " ORDER BY lastname ASC, firstname ASC"; + + $params['contextid'] = $this->accesscontext->id; + + $result = array(); + + if ($search) { + $groupname1 = get_string('enrolledusersmatching', 'enrol', $search); + $groupname2 = get_string('potusersmatching', 'role', $search); + } else { + $groupname1 = get_string('enrolledusers', 'enrol'); + $groupname2 = get_string('potusers', 'role'); + } + + if ($sql1) { + $enrolleduserscount = $DB->count_records_sql($countfields . $sql1, $params); + if (!$this->is_validating() and $enrolleduserscount > $this::MAX_ENROLLED_PER_PAGE) { + $result[$groupname1] = array(); + $toomany = $this->too_many_results($search, $enrolleduserscount); + $result[implode(' - ', array_keys($toomany))] = array(); + + } else { + $enrolledusers = $DB->get_records_sql($fields . $sql1 . $order, $params); + if ($enrolledusers) { + $result[$groupname1] = $enrolledusers; + } + } + if ($sql2) { + $result[''] = array(); + } + } + if ($sql2) { + $otheruserscount = $DB->count_records_sql($countfields . $sql2, $params); + if (!$this->is_validating() and $otheruserscount > $this::MAX_POTENTIAL_PER_PAGE) { + $result[$groupname2] = array(); + $toomany = $this->too_many_results($search, $otheruserscount); + $result[implode(' - ', array_keys($toomany))] = array(); + } else { + $otherusers = $DB->get_records_sql($fields . $sql2 . $order, $params); + if ($otherusers) { + $result[$groupname2] = $otherusers; + } + } + } + + return $result; + } + + protected function get_options() { + global $CFG; + $options = parent::get_options(); + $options['file'] = $CFG->admin . '/roles/lib.php'; + return $options; + } +} + /** * User selector subclass for the list of potential users on the assign roles page, * when we are assigning in a context at or above the course level. In this case we