1313
1414namespace CakeDC \Users \Test \TestCase \Controller \Traits ;
1515
16+ use Authentication \Authenticator \AuthenticatorCollection ;
1617use Authentication \Authenticator \Result ;
1718use Authentication \Authenticator \SessionAuthenticator ;
1819use Authentication \Identifier \IdentifierCollection ;
2223use Cake \Event \Event ;
2324use Cake \Http \Response ;
2425use Cake \Http \ServerRequest ;
26+ use CakeDC \Auth \Authentication \AuthenticationService ;
2527use CakeDC \Auth \Authentication \Failure ;
2628use CakeDC \Auth \Authenticator \FormAuthenticator ;
2729use CakeDC \Users \Authenticator \SocialAuthenticator ;
@@ -48,9 +50,9 @@ public function setUp(): void
4850 ->getMock ();
4951
5052 // $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent')
51- // ->onlyMethods(['setConfig'])
52- // ->disableOriginalConstructor()
53- // ->getMock();
53+ // ->onlyMethods(['setConfig'])
54+ // ->disableOriginalConstructor()
55+ // ->getMock();
5456 }
5557
5658 /**
@@ -147,76 +149,282 @@ public function testLoginHappy()
147149 */
148150 public function testLoginRehash ()
149151 {
152+ \Cake \Core \Configure::write ('Auth.PasswordRehash ' , [
153+ 'authenticators ' => [
154+ 'Form ' => 'Password ' ,
155+ ],
156+ ]);
157+
150158 $ passwordIdentifier = $ this ->getMockBuilder (PasswordIdentifier::class)
151159 ->onlyMethods (['needsPasswordRehash ' ])
152160 ->getMock ();
153161 $ passwordIdentifier ->expects ($ this ->any ())
154162 ->method ('needsPasswordRehash ' )
155163 ->willReturn (true );
156- $ identifiers = new IdentifierCollection ([]);
157- $ identifiers ->set ('Password ' , $ passwordIdentifier );
158164
159- $ SessionAuth = new SessionAuthenticator ($ identifiers );
165+ $ identifierCollection = new IdentifierCollection ([]);
166+ $ identifierCollection ->set ('Password ' , $ passwordIdentifier );
160167
161- $ sessionFailure = new Failure (
162- $ SessionAuth ,
163- new Result (null , Result::FAILURE_IDENTITY_NOT_FOUND ),
164- );
165- $ failures = [$ sessionFailure ];
168+ $ formAuthenticator = $ this ->getMockBuilder (FormAuthenticator::class)
169+ ->disableOriginalConstructor ()
170+ ->addMethods (['getIdentifier ' ])
171+ ->getMock ();
172+ $ formAuthenticator ->expects ($ this ->any ())
173+ ->method ('getIdentifier ' )
174+ ->willReturn ($ identifierCollection );
175+
176+ $ authenticatorCollection = $ this ->getMockBuilder (AuthenticatorCollection::class)
177+ ->disableOriginalConstructor ()
178+ ->getMock ();
179+ $ authenticatorCollection ->expects ($ this ->any ())
180+ ->method ('has ' )->with ('Form ' )->willReturn (true );
181+ $ authenticatorCollection ->expects ($ this ->any ())
182+ ->method ('get ' )->with ('Form ' )->willReturn ($ formAuthenticator );
166183
184+ $ user = $ this ->Trait ->getUsersTable ()->get ('00000000-0000-0000-0000-000000000002 ' );
185+ $ passwordBefore = $ user ['password ' ];
167186 $ userPassword = 'testLoginRehash ' . time ();
187+
188+ $ service = $ this ->getMockBuilder (AuthenticationService::class)
189+ ->disableOriginalConstructor ()
190+ ->getMock ();
191+ $ service ->expects ($ this ->any ())
192+ ->method ('authenticators ' )
193+ ->willReturn ($ authenticatorCollection );
194+ $ service ->expects ($ this ->any ())
195+ ->method ('identifiers ' )
196+ ->willReturn (new IdentifierCollection ([]));
197+ $ service ->expects ($ this ->any ())
198+ ->method ('getAuthenticationProvider ' )
199+ ->willReturn ($ formAuthenticator );
200+
201+ $ result = new Result ($ user , Result::SUCCESS );
202+ $ service ->expects ($ this ->any ())->method ('getResult ' )->willReturn ($ result );
203+
168204 $ this ->_mockDispatchEvent (new Event ('event ' ));
169- $ this ->_mockRequestPost ();
170- $ this ->Trait ->getRequest ()->expects ($ this ->any ())
205+
206+ $ request = $ this ->getMockBuilder ('Cake\Http\ServerRequest ' )
207+ ->onlyMethods (['is ' , 'getData ' ])
208+ ->getMock ();
209+
210+ $ request ->expects ($ this ->any ())
211+ ->method ('is ' )
212+ ->with ('post ' )
213+ ->willReturn (true );
214+
215+ $ request ->expects ($ this ->any ())
171216 ->method ('getData ' )
172- ->with ($ this ->equalTo ('password ' ))
173- ->willReturn ($ userPassword );
217+ ->willReturnCallback (function ($ key = null ) use ($ userPassword , $ user ) {
218+ if ($ key === 'password ' ) {
219+ return $ userPassword ;
220+ }
221+ if ($ key === 'username ' || $ key === 'email ' ) {
222+ return $ user ->email ;
223+ }
224+
225+ return [];
226+ });
227+
228+ $ identityWrapper = new \Authentication \Identity ($ user );
229+ $ request = $ request ->withAttribute ('authentication ' , $ service );
230+ $ request = $ request ->withAttribute ('identity ' , $ identityWrapper );
231+
232+ $ this ->Trait ->setRequest ($ request );
233+
234+ $ authComponent = $ this ->getMockBuilder (\Cake \Controller \Component::class)
235+ ->disableOriginalConstructor ()
236+ ->onlyMethods (['getConfig ' ])
237+ ->getMock ();
238+ $ authComponent ->expects ($ this ->any ())
239+ ->method ('getConfig ' )
240+ ->with ('loginRedirect ' )
241+ ->willReturn ('/home ' );
242+
243+ $ this ->Trait ->components ()->set ('Authentication ' , $ authComponent );
174244
175245 $ this ->_mockFlash ();
176- $ user = $ this ->Trait ->getUsersTable ()->get ('00000000-0000-0000-0000-000000000002 ' );
177- $ passwordBefore = $ user ['password ' ];
178- $ this ->assertNotEmpty ($ passwordBefore );
179- $ this ->_mockAuthentication ($ user ->toArray (), $ failures , $ identifiers );
180246 $ this ->Trait ->Flash ->expects ($ this ->never ())
181247 ->method ('error ' );
248+
182249 $ this ->Trait ->expects ($ this ->once ())
183250 ->method ('redirect ' )
184251 ->with ($ this ->successLoginRedirect )
185- ->will ( $ this -> returnValue ( new Response () ));
252+ ->willReturn ( new Response ());
186253
187254 $ registry = new ComponentRegistry (new \Cake \Controller \Controller (new \Cake \Http \ServerRequest ()));
188255 $ config = [
189256 'component ' => 'CakeDC/Users.Login ' ,
190- 'defaultMessage ' => __d ('cake_d_c/users ' , 'Username or password is incorrect ' ),
191- 'messages ' => [
192- FormAuthenticator::FAILURE_INVALID_RECAPTCHA => __d ('cake_d_c/users ' , 'Invalid reCaptcha ' ),
193- ],
194257 'targetAuthenticator ' => FormAuthenticator::class,
258+ 'PasswordRehash ' => [
259+ 'authenticators ' => ['Form ' => 'Password ' ],
260+ ],
195261 ];
262+
196263 $ Login = $ this ->getMockBuilder (LoginComponent::class)
197264 ->onlyMethods (['getController ' ])
198265 ->setConstructorArgs ([$ registry , $ config ])
199266 ->getMock ();
200267
201268 $ Login ->expects ($ this ->any ())
202269 ->method ('getController ' )
203- ->will ($ this ->returnValue ( $ this -> Trait ) );
270+ ->willReturn ($ this ->Trait );
204271 $ this ->Trait ->expects ($ this ->any ())
205272 ->method ('loadComponent ' )
206273 ->with (
207274 $ this ->equalTo ('CakeDC/Users.Login ' ),
208- $ this ->equalTo ( $ config ),
275+ $ this ->anything ( ),
209276 )
210- ->will ( $ this -> returnValue ( $ Login) );
277+ ->willReturn ( $ Login );
211278
212279 $ result = $ this ->Trait ->login ();
213280 $ this ->assertInstanceOf (Response::class, $ result );
281+
214282 $ userAfter = $ this ->Trait ->getUsersTable ()->get ('00000000-0000-0000-0000-000000000002 ' );
215- $ passwordAfter = $ userAfter ['password ' ];
216- $ this -> assertNotEquals ( $ passwordBefore , $ passwordAfter );
283+ $ this -> assertNotEquals ( $ passwordBefore , $ userAfter ['password ' ]) ;
284+
217285 $ passwordHasher = new DefaultPasswordHasher ();
218- $ check = $ passwordHasher ->check ($ userPassword , $ passwordAfter );
219- $ this ->assertTrue ($ check );
286+ $ this ->assertTrue ($ passwordHasher ->check ($ userPassword , $ userAfter ['password ' ]));
287+ }
288+
289+ public function testLoginRehashWithAuthenticatorStructure ()
290+ {
291+ \Cake \Core \Configure::write ('Auth.PasswordRehash ' , [
292+ 'authenticators ' => [
293+ 'Form ' => 'Authentication.Password ' ,
294+ ],
295+ ]);
296+
297+ $ userId = '00000000-0000-0000-0000-000000000002 ' ;
298+ $ user = $ this ->Trait ->getUsersTable ()->get ($ userId );
299+ $ oldHash = '$2y$10$OldHashNeedsUpgrade00000000000000000000000000000000 ' ;
300+ $ this ->Trait ->getUsersTable ()->updateAll (
301+ ['password ' => $ oldHash ],
302+ ['id ' => $ userId ],
303+ );
304+
305+ $ passwordIdentifier = $ this ->getMockBuilder (PasswordIdentifier::class)
306+ ->onlyMethods (['needsPasswordRehash ' ])
307+ ->getMock ();
308+ $ passwordIdentifier ->expects ($ this ->any ())
309+ ->method ('needsPasswordRehash ' )
310+ ->willReturn (true );
311+
312+ $ identifierCollection = new IdentifierCollection ([]);
313+ $ identifierCollection ->set ('Authentication.Password ' , $ passwordIdentifier );
314+
315+ $ formAuthenticator = $ this ->getMockBuilder (FormAuthenticator::class)
316+ ->disableOriginalConstructor ()
317+ ->addMethods (['getIdentifier ' ])
318+ ->getMock ();
319+ $ formAuthenticator ->expects ($ this ->any ())
320+ ->method ('getIdentifier ' )
321+ ->willReturn ($ identifierCollection );
322+
323+ $ authenticatorCollection = $ this ->getMockBuilder (AuthenticatorCollection::class)
324+ ->disableOriginalConstructor ()
325+ ->getMock ();
326+ $ authenticatorCollection ->expects ($ this ->any ())
327+ ->method ('has ' )->with ('Form ' )->willReturn (true );
328+ $ authenticatorCollection ->expects ($ this ->any ())
329+ ->method ('get ' )->with ('Form ' )->willReturn ($ formAuthenticator );
330+
331+ $ service = $ this ->getMockBuilder (AuthenticationService::class)
332+ ->disableOriginalConstructor ()
333+ ->getMock ();
334+ $ service ->expects ($ this ->any ())
335+ ->method ('authenticators ' )
336+ ->willReturn ($ authenticatorCollection );
337+ $ service ->expects ($ this ->any ())
338+ ->method ('identifiers ' )
339+ ->willReturn (new IdentifierCollection ([]));
340+ $ service ->expects ($ this ->any ())
341+ ->method ('getAuthenticationProvider ' )
342+ ->willReturn ($ formAuthenticator );
343+
344+ $ result = new Result ($ user , Result::SUCCESS );
345+ $ service ->expects ($ this ->any ())->method ('getResult ' )->willReturn ($ result );
346+
347+ $ this ->_mockDispatchEvent (new Event ('event ' ));
348+
349+ $ request = $ this ->getMockBuilder ('Cake\Http\ServerRequest ' )
350+ ->onlyMethods (['is ' , 'getData ' ])
351+ ->getMock ();
352+
353+ $ request ->expects ($ this ->any ())
354+ ->method ('is ' )
355+ ->with ('post ' )
356+ ->willReturn (true );
357+
358+ $ request ->expects ($ this ->any ())
359+ ->method ('getData ' )
360+ ->willReturnCallback (function ($ key = null ) use ($ user ) {
361+ if ($ key === 'password ' ) {
362+ return 'password123 ' ;
363+ }
364+ if ($ key === 'username ' || $ key === 'email ' ) {
365+ return $ user ->email ;
366+ }
367+
368+ return [];
369+ });
370+
371+ $ identityWrapper = new \Authentication \Identity ($ user );
372+
373+ $ request = $ request ->withAttribute ('authentication ' , $ service );
374+ $ request = $ request ->withAttribute ('identity ' , $ identityWrapper );
375+
376+ $ this ->Trait ->setRequest ($ request );
377+
378+ $ authComponent = $ this ->getMockBuilder (\Cake \Controller \Component::class)
379+ ->disableOriginalConstructor ()
380+ ->onlyMethods (['getConfig ' ])
381+ ->getMock ();
382+
383+ $ authComponent ->expects ($ this ->any ())
384+ ->method ('getConfig ' )
385+ ->with ('loginRedirect ' )
386+ ->willReturn ('/ ' );
387+
388+ $ this ->Trait ->components ()->set ('Authentication ' , $ authComponent );
389+
390+ $ registry = new ComponentRegistry (new \Cake \Controller \Controller (new \Cake \Http \ServerRequest ()));
391+ $ config = [
392+ 'component ' => 'CakeDC/Users.Login ' ,
393+ 'targetAuthenticator ' => FormAuthenticator::class,
394+ 'PasswordRehash ' => [
395+ 'authenticators ' => ['Form ' => 'Authentication.Password ' ],
396+ ],
397+ ];
398+
399+ $ Login = $ this ->getMockBuilder (LoginComponent::class)
400+ ->onlyMethods (['getController ' ])
401+ ->setConstructorArgs ([$ registry , $ config ])
402+ ->getMock ();
403+
404+ $ Login ->expects ($ this ->any ())
405+ ->method ('getController ' )
406+ ->willReturn ($ this ->Trait );
407+
408+ $ this ->Trait ->expects ($ this ->any ())
409+ ->method ('loadComponent ' )
410+ ->with (
411+ $ this ->equalTo ('CakeDC/Users.Login ' ),
412+ $ this ->anything (),
413+ )
414+ ->willReturn ($ Login );
415+
416+ $ this ->Trait ->expects ($ this ->once ())
417+ ->method ('redirect ' )
418+ ->willReturn (new Response ());
419+
420+ $ this ->Trait ->login ();
421+
422+ $ userAfter = $ this ->Trait ->getUsersTable ()->get ($ userId );
423+
424+ $ this ->assertNotEquals (
425+ $ oldHash ,
426+ $ userAfter ->password ,
427+ );
220428 }
221429
222430 /**
@@ -267,8 +475,8 @@ public function testLoginGet()
267475 ->method ('getController ' )
268476 ->will ($ this ->returnValue ($ this ->Trait ));
269477 // $this->Trait->expects($this->any())
270- // ->method('getRequest')
271- // ->will($this->returnValue($request));
478+ // ->method('getRequest')
479+ // ->will($this->returnValue($request));
272480 $ this ->Trait ->expects ($ this ->any ())
273481 ->method ('loadComponent ' )
274482 ->with (
0 commit comments