diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 1506890cc98..e19eb1f5852 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -4754,13 +4754,19 @@ function update_internal_user_password($user, $password, $fasthash = false) { $hashedpassword = hash_internal_user_password($password, $fasthash); } - // If verification fails then it means the password has changed. - if (isset($user->password)) { - // While creating new user, password in unset in $user object, to avoid - // saving it with user_create() + $algorithmchanged = false; + + if ($hashedpassword === AUTH_PASSWORD_NOT_CACHED) { + // Password is not cached, update it if not set to AUTH_PASSWORD_NOT_CACHED. + $passwordchanged = ($user->password !== $hashedpassword); + + } else if (isset($user->password)) { + // If verification fails then it means the password has changed. $passwordchanged = !password_verify($password, $user->password); $algorithmchanged = password_needs_rehash($user->password, PASSWORD_DEFAULT); } else { + // While creating new user, password in unset in $user object, to avoid + // saving it with user_create() $passwordchanged = true; } diff --git a/lib/tests/moodlelib_test.php b/lib/tests/moodlelib_test.php index 016d656b145..776d1fcb60b 100644 --- a/lib/tests/moodlelib_test.php +++ b/lib/tests/moodlelib_test.php @@ -2271,6 +2271,39 @@ class core_moodlelib_testcase extends advanced_testcase { $this->assertEquals('manual', $user->auth); } + /** + * Testing that if the password is not cached, that it does not update + * the user table and fire event. + */ + public function test_update_internal_user_password_no_cache() { + $this->resetAfterTest(); + + $user = $this->getDataGenerator()->create_user(array('auth' => 'cas')); + $this->assertEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); + + $sink = $this->redirectEvents(); + update_internal_user_password($user, 'wonkawonka'); + $this->assertEquals(0, $sink->count(), 'User updated event should not fire'); + } + + /** + * Test if the user has a password hash, but now their auth method + * says not to cache it. Then it should update. + */ + public function test_update_internal_user_password_update_no_cache() { + $this->resetAfterTest(); + + $user = $this->getDataGenerator()->create_user(array('password' => 'test')); + $this->assertNotEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); + $user->auth = 'cas'; // Change to a auth that does not store passwords. + + $sink = $this->redirectEvents(); + update_internal_user_password($user, 'wonkawonka'); + $this->assertGreaterThanOrEqual(1, $sink->count(), 'User updated event should fire'); + + $this->assertEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); + } + public function test_fullname() { global $CFG;