diff --git a/enrol/externallib.php b/enrol/externallib.php index 5189a3a7edd..8281f3cc6aa 100644 --- a/enrol/externallib.php +++ b/enrol/externallib.php @@ -307,6 +307,7 @@ class core_enrol_external extends external_api { global $CFG, $USER, $DB; require_once($CFG->dirroot . '/course/lib.php'); + require_once($CFG->dirroot . '/user/lib.php'); require_once($CFG->libdir . '/completionlib.php'); // Do basic automatic PARAM checks on incoming data, using params description @@ -346,8 +347,8 @@ class core_enrol_external extends external_api { continue; } - if (!$sameuser and !course_can_view_participants($context)) { - // we need capability to view participants + // If viewing details of another user, then we must be able to view participants as well as profile of that user. + if (!$sameuser && (!course_can_view_participants($context) || !user_can_view_profile($user, $course))) { continue; } diff --git a/enrol/tests/externallib_test.php b/enrol/tests/externallib_test.php index c98df46ca47..c126c90b312 100644 --- a/enrol/tests/externallib_test.php +++ b/enrol/tests/externallib_test.php @@ -610,6 +610,81 @@ class core_enrol_externallib_testcase extends externallib_advanced_testcase { $this->assertEquals(0, $enrolledincourses[0]['lastaccess']); // I can't see this, hidden by global setting. } + /** + * Test that get_users_courses respects the capability to view participants when viewing courses of other user + */ + public function test_get_users_courses_can_view_participants(): void { + global $DB; + + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $context = context_course::instance($course->id); + + $user1 = $this->getDataGenerator()->create_and_enrol($course, 'student'); + $user2 = $this->getDataGenerator()->create_and_enrol($course, 'student'); + + $this->setUser($user1); + + $courses = core_enrol_external::clean_returnvalue( + core_enrol_external::get_users_courses_returns(), + core_enrol_external::get_users_courses($user2->id, false) + ); + + $this->assertCount(1, $courses); + $this->assertEquals($course->id, reset($courses)['id']); + + // Prohibit the capability for viewing course participants. + $studentrole = $DB->get_field('role', 'id', ['shortname' => 'student']); + assign_capability('moodle/course:viewparticipants', CAP_PROHIBIT, $studentrole, $context->id); + + $courses = core_enrol_external::clean_returnvalue( + core_enrol_external::get_users_courses_returns(), + core_enrol_external::get_users_courses($user2->id, false) + ); + $this->assertEmpty($courses); + } + + /* + * Test that get_users_courses respects the capability to view a users profile when viewing courses of other user + */ + public function test_get_users_courses_can_view_profile(): void { + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course([ + 'groupmode' => VISIBLEGROUPS, + ]); + + $user1 = $this->getDataGenerator()->create_and_enrol($course, 'student'); + $user2 = $this->getDataGenerator()->create_and_enrol($course, 'student'); + + // Create separate groups for each of our students. + $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); + groups_add_member($group1, $user1); + $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); + groups_add_member($group2, $user2); + + $this->setUser($user1); + + $courses = core_enrol_external::clean_returnvalue( + core_enrol_external::get_users_courses_returns(), + core_enrol_external::get_users_courses($user2->id, false) + ); + + $this->assertCount(1, $courses); + $this->assertEquals($course->id, reset($courses)['id']); + + // Change to separate groups mode, so students can't view information about each other in different groups. + $course->groupmode = SEPARATEGROUPS; + update_course($course); + + $courses = core_enrol_external::clean_returnvalue( + core_enrol_external::get_users_courses_returns(), + core_enrol_external::get_users_courses($user2->id, false) + ); + $this->assertEmpty($courses); + } + /** * Test get_users_courses with mathjax in the name. */