Skip to content

Commit 8632026

Browse files
author
David Monllao
committed
Merge branch 'MDL-62663_35' of https://github.com/andrewhancox/moodle into MOODLE_35_STABLE
2 parents 706ba3f + 740db2e commit 8632026

File tree

2 files changed

+253
-29
lines changed

2 files changed

+253
-29
lines changed

user/profile/lib.php

Lines changed: 65 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,23 @@
2222
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2323
*/
2424

25-
define ('PROFILE_VISIBLE_ALL', '2'); // Only visible for users with moodle/user:update capability.
26-
define ('PROFILE_VISIBLE_PRIVATE', '1'); // Either we are viewing our own profile or we have moodle/user:update capability.
27-
define ('PROFILE_VISIBLE_NONE', '0'); // Only visible for moodle/user:update capability.
25+
/**
26+
* Visible to anyone who can view the user.
27+
* Editable by the profile owner if they have the moodle/user:editownprofile capability
28+
* or any user with the moodle/user:update capability.
29+
*/
30+
define('PROFILE_VISIBLE_ALL', '2');
31+
/**
32+
* Visible to the profile owner or anyone with the moodle/user:viewalldetails capability.
33+
* Editable by the profile owner if they have the moodle/user:editownprofile capability
34+
* or any user with moodle/user:viewalldetails and moodle/user:update capabilities.
35+
*/
36+
define('PROFILE_VISIBLE_PRIVATE', '1');
37+
/**
38+
* Only visible to users with the moodle/user:viewalldetails capability.
39+
* Only editable by users with the moodle/user:viewalldetails and moodle/user:update capabilities.
40+
*/
41+
define('PROFILE_VISIBLE_NONE', '0');
2842

2943
/**
3044
* Base class for the customisable profile fields.
@@ -131,15 +145,14 @@ public function display_data() {
131145
* @return bool
132146
*/
133147
public function edit_field($mform) {
134-
if ($this->field->visible != PROFILE_VISIBLE_NONE
135-
or has_capability('moodle/user:update', context_system::instance())) {
136-
137-
$this->edit_field_add($mform);
138-
$this->edit_field_set_default($mform);
139-
$this->edit_field_set_required($mform);
140-
return true;
148+
if (!$this->is_editable()) {
149+
return false;
141150
}
142-
return false;
151+
152+
$this->edit_field_add($mform);
153+
$this->edit_field_set_default($mform);
154+
$this->edit_field_set_required($mform);
155+
return true;
143156
}
144157

145158
/**
@@ -148,12 +161,12 @@ public function edit_field($mform) {
148161
* @return bool
149162
*/
150163
public function edit_after_data($mform) {
151-
if ($this->field->visible != PROFILE_VISIBLE_NONE
152-
or has_capability('moodle/user:update', context_system::instance())) {
153-
$this->edit_field_set_locked($mform);
154-
return true;
164+
if (!$this->is_editable()) {
165+
return false;
155166
}
156-
return false;
167+
168+
$this->edit_field_set_locked($mform);
169+
return true;
157170
}
158171

159172
/**
@@ -429,6 +442,31 @@ public function is_visible() {
429442
}
430443
}
431444

445+
/**
446+
* Check if the field data is editable for the current user
447+
* This method should not generally be overwritten by child classes.
448+
* @return bool
449+
*/
450+
public function is_editable() {
451+
global $USER;
452+
453+
if (!$this->is_visible()) {
454+
return false;
455+
}
456+
457+
$systemcontext = context_system::instance();
458+
459+
if ($this->userid == $USER->id && has_capability('moodle/user:editownprofile', $systemcontext)) {
460+
return true;
461+
}
462+
463+
if (has_capability('moodle/user:update', $systemcontext)) {
464+
return true;
465+
}
466+
467+
return false;
468+
}
469+
432470
/**
433471
* Check if the field data is considered empty
434472
* @internal This method should not generally be overwritten by child classes.
@@ -565,27 +603,25 @@ function profile_load_data($user) {
565603
* @param int $userid id of user whose profile is being edited.
566604
*/
567605
function profile_definition($mform, $userid = 0) {
568-
global $CFG, $DB;
569-
570-
// If user is "admin" fields are displayed regardless.
571-
$update = has_capability('moodle/user:update', context_system::instance());
572-
573606
$categories = profile_get_user_fields_with_data_by_category($userid);
574607
foreach ($categories as $categoryid => $fields) {
575608
// Check first if *any* fields will be displayed.
576-
$display = false;
609+
$fieldstodisplay = [];
610+
577611
foreach ($fields as $formfield) {
578-
if ($formfield->is_visible()) {
579-
$display = true;
612+
if ($formfield->is_editable()) {
613+
$fieldstodisplay[] = $formfield;
580614
}
581615
}
582616

617+
if (empty($fieldstodisplay)) {
618+
continue;
619+
}
620+
583621
// Display the header and the fields.
584-
if ($display or $update) {
585-
$mform->addElement('header', 'category_'.$categoryid, format_string($formfield->get_category_name()));
586-
foreach ($fields as $formfield) {
587-
$formfield->edit_field($mform);
588-
}
622+
$mform->addElement('header', 'category_'.$categoryid, format_string($fields[0]->get_category_name()));
623+
foreach ($fieldstodisplay as $formfield) {
624+
$formfield->edit_field($mform);
589625
}
590626
}
591627
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
@core @core_user
2+
Feature: Custom profile fields should be visible and editable by those with the correct permissions.
3+
4+
Background: Attempting to self-register as a new user with empty names
5+
Given the following "users" exist:
6+
| username | firstname | lastname | email |
7+
| userwithinformation | userwithinformation | 1 | userwithinformation@example.com |
8+
And the following "courses" exist:
9+
| fullname | shortname | category | groupmode |
10+
| Course 1 | C1 | 0 | 1 |
11+
And the following "course enrolments" exist:
12+
| user | course | role |
13+
| userwithinformation | C1 | student |
14+
15+
And I log in as "admin"
16+
And I navigate to "User profile fields" node in "Site administration > Users > Accounts"
17+
And I set the field "datatype" to "Text input"
18+
And I set the following fields to these values:
19+
| Short name | notvisible_field |
20+
| Name | notvisible_field |
21+
| Who is this field visible to? | Not visible |
22+
And I click on "Save changes" "button"
23+
24+
And I set the field "datatype" to "Text input"
25+
And I set the following fields to these values:
26+
| Short name | uservisible_field |
27+
| Name | uservisible_field |
28+
| Who is this field visible to? | Visible to user |
29+
And I click on "Save changes" "button"
30+
31+
And I set the field "datatype" to "Text input"
32+
And I set the following fields to these values:
33+
| Short name | everyonevisible_field |
34+
| Name | everyonevisible_field |
35+
| Who is this field visible to? | Visible to everyone |
36+
And I click on "Save changes" "button"
37+
38+
And I navigate to "Browse list of users" node in "Site administration > Users > Accounts"
39+
And I click on ".icon[title=Edit]" "css_element" in the "userwithinformation@example.com" "table_row"
40+
And I expand all fieldsets
41+
And I set the field "notvisible_field" to "notvisible_field_information"
42+
And I set the field "uservisible_field" to "uservisible_field_information"
43+
And I set the field "everyonevisible_field" to "everyonevisible_field_information"
44+
And I click on "Update profile" "button"
45+
And I log out
46+
47+
@javascript
48+
Scenario: User with moodle/user:update but without moodle/user:viewalldetails can only update visible profile fields.
49+
Given the following "roles" exist:
50+
| name | shortname | description | archetype |
51+
| Update Users | updateusers | updateusers | |
52+
And the following "permission overrides" exist:
53+
| capability | permission | role | contextlevel | reference |
54+
| moodle/user:update | Allow | updateusers | System | |
55+
And the following "users" exist:
56+
| username | firstname | lastname | email |
57+
| user_updateusers | updateusers | 1 | updateusers@example.com |
58+
And the following "role assigns" exist:
59+
| user | role | contextlevel | reference |
60+
| user_updateusers | updateusers | System | |
61+
And the following "course enrolments" exist:
62+
| user | course | role |
63+
| user_updateusers | C1 | editingteacher |
64+
And I log in as "user_updateusers"
65+
And I am on "Course 1" course homepage
66+
And I navigate to course participants
67+
And I follow "userwithinformation 1"
68+
69+
Then I should see "everyonevisible_field"
70+
And I should see "everyonevisible_field_information"
71+
And I should not see "uservisible_field"
72+
And I should not see "uservisible_field_information"
73+
And I should not see "notvisible_field"
74+
And I should not see "notvisible_field_information"
75+
And I follow "Edit profile"
76+
And the following fields match these values:
77+
| everyonevisible_field | everyonevisible_field_information |
78+
And I should not see "uservisible_field"
79+
And I should not see "notvisible_field"
80+
81+
@javascript
82+
Scenario: User with moodle/user:viewalldetails but without moodle/user:update can view all profile fields.
83+
Given the following "roles" exist:
84+
| name | shortname | description | archetype |
85+
| View All Details | viewalldetails | viewalldetails | |
86+
And the following "permission overrides" exist:
87+
| capability | permission | role | contextlevel | reference |
88+
| moodle/user:viewalldetails | Allow | viewalldetails | System | |
89+
And the following "users" exist:
90+
| username | firstname | lastname | email |
91+
| user_viewalldetails | viewalldetails | 1 | viewalldetails@example.com |
92+
And the following "role assigns" exist:
93+
| user | role | contextlevel | reference |
94+
| user_viewalldetails | viewalldetails | System | |
95+
And the following "course enrolments" exist:
96+
| user | course | role |
97+
| user_viewalldetails | C1 | editingteacher |
98+
And I log in as "user_viewalldetails"
99+
And I am on "Course 1" course homepage
100+
And I navigate to course participants
101+
And I follow "userwithinformation 1"
102+
103+
Then I should see "everyonevisible_field"
104+
And I should see "everyonevisible_field_information"
105+
And I should see "uservisible_field"
106+
And I should see "uservisible_field_information"
107+
And I should see "notvisible_field"
108+
And I should see "notvisible_field_information"
109+
And I should not see "Edit profile"
110+
111+
@javascript
112+
Scenario: User with moodle/user:viewalldetails and moodle/user:update capabilities can view and edit all profile fields.
113+
Given the following "roles" exist:
114+
| name | shortname | description | archetype |
115+
| View All Details and Update Users | viewalldetailsandupdateusers | viewalldetailsandupdateusers | |
116+
And the following "permission overrides" exist:
117+
| capability | permission | role | contextlevel | reference |
118+
| moodle/user:viewalldetails | Allow | viewalldetailsandupdateusers | System | |
119+
| moodle/user:update | Allow | viewalldetailsandupdateusers | System | |
120+
And the following "users" exist:
121+
| username | firstname | lastname | email |
122+
| user_viewalldetailsandupdateusers | viewalldetailsandupdateusers | 1 | viewalldetailsandupdateusers@example.com |
123+
And the following "role assigns" exist:
124+
| user | role | contextlevel | reference |
125+
| user_viewalldetailsandupdateusers | viewalldetailsandupdateusers | System | |
126+
And the following "course enrolments" exist:
127+
| user | course | role |
128+
| user_viewalldetailsandupdateusers | C1 | editingteacher |
129+
And I log in as "user_viewalldetailsandupdateusers"
130+
And I am on "Course 1" course homepage
131+
And I navigate to course participants
132+
And I follow "userwithinformation 1"
133+
134+
Then I should see "everyonevisible_field"
135+
And I should see "everyonevisible_field_information"
136+
And I should see "uservisible_field"
137+
And I should see "uservisible_field_information"
138+
And I should see "notvisible_field"
139+
And I should see "notvisible_field_information"
140+
And I follow "Edit profile"
141+
And the following fields match these values:
142+
| everyonevisible_field | everyonevisible_field_information |
143+
| uservisible_field | uservisible_field_information |
144+
| notvisible_field | notvisible_field_information |
145+
146+
@javascript
147+
Scenario: Users can view and edit custom profile fields except those marked as not visible.
148+
Given I log in as "userwithinformation"
149+
And I follow "Profile" in the user menu
150+
151+
Then I should see "everyonevisible_field"
152+
And I should see "everyonevisible_field_information"
153+
And I should see "uservisible_field"
154+
And I should see "uservisible_field_information"
155+
And I should not see "notvisible_field"
156+
And I should not see "notvisible_field_information"
157+
158+
And I click on "Edit profile" "link" in the "region-main" "region"
159+
Then the following fields match these values:
160+
| everyonevisible_field | everyonevisible_field_information |
161+
| uservisible_field | uservisible_field_information |
162+
And I should not see "notvisible_field"
163+
And I should not see "notvisible_field_information"
164+
165+
@javascript
166+
Scenario: Users can view but not edit custom profile fields when denied the edit own profile capability.
167+
Given the following "roles" exist:
168+
| name | shortname | description | archetype |
169+
| Deny editownprofile | denyeditownprofile | denyeditownprofile | |
170+
171+
And the following "permission overrides" exist:
172+
| capability | permission | role | contextlevel | reference |
173+
| moodle/user:editownprofile | Prohibit | denyeditownprofile | System | |
174+
And the following "role assigns" exist:
175+
| user | role | contextlevel | reference |
176+
| userwithinformation | denyeditownprofile | System | |
177+
178+
And I log in as "userwithinformation"
179+
And I follow "Profile" in the user menu
180+
181+
Then I should see "everyonevisible_field"
182+
And I should see "everyonevisible_field_information"
183+
And I should see "uservisible_field"
184+
And I should see "uservisible_field_information"
185+
And I should not see "notvisible_field"
186+
And I should not see "notvisible_field_information"
187+
188+
And I should not see "Edit profile"

0 commit comments

Comments
 (0)