From 8ee3a3e9d8aa1da1772be60a3080626257cd76fe Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Mon, 2 Feb 2026 11:40:42 -0400 Subject: [PATCH 1/5] refactor PasswordRehash configuration --- config/users.php | 4 +- .../Controller/Traits/LoginTraitTest.php | 150 ++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 2b41eb46..1210d07b 100644 --- a/config/users.php +++ b/config/users.php @@ -284,7 +284,9 @@ ], 'RbacPolicy' => [], 'PasswordRehash' => [ - 'identifiers' => ['Password'], + 'authenticators' => [ + 'Form' => 'Authentication.Password', + ], ], ], 'OAuth' => [ diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 8af0d18e..d007a361 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -22,11 +22,14 @@ use Cake\Event\Event; use Cake\Http\Response; use Cake\Http\ServerRequest; +use CakeDC\Auth\Authentication\AuthenticationService; use CakeDC\Auth\Authentication\Failure; use CakeDC\Auth\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Controller\Component\LoginComponent; +use Authentication\Authenticator\AuthenticatorCollection; + class LoginTraitTest extends BaseTrait { /** @@ -219,6 +222,153 @@ public function testLoginRehash() $this->assertTrue($check); } + + /** + * Test para verificar el Rehashing con la estructura de configuración anidada (Cake 5) + * Fix para issue #1170 + * + * @return void + */ + /* + public function testLoginRehashWithAuthenticatorStructure() + { + // 1. Configuración del Plugin + \Cake\Core\Configure::write('Auth.PasswordRehash', [ + 'authenticators' => [ + 'Form' => 'Authentication.Password' + ] + ]); + + // 2. Preparación de datos + $userId = '00000000-0000-0000-0000-000000000002'; + $user = $this->Trait->getUsersTable()->get($userId); + $oldHash = '$2y$10$OldHashNeedsUpgrade00000000000000000000000000000000'; + $user->password = $oldHash; + $this->Trait->getUsersTable()->save($user); + + // 3. Construcción de Mocks (Estilo Cake 5) + + // A. Identifier + $passwordIdentifier = $this->getMockBuilder(PasswordIdentifier::class) + ->onlyMethods(['needsPasswordRehash']) + ->getMock(); + $passwordIdentifier->expects($this->any()) + ->method('needsPasswordRehash') + ->willReturn(true); + + // B. Identifier Collection + $identifierCollection = new IdentifierCollection([]); + $identifierCollection->set('Authentication.Password', $passwordIdentifier); + + // C. Authenticator + $formAuthenticator = $this->getMockBuilder(FormAuthenticator::class) + ->disableOriginalConstructor() + ->addMethods(['getIdentifier']) + ->getMock(); + $formAuthenticator->expects($this->any()) + ->method('getIdentifier') + ->willReturn($identifierCollection); + + // D. Authenticator Collection + $authenticatorCollection = $this->getMockBuilder(AuthenticatorCollection::class) + ->disableOriginalConstructor() + ->getMock(); + $authenticatorCollection->expects($this->any()) + ->method('has')->with('Form')->willReturn(true); + $authenticatorCollection->expects($this->any()) + ->method('get')->with('Form')->willReturn($formAuthenticator); + + // E. Servicio + $service = $this->getMockBuilder(AuthenticationService::class) + ->disableOriginalConstructor() + ->getMock(); + $service->expects($this->any()) + ->method('authenticators') + ->willReturn($authenticatorCollection); + $service->expects($this->any()) + ->method('identifiers') + ->willReturn(new IdentifierCollection([])); + $service->expects($this->any()) + ->method('getAuthenticationProvider') + ->willReturn($formAuthenticator); + + $result = new Result($user, Result::SUCCESS); + $service->expects($this->any())->method('getResult')->willReturn($result); + + // 4. Configuración del Request + $this->_mockDispatchEvent(new Event('event')); + + $request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->onlyMethods(['is', 'getData']) + ->getMock(); + + $request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + + $request->expects($this->any()) + ->method('getData') + ->will($this->returnCallback(function($key = null) use ($user) { + if ($key === 'password') return 'password123'; + if ($key === 'username' || $key === 'email') return $user->email; + return []; + })); + + // --- CORRECCIÓN AQUÍ: Envolvemos el usuario en Identity --- + $identityWrapper = new \Authentication\Identity($user); + + $request = $request->withAttribute('authentication', $service); + $request = $request->withAttribute('identity', $identityWrapper); // Usamos el wrapper, no el user directo + + $this->Trait->setRequest($request); + + // 5. Configuración del Componente Login + $registry = new ComponentRegistry(new \Cake\Controller\Controller(new \Cake\Http\ServerRequest())); + $config = [ + 'component' => 'CakeDC/Users.Login', + 'targetAuthenticator' => FormAuthenticator::class, + 'PasswordRehash' => [ + 'authenticators' => ['Form' => 'Authentication.Password'] + ] + ]; + + $Login = $this->getMockBuilder(LoginComponent::class) + ->onlyMethods(['getController']) + ->setConstructorArgs([$registry, $config]) + ->getMock(); + + $Login->expects($this->any()) + ->method('getController') + ->will($this->returnValue($this->Trait)); + + $this->Trait->expects($this->any()) + ->method('loadComponent') + ->with( + $this->equalTo('CakeDC/Users.Login'), + $this->anything() + ) + ->will($this->returnValue($Login)); + + // 6. Ejecución + $this->_mockFlash(); + $this->Trait->expects($this->once()) + ->method('redirect') + ->will($this->returnValue(new Response())); + + $this->Trait->login(); + + // 7. Aserciones + $userAfter = $this->Trait->getUsersTable()->get($userId); + + $this->assertNotEquals( + $oldHash, + $userAfter->password, + 'El password debería haber sido actualizado (rehashed)' + ); + } + /* */ + /** * test * From 1dd8ed9729bd25c214f3c730bc1b766307c865f7 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Fri, 6 Feb 2026 12:09:58 -0400 Subject: [PATCH 2/5] feat: enhance login rehash functionality with improved authenticator structure --- .../Controller/Traits/LoginTraitTest.php | 194 +++++++++++------- 1 file changed, 121 insertions(+), 73 deletions(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index d007a361..b1850b7d 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -1,4 +1,5 @@ getMock(); // $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - // ->onlyMethods(['setConfig']) - // ->disableOriginalConstructor() - // ->getMock(); + // ->onlyMethods(['setConfig']) + // ->disableOriginalConstructor() + // ->getMock(); } /** @@ -150,52 +151,112 @@ public function testLoginHappy() */ public function testLoginRehash() { + \Cake\Core\Configure::write('Auth.PasswordRehash', [ + 'authenticators' => [ + 'Form' => 'Password' + ] + ]); + $passwordIdentifier = $this->getMockBuilder(PasswordIdentifier::class) ->onlyMethods(['needsPasswordRehash']) ->getMock(); $passwordIdentifier->expects($this->any()) ->method('needsPasswordRehash') ->willReturn(true); - $identifiers = new IdentifierCollection([]); - $identifiers->set('Password', $passwordIdentifier); - $SessionAuth = new SessionAuthenticator($identifiers); + $identifierCollection = new IdentifierCollection([]); + $identifierCollection->set('Password', $passwordIdentifier); - $sessionFailure = new Failure( - $SessionAuth, - new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND), - ); - $failures = [$sessionFailure]; + $formAuthenticator = $this->getMockBuilder(FormAuthenticator::class) + ->disableOriginalConstructor() + ->addMethods(['getIdentifier']) + ->getMock(); + $formAuthenticator->expects($this->any()) + ->method('getIdentifier') + ->willReturn($identifierCollection); + + $authenticatorCollection = $this->getMockBuilder(AuthenticatorCollection::class) + ->disableOriginalConstructor() + ->getMock(); + $authenticatorCollection->expects($this->any()) + ->method('has')->with('Form')->willReturn(true); + $authenticatorCollection->expects($this->any()) + ->method('get')->with('Form')->willReturn($formAuthenticator); + $user = $this->Trait->getUsersTable()->get('00000000-0000-0000-0000-000000000002'); + $passwordBefore = $user['password']; $userPassword = 'testLoginRehash' . time(); + + $service = $this->getMockBuilder(AuthenticationService::class) + ->disableOriginalConstructor() + ->getMock(); + $service->expects($this->any()) + ->method('authenticators') + ->willReturn($authenticatorCollection); + $service->expects($this->any()) + ->method('identifiers') + ->willReturn(new IdentifierCollection([])); + $service->expects($this->any()) + ->method('getAuthenticationProvider') + ->willReturn($formAuthenticator); + + $result = new Result($user, Result::SUCCESS); + $service->expects($this->any())->method('getResult')->willReturn($result); + $this->_mockDispatchEvent(new Event('event')); - $this->_mockRequestPost(); - $this->Trait->getRequest()->expects($this->any()) + + $request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->onlyMethods(['is', 'getData']) + ->getMock(); + + $request->expects($this->any()) + ->method('is') + ->with('post') + ->willReturn(true); + + $request->expects($this->any()) ->method('getData') - ->with($this->equalTo('password')) - ->willReturn($userPassword); + ->willReturnCallback(function ($key = null) use ($userPassword, $user) { + if ($key === 'password') return $userPassword; + if ($key === 'username' || $key === 'email') return $user->email; + return []; + }); + + $identityWrapper = new \Authentication\Identity($user); + $request = $request->withAttribute('authentication', $service); + $request = $request->withAttribute('identity', $identityWrapper); + + $this->Trait->setRequest($request); + + $authComponent = $this->getMockBuilder(\Cake\Controller\Component::class) + ->disableOriginalConstructor() + ->onlyMethods(['getConfig']) + ->getMock(); + $authComponent->expects($this->any()) + ->method('getConfig') + ->with('loginRedirect') + ->willReturn('/home'); + + $this->Trait->components()->set('Authentication', $authComponent); $this->_mockFlash(); - $user = $this->Trait->getUsersTable()->get('00000000-0000-0000-0000-000000000002'); - $passwordBefore = $user['password']; - $this->assertNotEmpty($passwordBefore); - $this->_mockAuthentication($user->toArray(), $failures, $identifiers); $this->Trait->Flash->expects($this->never()) ->method('error'); + $this->Trait->expects($this->once()) ->method('redirect') ->with($this->successLoginRedirect) - ->will($this->returnValue(new Response())); + ->willReturn(new Response()); $registry = new ComponentRegistry(new \Cake\Controller\Controller(new \Cake\Http\ServerRequest())); $config = [ 'component' => 'CakeDC/Users.Login', - 'defaultMessage' => __d('cake_d_c/users', 'Username or password is incorrect'), - 'messages' => [ - FormAuthenticator::FAILURE_INVALID_RECAPTCHA => __d('cake_d_c/users', 'Invalid reCaptcha'), - ], 'targetAuthenticator' => FormAuthenticator::class, + 'PasswordRehash' => [ + 'authenticators' => ['Form' => 'Password'] + ] ]; + $Login = $this->getMockBuilder(LoginComponent::class) ->onlyMethods(['getController']) ->setConstructorArgs([$registry, $config]) @@ -203,52 +264,39 @@ public function testLoginRehash() $Login->expects($this->any()) ->method('getController') - ->will($this->returnValue($this->Trait)); + ->willReturn($this->Trait); $this->Trait->expects($this->any()) ->method('loadComponent') ->with( $this->equalTo('CakeDC/Users.Login'), - $this->equalTo($config), + $this->anything() ) - ->will($this->returnValue($Login)); + ->willReturn($Login); $result = $this->Trait->login(); $this->assertInstanceOf(Response::class, $result); + $userAfter = $this->Trait->getUsersTable()->get('00000000-0000-0000-0000-000000000002'); - $passwordAfter = $userAfter['password']; - $this->assertNotEquals($passwordBefore, $passwordAfter); + $this->assertNotEquals($passwordBefore, $userAfter['password']); + $passwordHasher = new DefaultPasswordHasher(); - $check = $passwordHasher->check($userPassword, $passwordAfter); - $this->assertTrue($check); + $this->assertTrue($passwordHasher->check($userPassword, $userAfter['password'])); } - - /** - * Test para verificar el Rehashing con la estructura de configuración anidada (Cake 5) - * Fix para issue #1170 - * - * @return void - */ - /* public function testLoginRehashWithAuthenticatorStructure() { - // 1. Configuración del Plugin \Cake\Core\Configure::write('Auth.PasswordRehash', [ 'authenticators' => [ 'Form' => 'Authentication.Password' ] ]); - // 2. Preparación de datos $userId = '00000000-0000-0000-0000-000000000002'; $user = $this->Trait->getUsersTable()->get($userId); $oldHash = '$2y$10$OldHashNeedsUpgrade00000000000000000000000000000000'; $user->password = $oldHash; $this->Trait->getUsersTable()->save($user); - // 3. Construcción de Mocks (Estilo Cake 5) - - // A. Identifier $passwordIdentifier = $this->getMockBuilder(PasswordIdentifier::class) ->onlyMethods(['needsPasswordRehash']) ->getMock(); @@ -256,11 +304,9 @@ public function testLoginRehashWithAuthenticatorStructure() ->method('needsPasswordRehash') ->willReturn(true); - // B. Identifier Collection $identifierCollection = new IdentifierCollection([]); $identifierCollection->set('Authentication.Password', $passwordIdentifier); - // C. Authenticator $formAuthenticator = $this->getMockBuilder(FormAuthenticator::class) ->disableOriginalConstructor() ->addMethods(['getIdentifier']) @@ -269,7 +315,6 @@ public function testLoginRehashWithAuthenticatorStructure() ->method('getIdentifier') ->willReturn($identifierCollection); - // D. Authenticator Collection $authenticatorCollection = $this->getMockBuilder(AuthenticatorCollection::class) ->disableOriginalConstructor() ->getMock(); @@ -278,7 +323,6 @@ public function testLoginRehashWithAuthenticatorStructure() $authenticatorCollection->expects($this->any()) ->method('get')->with('Form')->willReturn($formAuthenticator); - // E. Servicio $service = $this->getMockBuilder(AuthenticationService::class) ->disableOriginalConstructor() ->getMock(); @@ -291,13 +335,12 @@ public function testLoginRehashWithAuthenticatorStructure() $service->expects($this->any()) ->method('getAuthenticationProvider') ->willReturn($formAuthenticator); - + $result = new Result($user, Result::SUCCESS); $service->expects($this->any())->method('getResult')->willReturn($result); - // 4. Configuración del Request $this->_mockDispatchEvent(new Event('event')); - + $request = $this->getMockBuilder('Cake\Http\ServerRequest') ->onlyMethods(['is', 'getData']) ->getMock(); @@ -305,25 +348,35 @@ public function testLoginRehashWithAuthenticatorStructure() $request->expects($this->any()) ->method('is') ->with('post') - ->will($this->returnValue(true)); + ->willReturn(true); $request->expects($this->any()) ->method('getData') - ->will($this->returnCallback(function($key = null) use ($user) { + ->willReturnCallback(function ($key = null) use ($user) { if ($key === 'password') return 'password123'; if ($key === 'username' || $key === 'email') return $user->email; return []; - })); - - // --- CORRECCIÓN AQUÍ: Envolvemos el usuario en Identity --- + }); + $identityWrapper = new \Authentication\Identity($user); - + $request = $request->withAttribute('authentication', $service); - $request = $request->withAttribute('identity', $identityWrapper); // Usamos el wrapper, no el user directo + $request = $request->withAttribute('identity', $identityWrapper); $this->Trait->setRequest($request); - // 5. Configuración del Componente Login + $authComponent = $this->getMockBuilder(\Cake\Controller\Component::class) + ->disableOriginalConstructor() + ->onlyMethods(['getConfig']) + ->getMock(); + + $authComponent->expects($this->any()) + ->method('getConfig') + ->with('loginRedirect') + ->willReturn('/'); + + $this->Trait->components()->set('Authentication', $authComponent); + $registry = new ComponentRegistry(new \Cake\Controller\Controller(new \Cake\Http\ServerRequest())); $config = [ 'component' => 'CakeDC/Users.Login', @@ -332,7 +385,7 @@ public function testLoginRehashWithAuthenticatorStructure() 'authenticators' => ['Form' => 'Authentication.Password'] ] ]; - + $Login = $this->getMockBuilder(LoginComponent::class) ->onlyMethods(['getController']) ->setConstructorArgs([$registry, $config]) @@ -340,7 +393,7 @@ public function testLoginRehashWithAuthenticatorStructure() $Login->expects($this->any()) ->method('getController') - ->will($this->returnValue($this->Trait)); + ->willReturn($this->Trait); $this->Trait->expects($this->any()) ->method('loadComponent') @@ -348,26 +401,21 @@ public function testLoginRehashWithAuthenticatorStructure() $this->equalTo('CakeDC/Users.Login'), $this->anything() ) - ->will($this->returnValue($Login)); + ->willReturn($Login); - // 6. Ejecución - $this->_mockFlash(); $this->Trait->expects($this->once()) ->method('redirect') - ->will($this->returnValue(new Response())); + ->willReturn(new Response()); $this->Trait->login(); - // 7. Aserciones $userAfter = $this->Trait->getUsersTable()->get($userId); - + $this->assertNotEquals( - $oldHash, - $userAfter->password, - 'El password debería haber sido actualizado (rehashed)' + $oldHash, + $userAfter->password ); } - /* */ /** * test @@ -417,8 +465,8 @@ public function testLoginGet() ->method('getController') ->will($this->returnValue($this->Trait)); // $this->Trait->expects($this->any()) - // ->method('getRequest') - // ->will($this->returnValue($request)); + // ->method('getRequest') + // ->will($this->returnValue($request)); $this->Trait->expects($this->any()) ->method('loadComponent') ->with( From 6e425dd61add14d59898f7c2f39515eadcabe49e Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Fri, 6 Feb 2026 12:11:32 -0400 Subject: [PATCH 3/5] phpcs fix --- .../Controller/Traits/LoginTraitTest.php | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index b1850b7d..dbdc9a86 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -1,5 +1,4 @@ [ - 'Form' => 'Password' - ] + 'Form' => 'Password', + ], ]); $passwordIdentifier = $this->getMockBuilder(PasswordIdentifier::class) @@ -217,8 +215,13 @@ public function testLoginRehash() $request->expects($this->any()) ->method('getData') ->willReturnCallback(function ($key = null) use ($userPassword, $user) { - if ($key === 'password') return $userPassword; - if ($key === 'username' || $key === 'email') return $user->email; + if ($key === 'password') { + return $userPassword; + } + if ($key === 'username' || $key === 'email') { + return $user->email; + } + return []; }); @@ -253,8 +256,8 @@ public function testLoginRehash() 'component' => 'CakeDC/Users.Login', 'targetAuthenticator' => FormAuthenticator::class, 'PasswordRehash' => [ - 'authenticators' => ['Form' => 'Password'] - ] + 'authenticators' => ['Form' => 'Password'], + ], ]; $Login = $this->getMockBuilder(LoginComponent::class) @@ -269,7 +272,7 @@ public function testLoginRehash() ->method('loadComponent') ->with( $this->equalTo('CakeDC/Users.Login'), - $this->anything() + $this->anything(), ) ->willReturn($Login); @@ -287,8 +290,8 @@ public function testLoginRehashWithAuthenticatorStructure() { \Cake\Core\Configure::write('Auth.PasswordRehash', [ 'authenticators' => [ - 'Form' => 'Authentication.Password' - ] + 'Form' => 'Authentication.Password', + ], ]); $userId = '00000000-0000-0000-0000-000000000002'; @@ -353,8 +356,13 @@ public function testLoginRehashWithAuthenticatorStructure() $request->expects($this->any()) ->method('getData') ->willReturnCallback(function ($key = null) use ($user) { - if ($key === 'password') return 'password123'; - if ($key === 'username' || $key === 'email') return $user->email; + if ($key === 'password') { + return 'password123'; + } + if ($key === 'username' || $key === 'email') { + return $user->email; + } + return []; }); @@ -382,8 +390,8 @@ public function testLoginRehashWithAuthenticatorStructure() 'component' => 'CakeDC/Users.Login', 'targetAuthenticator' => FormAuthenticator::class, 'PasswordRehash' => [ - 'authenticators' => ['Form' => 'Authentication.Password'] - ] + 'authenticators' => ['Form' => 'Authentication.Password'], + ], ]; $Login = $this->getMockBuilder(LoginComponent::class) @@ -399,7 +407,7 @@ public function testLoginRehashWithAuthenticatorStructure() ->method('loadComponent') ->with( $this->equalTo('CakeDC/Users.Login'), - $this->anything() + $this->anything(), ) ->willReturn($Login); @@ -413,7 +421,7 @@ public function testLoginRehashWithAuthenticatorStructure() $this->assertNotEquals( $oldHash, - $userAfter->password + $userAfter->password, ); } From 6cc317b8d9aed5f939ce12b9f47641c617f21cdf Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Tue, 10 Feb 2026 15:22:10 -0400 Subject: [PATCH 4/5] refactor: update password hash in test using updateAll method --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index dbdc9a86..34aa8dca 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -297,8 +297,10 @@ public function testLoginRehashWithAuthenticatorStructure() $userId = '00000000-0000-0000-0000-000000000002'; $user = $this->Trait->getUsersTable()->get($userId); $oldHash = '$2y$10$OldHashNeedsUpgrade00000000000000000000000000000000'; - $user->password = $oldHash; - $this->Trait->getUsersTable()->save($user); + $this->Trait->getUsersTable()->updateAll( + ['password' => $oldHash], + ['id' => $userId] + ); $passwordIdentifier = $this->getMockBuilder(PasswordIdentifier::class) ->onlyMethods(['needsPasswordRehash']) From bdac80e1edd18eebb668bedd6212c9bde67bb77e Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Tue, 10 Feb 2026 15:23:30 -0400 Subject: [PATCH 5/5] phpcs fix --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 34aa8dca..2aac76fe 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -299,7 +299,7 @@ public function testLoginRehashWithAuthenticatorStructure() $oldHash = '$2y$10$OldHashNeedsUpgrade00000000000000000000000000000000'; $this->Trait->getUsersTable()->updateAll( ['password' => $oldHash], - ['id' => $userId] + ['id' => $userId], ); $passwordIdentifier = $this->getMockBuilder(PasswordIdentifier::class)