MDL-69194 user: make core_user_update_users return warnings

Add unit test coverage for the new warning scenarios.
This commit is contained in:
Matt Porritt 2021-04-08 00:44:17 +00:00
parent 6e7d77d11c
commit 8281261b5a
4 changed files with 69 additions and 9 deletions

View file

@ -626,4 +626,4 @@ $string['wwwrootslash'] = 'Detected incorrect $CFG->wwwroot in config.php, it mu
$string['xmldberror'] = 'XMLDB error!';
$string['alreadyloggedin'] = 'You are already logged in as {$a}, you need to log out before logging in as different user.';
$string['youcannotdeletecategory'] = 'You cannot delete category \'{$a}\' because you can neither delete the contents, nor move them elsewhere.';
$string['protected_cc_not_supported'] = 'Protected cartridges not supported.';
$string['protected_cc_not_supported'] = 'Protected cartridges not supported.';

View file

@ -572,26 +572,32 @@ class core_user_external extends external_api {
// First check the user exists.
if (!$existinguser = core_user::get_user($user['id'])) {
throw new moodle_exception('invaliduserid');
throw new moodle_exception('invaliduserid', '', '', null,
'Invalid user ID');
}
// Check if we are trying to update an admin.
if ($existinguser->id != $USER->id and is_siteadmin($existinguser) and !is_siteadmin($USER)) {
throw new moodle_exception('usernotupdatedadmin');
throw new moodle_exception('usernotupdatedadmin', '', '', null,
'Cannot update admin accounts');
}
// Other checks (deleted, remote or guest users).
if ($existinguser->deleted) {
throw new moodle_exception('usernotupdateddeleted');
throw new moodle_exception('usernotupdateddeleted', '', '', null,
'User is a deleted user');
}
if (is_mnet_remote_user($existinguser)) {
throw new moodle_exception('usernotupdatedremote');
throw new moodle_exception('usernotupdatedremote', '', '', null,
'User is a remote user');
}
if (isguestuser($existinguser->id)) {
throw new moodle_exception('usernotupdatedguest');
throw new moodle_exception('usernotupdatedguest', '', '', null,
'Cannot update guest account');
}
// Check duplicated emails.
if (isset($user['email']) && $user['email'] !== $existinguser->email) {
if (!validate_email($user['email'])) {
throw new moodle_exception('useremailinvalid');
throw new moodle_exception('useremailinvalid', '', '', null,
'Invalid email address');
} else if (empty($CFG->allowaccountssameemail)) {
// Make a case-insensitive query for the given email address
// and make sure to exclude the user being updated.
@ -603,7 +609,8 @@ class core_user_external extends external_api {
);
// Skip if there are other user(s) that already have the same email.
if ($DB->record_exists_select('user', $select, $params)) {
throw new moodle_exception('useremailduplicate');
throw new moodle_exception('useremailduplicate', '', '', null,
'Duplicate email address');
}
}
}

View file

@ -715,6 +715,7 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
global $USER, $CFG, $DB;
$this->resetAfterTest(true);
$this->preventResetByRollback();
$wsuser = self::getDataGenerator()->create_user();
self::setUser($wsuser);
@ -780,8 +781,20 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
$user4['id'] = $userdeleted->id;
user_delete_user($userdeleted);
$user5 = self::getDataGenerator()->create_user();
$user5 = array('id' => $user5->id, 'email' => $user5->email);
// Call the external function.
core_user_external::update_users(array($user1, $user2, $user3, $user4));
$returnvalue = core_user_external::update_users(array($user1, $user2, $user3, $user4));
$returnvalue = external_api::clean_returnvalue(core_user_external::update_users_returns(), $returnvalue);
// Check warnings.
$this->assertEquals($user2['id'], $returnvalue['warnings'][0]['itemid']); // Guest user.
$this->assertEquals('usernotupdatedguest', $returnvalue['warnings'][0]['warningcode']);
$this->assertEquals($user3['id'], $returnvalue['warnings'][1]['itemid']); // Admin user.
$this->assertEquals('usernotupdatedadmin', $returnvalue['warnings'][1]['warningcode']);
$this->assertEquals($user4['id'], $returnvalue['warnings'][2]['itemid']); // Deleted user.
$this->assertEquals('usernotupdateddeleted', $returnvalue['warnings'][2]['warningcode']);
$dbuser2 = $DB->get_record('user', array('id' => $user2['id']));
$this->assertNotEquals($dbuser2->username, $user2['username']);
@ -824,6 +837,39 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
$dbuserdelpic = $DB->get_record('user', array('id' => $user1['id']));
$this->assertEquals(0, $dbuserdelpic->picture, 'Picture must be deleted when sent as 0.');
// Updating user with an invalid email.
$user5['email'] = 'bogus';
$returnvalue = core_user_external::update_users(array($user5));
$returnvalue = external_api::clean_returnvalue(core_user_external::update_users_returns(), $returnvalue);
$this->assertEquals('useremailinvalid', $returnvalue['warnings'][0]['warningcode']);
$this->assertStringContainsString('Invalid email address',
$returnvalue['warnings'][0]['message']);
// Updating user with a duplicate email.
$user5['email'] = $user1['email'];
$returnvalue = core_user_external::update_users(array($user1, $user5));
$returnvalue = external_api::clean_returnvalue(core_user_external::update_users_returns(), $returnvalue);
$this->assertEquals('useremailduplicate', $returnvalue['warnings'][0]['warningcode']);
$this->assertStringContainsString('Duplicate email address',
$returnvalue['warnings'][0]['message']);
// Updating a user that does not exist.
$user5['id'] = -1;
$returnvalue = core_user_external::update_users(array($user5));
$returnvalue = external_api::clean_returnvalue(core_user_external::update_users_returns(), $returnvalue);
$this->assertEquals('invaliduserid', $returnvalue['warnings'][0]['warningcode']);
$this->assertStringContainsString('Invalid user ID',
$returnvalue['warnings'][0]['message']);
// Updating a remote user.
$user1['mnethostid'] = 5;
user_update_user($user1); // Update user not using webservice.
unset($user1['mnethostid']); // The mnet host ID field is not in the allowed field list for the webservice.
$returnvalue = core_user_external::update_users(array($user1));
$returnvalue = external_api::clean_returnvalue(core_user_external::update_users_returns(), $returnvalue);
$this->assertEquals('usernotupdatedremote', $returnvalue['warnings'][0]['warningcode']);
$this->assertStringContainsString('User is a remote user',
$returnvalue['warnings'][0]['message']);
// Call without required capability.
$this->unassignUserCapability('moodle/user:update', $context->id, $roleid);

View file

@ -1,5 +1,12 @@
This files describes API changes for code that uses the user API.
=== 4.0 ===
* External function core_user_external::update_users() will now fail on a per user basis. Previously if one user
update failed all users in the operation would fail.
* External function core_user_external::update_users() now returns an error code and message to why a user update
action failed.
=== 3.11 ===
* Added new core_user/form_user_selector JS module that can be used as the 'ajax' handler for the autocomplete form