mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 05:58:34 +01:00
Merge branch 'wip-MDL-27177-master' of git://github.com/abgreeve/moodle
This commit is contained in:
commit
f1352da1ba
57
user/lib.php
57
user/lib.php
@ -1067,3 +1067,60 @@ function user_mygrades_url($userid = null, $courseid = SITEID) {
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user has the permission to viewdetails in a shared course's context.
|
||||
*
|
||||
* @param object $user The other user's details.
|
||||
* @param object $course Use this course to see if we have permission to see this user's profile.
|
||||
* @param context $usercontext The user context if available.
|
||||
* @return bool true for ability to view this user, else false.
|
||||
*/
|
||||
function user_can_view_profile($user, $course = null, $usercontext = null) {
|
||||
global $USER, $CFG;
|
||||
|
||||
if ($user->deleted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If any of these four things, return true.
|
||||
// Number 1.
|
||||
if ($USER->id == $user->id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Number 2.
|
||||
if (empty($CFG->forceloginforprofiles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (empty($usercontext)) {
|
||||
$usercontext = context_user::instance($user->id);
|
||||
}
|
||||
// Number 3.
|
||||
if (has_capability('moodle/user:viewdetails', $usercontext)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Number 4.
|
||||
if (has_coursecontact_role($user->id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isset($course)) {
|
||||
$sharedcourses = array($course);
|
||||
} else {
|
||||
$sharedcourses = enrol_get_shared_courses($USER->id, $user->id, true);
|
||||
}
|
||||
foreach ($sharedcourses as $sharedcourse) {
|
||||
$coursecontext = context_course::instance($sharedcourse->id);
|
||||
if (has_capability('moodle/user:viewdetails', $coursecontext)) {
|
||||
if (!groups_user_groups_visible($sharedcourse, $user->id)) {
|
||||
// Not a member of the same group.
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ require_once(dirname(__FILE__) . '/../config.php');
|
||||
require_once($CFG->dirroot . '/my/lib.php');
|
||||
require_once($CFG->dirroot . '/tag/lib.php');
|
||||
require_once($CFG->dirroot . '/user/profile/lib.php');
|
||||
require_once($CFG->dirroot . '/user/lib.php');
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
|
||||
$userid = optional_param('id', 0, PARAM_INT);
|
||||
@ -75,10 +76,7 @@ if ((!$user = $DB->get_record('user', array('id' => $userid))) || ($user->delete
|
||||
$currentuser = ($user->id == $USER->id);
|
||||
$context = $usercontext = context_user::instance($userid, MUST_EXIST);
|
||||
|
||||
if (!$currentuser &&
|
||||
!empty($CFG->forceloginforprofiles) &&
|
||||
!has_capability('moodle/user:viewdetails', $context) &&
|
||||
!has_coursecontact_role($userid)) {
|
||||
if (!user_can_view_profile($user, null, $context)) {
|
||||
|
||||
// Course managers can be browsed at site level. If not forceloginforprofiles, allow access (bug #4366).
|
||||
$struser = get_string('user');
|
||||
|
@ -9,15 +9,18 @@ Feature: Access to full profiles of users
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
| student2 | Student | 2 | student2@example.com |
|
||||
| student3 | Student | 3 | student2@example.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
| Course 2 | C2 | topics |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student3 | C2 | student |
|
||||
|
||||
Scenario: Viewing full profiles with default settings
|
||||
When I log in as "student1"
|
||||
@ -60,3 +63,69 @@ Feature: Access to full profiles of users
|
||||
And I follow "Student 2"
|
||||
And I follow "Full profile"
|
||||
Then I should see "First access to site"
|
||||
|
||||
@javascript
|
||||
Scenario: Viewing own full profile
|
||||
Given I log in as "student1"
|
||||
When I follow "Profile" in the user menu
|
||||
Then I should see "First access to site"
|
||||
|
||||
@javascript
|
||||
Scenario: Viewing full profiles of someone with the course contact role
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Courses" node in "Site administration > Appearance"
|
||||
And I set the following fields to these values:
|
||||
| Course creator | 1 |
|
||||
And I press "Save changes"
|
||||
And I navigate to "Assign system roles" node in "Site administration > Users > Permissions"
|
||||
And I follow "Course creator"
|
||||
And I click on "//div[@class='userselector']/descendant::option[contains(., 'Student 3')]" "xpath_element"
|
||||
And I press "Add"
|
||||
And I log out
|
||||
When I log in as "student1"
|
||||
And I follow "Messages" in the user menu
|
||||
And I set the following fields to these values:
|
||||
| Search people and messages | Student 3 |
|
||||
And I press "Search people and messages"
|
||||
And I follow "Picture of Student 3"
|
||||
Then I should see "First access to site"
|
||||
|
||||
@javascript
|
||||
Scenario: View full profiles of someone in the same group in a course with separate groups.
|
||||
Given I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I follow "Course 1"
|
||||
And I follow "Edit settings"
|
||||
And I set the following fields to these values:
|
||||
| Group mode | Separate groups |
|
||||
| Force group mode | Yes |
|
||||
And I press "Save and display"
|
||||
And I log out
|
||||
When I log in as "student1"
|
||||
And I follow "Messages" in the user menu
|
||||
And I set the following fields to these values:
|
||||
| Search people and messages | Student 2 |
|
||||
And I press "Search people and messages"
|
||||
And I follow "Picture of Student 2"
|
||||
And I should not see "First access to site"
|
||||
And I should see "The details of this user are not available to you"
|
||||
And I log out
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I follow "Course 1"
|
||||
And I expand "Users" node
|
||||
And I follow "Groups"
|
||||
And I press "Create group"
|
||||
And I set the following fields to these values:
|
||||
| Group name | Group 1 |
|
||||
And I press "Save changes"
|
||||
And I add "Student 1 (student1@example.com)" user to "Group 1" group members
|
||||
And I add "Student 2 (student2@example.com)" user to "Group 1" group members
|
||||
And I log out
|
||||
And I log in as "student1"
|
||||
And I follow "Messages" in the user menu
|
||||
And I set the following fields to these values:
|
||||
| Search people and messages | Student 2 |
|
||||
And I press "Search people and messages"
|
||||
And I follow "Picture of Student 2"
|
||||
Then I should see "First access to site"
|
||||
|
@ -398,4 +398,94 @@ class core_userliblib_testcase extends advanced_testcase {
|
||||
$this->assertEquals(intval($matches[2]), $testsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test user_can_view_profile
|
||||
*/
|
||||
public function test_user_can_view_profile() {
|
||||
global $DB, $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create five users.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$user3 = $this->getDataGenerator()->create_user();
|
||||
$user4 = $this->getDataGenerator()->create_user();
|
||||
$user5 = $this->getDataGenerator()->create_user();
|
||||
$user6 = $this->getDataGenerator()->create_user(array('deleted' => 1));
|
||||
$user7 = $this->getDataGenerator()->create_user();
|
||||
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
|
||||
// Add the course creator role to the course contact and assign a user to that role.
|
||||
$CFG->coursecontact = '2';
|
||||
$coursecreatorrole = $DB->get_record('role', array('shortname' => 'coursecreator'));
|
||||
$this->getDataGenerator()->role_assign($coursecreatorrole->id, $user7->id);
|
||||
|
||||
// Create two courses.
|
||||
$course1 = $this->getDataGenerator()->create_course();
|
||||
$course2 = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = context_course::instance($course2->id);
|
||||
// Prepare another course with separate groups and groupmodeforce set to true.
|
||||
$record = new stdClass();
|
||||
$record->groupmode = 1;
|
||||
$record->groupmodeforce = 1;
|
||||
$course3 = $this->getDataGenerator()->create_course($record);
|
||||
// Enrol users 1 and 2 in first course.
|
||||
$this->getDataGenerator()->enrol_user($user1->id, $course1->id);
|
||||
$this->getDataGenerator()->enrol_user($user2->id, $course1->id);
|
||||
// Enrol users 2 and 3 in second course.
|
||||
$this->getDataGenerator()->enrol_user($user2->id, $course2->id);
|
||||
$this->getDataGenerator()->enrol_user($user3->id, $course2->id);
|
||||
// Enrol users 1, 4, and 5 into course 3.
|
||||
$this->getDataGenerator()->enrol_user($user1->id, $course3->id);
|
||||
$this->getDataGenerator()->enrol_user($user4->id, $course3->id);
|
||||
$this->getDataGenerator()->enrol_user($user5->id, $course3->id);
|
||||
|
||||
// Remove capability moodle/user:viewdetails in course 2.
|
||||
assign_capability('moodle/user:viewdetails', CAP_PROHIBIT, $studentrole->id, $coursecontext);
|
||||
$coursecontext->mark_dirty();
|
||||
// Set current user to user 1.
|
||||
$this->setUser($user1);
|
||||
// User 1 can see User 1's profile.
|
||||
$this->assertTrue(user_can_view_profile($user1));
|
||||
|
||||
$tempcfg = $CFG->forceloginforprofiles;
|
||||
$CFG->forceloginforprofiles = 0;
|
||||
// Not forced to log in to view profiles, should be able to see all profiles besides user 6.
|
||||
$users = array($user1, $user2, $user3, $user4, $user5, $user7);
|
||||
foreach ($users as $user) {
|
||||
$this->assertTrue(user_can_view_profile($user));
|
||||
}
|
||||
// Restore setting.
|
||||
$CFG->forceloginforprofiles = $tempcfg;
|
||||
|
||||
// User 1 can not see user 6 as they have been deleted.
|
||||
$this->assertFalse(user_can_view_profile($user6));
|
||||
// User 1 can see User 7 as they are a course contact.
|
||||
$this->assertTrue(user_can_view_profile($user7));
|
||||
// User 1 is in a course with user 2 and has the right capability - return true.
|
||||
$this->assertTrue(user_can_view_profile($user2));
|
||||
// User 1 is not in a course with user 3 - return false.
|
||||
$this->assertFalse(user_can_view_profile($user3));
|
||||
|
||||
// Set current user to user 2.
|
||||
$this->setUser($user2);
|
||||
// User 2 is in a course with user 3 but does not have the right capability - return false.
|
||||
$this->assertFalse(user_can_view_profile($user3));
|
||||
|
||||
// Set user 1 in one group and users 4 and 5 in another group.
|
||||
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course3->id));
|
||||
$group2 = $this->getDataGenerator()->create_group(array('courseid' => $course3->id));
|
||||
groups_add_member($group1->id, $user1->id);
|
||||
groups_add_member($group2->id, $user4->id);
|
||||
groups_add_member($group2->id, $user5->id);
|
||||
$this->setUser($user1);
|
||||
// Check that user 1 can not see user 4.
|
||||
$this->assertFalse(user_can_view_profile($user4));
|
||||
// Check that user 5 can see user 4.
|
||||
$this->setUser($user5);
|
||||
$this->assertTrue(user_can_view_profile($user4));
|
||||
|
||||
$CFG->coursecontact = null;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
require_once("../config.php");
|
||||
require_once($CFG->dirroot.'/user/profile/lib.php');
|
||||
require_once($CFG->dirroot.'/user/lib.php');
|
||||
require_once($CFG->dirroot.'/tag/lib.php');
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
@ -125,9 +126,8 @@ if ($currentuser) {
|
||||
$PAGE->set_title("$strpersonalprofile: ");
|
||||
$PAGE->set_heading("$strpersonalprofile: ");
|
||||
|
||||
// Check course level capabilities.
|
||||
if (!has_capability('moodle/user:viewdetails', $coursecontext) && // Normal enrolled user or mnager.
|
||||
($user->deleted or !has_capability('moodle/user:viewdetails', $usercontext))) { // Usually parent.
|
||||
// Check to see if the user can see this user's profile.
|
||||
if (!user_can_view_profile($user, $course, $usercontext) && !$isparent) {
|
||||
print_error('cannotviewprofile');
|
||||
}
|
||||
|
||||
@ -152,22 +152,9 @@ if ($currentuser) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// If groups are in use and enforced throughout the course, then make sure we can meet in at least one course level group.
|
||||
// Except when we are a parent, in which case we would not be in any group.
|
||||
if (groups_get_course_groupmode($course) == SEPARATEGROUPS
|
||||
and $course->groupmodeforce
|
||||
and !has_capability('moodle/site:accessallgroups', $coursecontext)
|
||||
and !has_capability('moodle/site:accessallgroups', $coursecontext, $user->id)
|
||||
and !$isparent) {
|
||||
if (!isloggedin() or isguestuser()) {
|
||||
// Do not use require_login() here because we might have already used require_login($course).
|
||||
redirect(get_login_url());
|
||||
}
|
||||
$mygroups = array_keys(groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid, 'g.id, g.name'));
|
||||
$usergroups = array_keys(groups_get_all_groups($course->id, $user->id, $course->defaultgroupingid, 'g.id, g.name'));
|
||||
if (!array_intersect($mygroups, $usergroups)) {
|
||||
print_error("groupnotamember", '', "../course/view.php?id=$course->id");
|
||||
}
|
||||
if (!isloggedin() or isguestuser()) {
|
||||
// Do not use require_login() here because we might have already used require_login($course).
|
||||
redirect(get_login_url());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user