MDL-61939 tool_policy: usermodified should be realuser

When logged in as another user and accept the policies on somebody else's behalf make sure that
usermodified is recorded as real user
This commit is contained in:
Marina Glancy 2018-04-13 13:41:00 +08:00
parent 6fa694bef0
commit e8cf2ffd61
8 changed files with 167 additions and 68 deletions

View file

@ -29,6 +29,7 @@ use coding_exception;
use context_helper;
use context_system;
use context_user;
use core\session\manager;
use stdClass;
use tool_policy\event\acceptance_created;
use tool_policy\event\acceptance_updated;
@ -772,6 +773,46 @@ class api {
return $ret;
}
/**
* Checks if user can accept policies for themselves or on behalf of another user
*
* @param int $userid
* @param bool $throwexception
* @return bool
*/
public static function can_accept_policies($userid = null, $throwexception = false) {
global $USER;
if (!isloggedin() || isguestuser()) {
if ($throwexception) {
throw new \moodle_exception('noguest');
} else {
return false;
}
}
if (!$userid) {
$userid = $USER->id;
}
if ($userid == $USER->id && !manager::is_loggedinas()) {
if ($throwexception) {
require_capability('tool/policy:accept', context_system::instance());
return;
} else {
return has_capability('tool/policy:accept', context_system::instance());
}
}
// Check capability to accept on behalf as the real user.
$realuser = manager::get_realuser();
$usercontext = \context_user::instance($userid);
if ($throwexception) {
require_capability('tool/policy:acceptbehalf', $usercontext, $realuser);
return;
} else {
return has_capability('tool/policy:acceptbehalf', $usercontext, $realuser);
}
}
/**
* Accepts the current revisions of all policies that the user has not yet accepted
*
@ -782,24 +823,18 @@ class api {
*/
public static function accept_policies($policyversionid, $userid = null, $note = null, $lang = null) {
global $DB, $USER;
if (!isloggedin() || isguestuser()) {
throw new \moodle_exception('noguest');
}
if (!$userid) {
$userid = $USER->id;
}
$usercontext = \context_user::instance($userid);
if ($userid == $USER->id) {
require_capability('tool/policy:accept', context_system::instance());
} else {
require_capability('tool/policy:acceptbehalf', $usercontext);
}
// Validate arguments and capabilities.
if (empty($policyversionid)) {
return;
} else if (!is_array($policyversionid)) {
$policyversionid = [$policyversionid];
}
if (!$userid) {
$userid = $USER->id;
}
self::can_accept_policies($userid, true);
// Retrieve the list of policy versions that need agreement (do not update existing agreements).
list($sql, $params) = $DB->get_in_or_equal($policyversionid, SQL_PARAMS_NAMED);
$sql = "SELECT v.id AS versionid, a.*
FROM {tool_policy_versions} v
@ -807,8 +842,9 @@ class api {
WHERE (a.id IS NULL or a.status <> 1) AND v.id " . $sql;
$needacceptance = $DB->get_records_sql($sql, ['userid' => $userid] + $params);
$realuser = manager::get_realuser();
$updatedata = ['status' => 1, 'lang' => $lang ?: current_language(),
'timemodified' => time(), 'usermodified' => $USER->id, 'note' => $note];
'timemodified' => time(), 'usermodified' => $realuser->id, 'note' => $note];
foreach ($needacceptance as $versionid => $currentacceptance) {
unset($currentacceptance->versionid);
if ($currentacceptance->id) {
@ -871,23 +907,16 @@ class api {
*/
public static function revoke_acceptance($policyversionid, $userid, $note = null) {
global $DB, $USER;
if (!isloggedin() || isguestuser()) {
throw new \moodle_exception('noguest');
}
if (!$userid) {
$userid = $USER->id;
}
$usercontext = \context_user::instance($userid);
if ($userid == $USER->id) {
require_capability('tool/policy:accept', context_system::instance());
} else {
require_capability('tool/policy:acceptbehalf', $usercontext);
}
self::can_accept_policies($userid, true);
if ($currentacceptance = $DB->get_record('tool_policy_acceptances',
['policyversionid' => $policyversionid, 'userid' => $userid])) {
$realuser = manager::get_realuser();
$updatedata = ['id' => $currentacceptance->id, 'status' => 0, 'timemodified' => time(),
'usermodified' => $USER->id, 'note' => $note];
'usermodified' => $realuser->id, 'note' => $note];
$DB->update_record('tool_policy_acceptances', $updatedata);
acceptance_updated::create_from_record((object)($updatedata + (array)$currentacceptance))->trigger();
}

View file

@ -94,7 +94,7 @@ class accept_policy extends \moodleform {
* @return array (userid=>username)
*/
protected function validate_and_get_users($userids) {
global $DB, $USER;
global $DB;
$usernames = [];
list($sql, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$params['usercontextlevel'] = CONTEXT_USER;
@ -103,7 +103,6 @@ class accept_policy extends \moodleform {
" FROM {user} u JOIN {context} ctx ON ctx.contextlevel=:usercontextlevel AND ctx.instanceid = u.id
WHERE u.id " . $sql, $params);
$acceptany = has_capability('tool/policy:acceptbehalf', \context_system::instance());
foreach ($userids as $userid) {
if (!isset($users[$userid])) {
throw new \dml_missing_record_exception('user', 'id=?', [$userid]);
@ -112,12 +111,8 @@ class accept_policy extends \moodleform {
if (isguestuser($user)) {
throw new \moodle_exception('noguest');
}
if ($userid == $USER->id) {
require_capability('tool/policy:accept', \context_system::instance());
} else if (!$acceptany) {
\context_helper::preload_from_record($user);
require_capability('tool/policy:acceptbehalf', \context_user::instance($userid));
}
api::can_accept_policies($userid, true);
$usernames[$userid] = fullname($user);
}
return $usernames;

View file

@ -29,6 +29,7 @@ defined('MOODLE_INTERNAL') || die();
use context_system;
use core\output\notification;
use core\session\manager;
use core_user;
use html_writer;
use moodle_url;
@ -77,21 +78,19 @@ class page_agreedocs implements renderable, templatable {
*/
public function __construct($agreedocs = null, $behalfid = 0, $action = null) {
global $USER;
$realuser = manager::get_realuser();
$this->agreedocs = $agreedocs;
if (empty($this->agreedocs)) {
$this->agreedocs = [];
}
$this->behalfid = $behalfid;
$this->action = $action;
if (!empty($this->behalfid) && $USER->id != $this->behalfid) {
$this->behalfuser = core_user::get_user($this->behalfid, '*');
// If behalf user doesn't exist, behalfid parameter will be ignored.
if ($this->behalfuser === false) {
$this->behalfid = 0;
}
$behalfid = $behalfid ?: $USER->id;
if ($realuser->id != $behalfid) {
$this->behalfuser = core_user::get_user($behalfid, '*', MUST_EXIST);
$this->behalfid = $this->behalfuser->id;
}
$this->policies = api::list_current_versions(policy_version::AUDIENCE_LOGGEDIN);
@ -267,12 +266,7 @@ class page_agreedocs implements renderable, templatable {
// Check for correct user capabilities.
if (!empty($USER->id)) {
// For existing users, it's needed to check if they have the capability for accepting policies.
if (empty($this->behalfid) || $this->behalfid == $USER->id) {
require_capability('tool/policy:accept', context_system::instance());
} else {
$usercontext = \context_user::instance($this->behalfid);
require_capability('tool/policy:acceptbehalf', $usercontext);
}
api::can_accept_policies($this->behalfid, true);
} else {
// For new users, the behalfid parameter is ignored.
if ($this->behalfid != $USER->id) {

View file

@ -25,6 +25,7 @@
namespace tool_policy\output;
use core\session\manager;
use moodle_exception;
defined('MOODLE_INTERNAL') || die();
@ -69,23 +70,16 @@ class page_nopermission implements renderable, templatable {
public function __construct($behalfid) {
global $USER;
$this->behalfid = $behalfid;
if (!empty($this->behalfid) && $USER->id != $this->behalfid) {
$this->behalfuser = core_user::get_user($this->behalfid, '*');
// If behalf user doesn't exist, behalfid parameter will be ignored.
if ($this->behalfuser === false) {
$this->behalfid = 0;
}
$behalfid = $behalfid ?: $USER->id;
$realuser = manager::get_realuser();
if ($realuser->id != $behalfid) {
$this->behalfuser = core_user::get_user($behalfid, '*', MUST_EXIST);
$this->behalfid = $this->behalfuser->id;
}
if (!empty($USER->id)) {
// For existing users, it's needed to check if they have the capability for accepting policies.
if (empty($this->behalfid) || $this->behalfid == $USER->id) {
$this->haspermissionagreedocs = has_capability('tool/policy:accept', context_system::instance());
} else {
$usercontext = \context_user::instance($this->behalfid);
$this->haspermissionagreedocs = has_capability('tool/policy:acceptbehalf', $usercontext);
}
$this->haspermissionagreedocs = api::can_accept_policies($this->behalfid);
}
$this->policies = api::list_current_versions(policy_version::AUDIENCE_LOGGEDIN);
@ -128,7 +122,7 @@ class page_nopermission implements renderable, templatable {
* Export the page data for the mustache template.
*
* @param renderer_base $output renderer to be used to render the page elements.
* @return stdClass
* @return \stdClass
*/
public function export_for_template(renderer_base $output) {
global $CFG;

View file

@ -77,8 +77,7 @@ class user_agreement implements \templatable, \renderable {
$this->accepted = $accepted;
$this->canaccept = $canaccept;
if (count($this->accepted) < count($this->versions) && $canaccept === null) {
$this->canaccept = (has_capability('tool/policy:acceptbehalf', \context_system::instance()) ||
has_capability('tool/policy:acceptbehalf', \context_user::instance($this->userid)));
$this->canaccept = \tool_policy\api::can_accept_policies($this->userid);
}
}

View file

@ -44,15 +44,9 @@ $PAGE->set_context(context_system::instance());
$PAGE->set_url('/admin/tool/policy/index.php');
$PAGE->set_popup_notification_allowed(false);
$haspermissionagreedocs = false;
if (!empty($USER->id)) {
// Existing user.
if (empty($behalfid) || $behalfid == $USER->id) {
$haspermissionagreedocs = has_capability('tool/policy:accept', context_system::instance());
} else {
$usercontext = \context_user::instance($behalfid);
$haspermissionagreedocs = has_capability('tool/policy:acceptbehalf', $usercontext);
}
$haspermissionagreedocs = api::can_accept_policies($behalfid);
} else {
// New user.
$haspermissionagreedocs = true;
@ -63,6 +57,9 @@ if (!$haspermissionagreedocs) {
} else if ($cancel) {
redirect(new moodle_url('/'));
} else {
if (!$behalfid && \core\session\manager::is_loggedinas()) {
$behalfid = $USER->id;
}
$outputpage = new \tool_policy\output\page_agreedocs($agreedocs, $behalfid, $submit);
}

View file

@ -228,3 +228,34 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I navigate to course participants
And I follow "User Two"
Then I should see "Policies and agreements"
Scenario: Agree on behalf of another user as an admin who is logged in as a manager
Given I log in as "admin"
And I set the following system permissions of "Manager" role:
| capability | permission |
| tool/policy:acceptbehalf | Allow |
And I log out
When I log in as "manager"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I log out
And I log in as "admin"
And I navigate to "Users > Accounts > Browse list of users" in site administration
And I follow "Manager"
And I follow "Log in as"
And I press "Continue"
And I navigate to "Privacy and policies > Manage policies" in site administration
And I click on "1 of 4 (25%)" "link" in the "This site policy" "table_row"
And I click on "Not agreed" "link" in the "User One" "table_row"
Then I should see "Consent details"
And I should see "User One"
And I should see "This site policy"
And I should see "I acknowledge that consents to these policies have been acquired"
And I set the field "Remarks" to "Consent received from a parent"
And I press "I agree to the policy"
And "Agreed on behalf of" "icon" should exist in the "User One" "table_row"
And "Max Manager" "link" should not exist in the "User One" "table_row"
And "Admin User" "link" should exist in the "User One" "table_row"
And "Consent received from a parent" "text" should exist in the "User One" "table_row"
And "Not agreed" "icon" should exist in the "User Two" "table_row"

View file

@ -551,3 +551,63 @@ Feature: User must accept policy managed by this plugin when logging in and sign
When I press "Next"
Then I should not see "I understand and agree"
And I should see "New account"
Scenario: Accept policy while being logged in as another user
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
When I log in as "admin"
And I navigate to "Users > Accounts > Browse list of users" in site administration
And I follow "User 1"
And I follow "Log in as"
Then I should see "You are logged in as User 1"
And I press "Continue"
And I should see "Please read our This site policy"
And I press "Next"
And I should see "Please read our This privacy policy"
And I press "Next"
And I should see "Viewing this page on behalf of User 1"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I log out
And I log in as "user1"
And I follow "Profile" in the user menu
And I follow "Policies and agreements"
And "Admin User" "link" should exist in the "This site policy" "table_row"
And "Admin User" "link" should exist in the "This privacy policy" "table_row"
Scenario: Log in as another user without capability to accept policies on their behalf
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
| manager | Max | Manager | man@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| manager | manager | System | |
When I log in as "manager"
And I press "Next"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I navigate to "Users > Accounts > Browse list of users" in site administration
And I follow "User 1"
And I follow "Log in as"
Then I should see "You are logged in as User 1"
And I press "Continue"
And I should see "Policies and agreements"
And I should see "No permission to agree to the policies on behalf of this user"
And I should see "Sorry, you do not have the required permission to agree to the following policies on behalf of User 1"