Skip to content

Commit

Permalink
Merge branch 'MDL-62663' of https://github.com/andrewhancox/moodle
Browse files Browse the repository at this point in the history
  • Loading branch information
David Monllao authored and andrewnicols committed Jul 19, 2018
2 parents e385230 + 7068dd3 commit a02f330
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 29 deletions.
94 changes: 65 additions & 29 deletions user/profile/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,23 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

define ('PROFILE_VISIBLE_ALL', '2'); // Only visible for users with moodle/user:update capability.
define ('PROFILE_VISIBLE_PRIVATE', '1'); // Either we are viewing our own profile or we have moodle/user:update capability.
define ('PROFILE_VISIBLE_NONE', '0'); // Only visible for moodle/user:update capability.
/**
* Visible to anyone who can view the user.
* Editable by the profile owner if they have the moodle/user:editownprofile capability
* or any user with the moodle/user:update capability.
*/
define('PROFILE_VISIBLE_ALL', '2');
/**
* Visible to the profile owner or anyone with the moodle/user:viewalldetails capability.
* Editable by the profile owner if they have the moodle/user:editownprofile capability
* or any user with moodle/user:viewalldetails and moodle/user:update capabilities.
*/
define('PROFILE_VISIBLE_PRIVATE', '1');
/**
* Only visible to users with the moodle/user:viewalldetails capability.
* Only editable by users with the moodle/user:viewalldetails and moodle/user:update capabilities.
*/
define('PROFILE_VISIBLE_NONE', '0');

/**
* Base class for the customisable profile fields.
Expand Down Expand Up @@ -131,15 +145,14 @@ public function display_data() {
* @return bool
*/
public function edit_field($mform) {
if ($this->field->visible != PROFILE_VISIBLE_NONE
or has_capability('moodle/user:update', context_system::instance())) {

$this->edit_field_add($mform);
$this->edit_field_set_default($mform);
$this->edit_field_set_required($mform);
return true;
if (!$this->is_editable()) {
return false;
}
return false;

$this->edit_field_add($mform);
$this->edit_field_set_default($mform);
$this->edit_field_set_required($mform);
return true;
}

/**
Expand All @@ -148,12 +161,12 @@ public function edit_field($mform) {
* @return bool
*/
public function edit_after_data($mform) {
if ($this->field->visible != PROFILE_VISIBLE_NONE
or has_capability('moodle/user:update', context_system::instance())) {
$this->edit_field_set_locked($mform);
return true;
if (!$this->is_editable()) {
return false;
}
return false;

$this->edit_field_set_locked($mform);
return true;
}

/**
Expand Down Expand Up @@ -429,6 +442,31 @@ public function is_visible() {
}
}

/**
* Check if the field data is editable for the current user
* This method should not generally be overwritten by child classes.
* @return bool
*/
public function is_editable() {
global $USER;

if (!$this->is_visible()) {
return false;
}

$systemcontext = context_system::instance();

if ($this->userid == $USER->id && has_capability('moodle/user:editownprofile', $systemcontext)) {
return true;
}

if (has_capability('moodle/user:update', $systemcontext)) {
return true;
}

return false;
}

/**
* Check if the field data is considered empty
* @internal This method should not generally be overwritten by child classes.
Expand Down Expand Up @@ -565,27 +603,25 @@ function profile_load_data($user) {
* @param int $userid id of user whose profile is being edited.
*/
function profile_definition($mform, $userid = 0) {
global $CFG, $DB;

// If user is "admin" fields are displayed regardless.
$update = has_capability('moodle/user:update', context_system::instance());

$categories = profile_get_user_fields_with_data_by_category($userid);
foreach ($categories as $categoryid => $fields) {
// Check first if *any* fields will be displayed.
$display = false;
$fieldstodisplay = [];

foreach ($fields as $formfield) {
if ($formfield->is_visible()) {
$display = true;
if ($formfield->is_editable()) {
$fieldstodisplay[] = $formfield;
}
}

if (empty($fieldstodisplay)) {
continue;
}

// Display the header and the fields.
if ($display or $update) {
$mform->addElement('header', 'category_'.$categoryid, format_string($formfield->get_category_name()));
foreach ($fields as $formfield) {
$formfield->edit_field($mform);
}
$mform->addElement('header', 'category_'.$categoryid, format_string($fields[0]->get_category_name()));
foreach ($fieldstodisplay as $formfield) {
$formfield->edit_field($mform);
}
}
}
Expand Down
188 changes: 188 additions & 0 deletions user/tests/behat/custom_profile_fields.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
@core @core_user
Feature: Custom profile fields should be visible and editable by those with the correct permissions.

Background: Attempting to self-register as a new user with empty names
Given the following "users" exist:
| username | firstname | lastname | email |
| userwithinformation | userwithinformation | 1 | userwithinformation@example.com |
And the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| userwithinformation | C1 | student |

And I log in as "admin"
And I navigate to "User profile fields" node in "Site administration > Users > Accounts"
And I set the field "datatype" to "Text input"
And I set the following fields to these values:
| Short name | notvisible_field |
| Name | notvisible_field |
| Who is this field visible to? | Not visible |
And I click on "Save changes" "button"

And I set the field "datatype" to "Text input"
And I set the following fields to these values:
| Short name | uservisible_field |
| Name | uservisible_field |
| Who is this field visible to? | Visible to user |
And I click on "Save changes" "button"

And I set the field "datatype" to "Text input"
And I set the following fields to these values:
| Short name | everyonevisible_field |
| Name | everyonevisible_field |
| Who is this field visible to? | Visible to everyone |
And I click on "Save changes" "button"

And I navigate to "Browse list of users" node in "Site administration > Users > Accounts"
And I click on ".icon[title=Edit]" "css_element" in the "userwithinformation@example.com" "table_row"
And I expand all fieldsets
And I set the field "notvisible_field" to "notvisible_field_information"
And I set the field "uservisible_field" to "uservisible_field_information"
And I set the field "everyonevisible_field" to "everyonevisible_field_information"
And I click on "Update profile" "button"
And I log out

@javascript
Scenario: User with moodle/user:update but without moodle/user:viewalldetails can only update visible profile fields.
Given the following "roles" exist:
| name | shortname | description | archetype |
| Update Users | updateusers | updateusers | |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/user:update | Allow | updateusers | System | |
And the following "users" exist:
| username | firstname | lastname | email |
| user_updateusers | updateusers | 1 | updateusers@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| user_updateusers | updateusers | System | |
And the following "course enrolments" exist:
| user | course | role |
| user_updateusers | C1 | editingteacher |
And I log in as "user_updateusers"
And I am on "Course 1" course homepage
And I navigate to course participants
And I follow "userwithinformation 1"

Then I should see "everyonevisible_field"
And I should see "everyonevisible_field_information"
And I should not see "uservisible_field"
And I should not see "uservisible_field_information"
And I should not see "notvisible_field"
And I should not see "notvisible_field_information"
And I follow "Edit profile"
And the following fields match these values:
| everyonevisible_field | everyonevisible_field_information |
And I should not see "uservisible_field"
And I should not see "notvisible_field"

@javascript
Scenario: User with moodle/user:viewalldetails but without moodle/user:update can view all profile fields.
Given the following "roles" exist:
| name | shortname | description | archetype |
| View All Details | viewalldetails | viewalldetails | |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/user:viewalldetails | Allow | viewalldetails | System | |
And the following "users" exist:
| username | firstname | lastname | email |
| user_viewalldetails | viewalldetails | 1 | viewalldetails@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| user_viewalldetails | viewalldetails | System | |
And the following "course enrolments" exist:
| user | course | role |
| user_viewalldetails | C1 | editingteacher |
And I log in as "user_viewalldetails"
And I am on "Course 1" course homepage
And I navigate to course participants
And I follow "userwithinformation 1"

Then I should see "everyonevisible_field"
And I should see "everyonevisible_field_information"
And I should see "uservisible_field"
And I should see "uservisible_field_information"
And I should see "notvisible_field"
And I should see "notvisible_field_information"
And I should not see "Edit profile"

@javascript
Scenario: User with moodle/user:viewalldetails and moodle/user:update capabilities can view and edit all profile fields.
Given the following "roles" exist:
| name | shortname | description | archetype |
| View All Details and Update Users | viewalldetailsandupdateusers | viewalldetailsandupdateusers | |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/user:viewalldetails | Allow | viewalldetailsandupdateusers | System | |
| moodle/user:update | Allow | viewalldetailsandupdateusers | System | |
And the following "users" exist:
| username | firstname | lastname | email |
| user_viewalldetailsandupdateusers | viewalldetailsandupdateusers | 1 | viewalldetailsandupdateusers@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| user_viewalldetailsandupdateusers | viewalldetailsandupdateusers | System | |
And the following "course enrolments" exist:
| user | course | role |
| user_viewalldetailsandupdateusers | C1 | editingteacher |
And I log in as "user_viewalldetailsandupdateusers"
And I am on "Course 1" course homepage
And I navigate to course participants
And I follow "userwithinformation 1"

Then I should see "everyonevisible_field"
And I should see "everyonevisible_field_information"
And I should see "uservisible_field"
And I should see "uservisible_field_information"
And I should see "notvisible_field"
And I should see "notvisible_field_information"
And I follow "Edit profile"
And the following fields match these values:
| everyonevisible_field | everyonevisible_field_information |
| uservisible_field | uservisible_field_information |
| notvisible_field | notvisible_field_information |

@javascript
Scenario: Users can view and edit custom profile fields except those marked as not visible.
Given I log in as "userwithinformation"
And I follow "Profile" in the user menu

Then I should see "everyonevisible_field"
And I should see "everyonevisible_field_information"
And I should see "uservisible_field"
And I should see "uservisible_field_information"
And I should not see "notvisible_field"
And I should not see "notvisible_field_information"

And I click on "Edit profile" "link" in the "region-main" "region"
Then the following fields match these values:
| everyonevisible_field | everyonevisible_field_information |
| uservisible_field | uservisible_field_information |
And I should not see "notvisible_field"
And I should not see "notvisible_field_information"

@javascript
Scenario: Users can view but not edit custom profile fields when denied the edit own profile capability.
Given the following "roles" exist:
| name | shortname | description | archetype |
| Deny editownprofile | denyeditownprofile | denyeditownprofile | |

And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/user:editownprofile | Prohibit | denyeditownprofile | System | |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| userwithinformation | denyeditownprofile | System | |

And I log in as "userwithinformation"
And I follow "Profile" in the user menu

Then I should see "everyonevisible_field"
And I should see "everyonevisible_field_information"
And I should see "uservisible_field"
And I should see "uservisible_field_information"
And I should not see "notvisible_field"
And I should not see "notvisible_field_information"

And I should not see "Edit profile"

0 comments on commit a02f330

Please sign in to comment.