‪TYPO3CMS  9.5
FrontendUserAuthenticationTest.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Doctrine\DBAL\Statement;
19 use Prophecy\Argument;
20 use Psr\Log\NullLogger;
32 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
33 
39 class ‪FrontendUserAuthenticationTest extends UnitTestCase
40 {
41  private const ‪NOT_CHECKED_INDICATOR = '--not-checked--';
42 
46  protected ‪$resetSingletonInstances = true;
47 
54  {
55  $uniqueSessionId = $this->getUniqueId('test');
56  $_COOKIE['fe_typo_user'] = $uniqueSessionId;
57 
58  // This setup fakes the "getAuthInfoArray() db call
59  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
60  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
61  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
62  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
63  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
64  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
65  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
66  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
67  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
68 
69  // Main session backend setup
70  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
71  $sessionRecord = [
72  'ses_id' => $uniqueSessionId . ‪self::NOT_CHECKED_INDICATOR,
73  'ses_data' => serialize(['foo' => 'bar']),
74  'ses_anonymous' => true,
75  'ses_iplock' => '[DISABLED]',
76  ];
77  $sessionBackendProphecy->get($uniqueSessionId)->shouldBeCalled()->willReturn($sessionRecord);
78  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
79  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
80  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
81 
82  $subject = new ‪FrontendUserAuthentication();
83  $subject->setLogger(new NullLogger());
84  $subject->gc_probability = -1;
85  $subject->start();
86 
87  $this->assertArrayNotHasKey('uid', $subject->user);
88  $this->assertEquals('bar', $subject->getSessionData('foo'));
89  $this->assertEquals($uniqueSessionId, $subject->id);
90  }
91 
96  {
97  // This setup fakes the "getAuthInfoArray() db call
98  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
99  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
100  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
101  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
102  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
103  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
104  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
105  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
106  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
107 
108  // Main session backend setup
109  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
110  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
111  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
112  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
113  // @todo Session handling is not used/evaluated at all in this test
114 
115  // Verify new session id is generated
116  $randomProphecy = $this->prophesize(Random::class);
117  $randomProphecy->generateRandomHexString(32)->shouldBeCalled()->willReturn('newSessionId');
118  GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
119 
120  // set() and update() shouldn't be called since no session cookie is set
121  $sessionBackendProphecy->set(Argument::cetera())->shouldNotBeCalled();
122  $sessionBackendProphecy->update(Argument::cetera())->shouldNotBeCalled();
123 
124  $subject = new ‪FrontendUserAuthentication();
125  $subject->setLogger(new NullLogger());
126  $subject->gc_probability = -1;
127  $subject->start();
128  $subject->storeSessionData();
129  }
130 
137  public function ‪canSetAndUnsetSessionKey()
138  {
139  $uniqueSessionId = $this->getUniqueId('test');
140  $_COOKIE['fe_typo_user'] = $uniqueSessionId;
141 
142  // This setup fakes the "getAuthInfoArray() db call
143  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
144  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
145  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
146  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
147  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
148  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
149  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
150  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
151  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
152 
153  // Main session backend setup
154  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
155  $sessionRecord = [
156  'ses_id' => $uniqueSessionId . ‪self::NOT_CHECKED_INDICATOR,
157  'ses_data' => serialize(['foo' => 'bar']),
158  'ses_anonymous' => true,
159  'ses_iplock' => '[DISABLED]',
160  ];
161  $sessionBackendProphecy->get($uniqueSessionId)->shouldBeCalled()->willReturn($sessionRecord);
162  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
163  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
164  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
165 
166  // set() and update() shouldn't be called since no session cookie is set
167  $sessionBackendProphecy->set(Argument::cetera())->shouldNotBeCalled();
168  $sessionBackendProphecy->update(Argument::cetera())->shouldNotBeCalled();
169  // remove() should be called with given session id
170  $sessionBackendProphecy->remove($uniqueSessionId)->shouldBeCalled();
171 
172  $subject = new FrontendUserAuthentication();
173  $subject->setLogger(new NullLogger());
174  $subject->gc_probability = -1;
175  $subject->start();
176  $subject->setSessionData('foo', 'bar');
177  $subject->removeSessionData();
178  $this->assertAttributeEmpty('sessionData', $subject);
179  }
180 
186  public function ‪canSetSessionDataForAnonymousUser()
187  {
188  $uniqueSessionId = $this->getUniqueId('test');
189  $_COOKIE['fe_typo_user'] = $uniqueSessionId;
190  $currentTime = ‪$GLOBALS['EXEC_TIME'];
191 
192  // This setup fakes the "getAuthInfoArray() db call
193  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
194  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
195  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
196  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
197  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
198  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
199  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
200  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
201  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
202 
203  // Main session backend setup
204  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
205  $sessionBackendProphecy->get($uniqueSessionId)->shouldBeCalled()->willThrow(new SessionNotFoundException('testing', 1486676313));
206  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
207  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
208  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
209 
210  // Verify new session id is generated
211  $randomProphecy = $this->prophesize(Random::class);
212  $randomProphecy->generateRandomHexString(32)->shouldBeCalled()->willReturn('newSessionId');
213  GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
214 
215  // set() and update() shouldn't be called since no session cookie is set
216  $sessionBackendProphecy->update(Argument::cetera())->shouldNotBeCalled();
217  $sessionBackendProphecy->get('newSessionId')->shouldBeCalled()->willThrow(new SessionNotFoundException('testing', 1486676314));
218 
219  // new session should be written
220  $sessionBackendProphecy->set(
221  'newSessionId',
222  [
223  'ses_id' => 'newSessionId',
224  'ses_iplock' => '[DISABLED]',
225  'ses_userid' => 0,
226  'ses_tstamp' => $currentTime,
227  'ses_data' => serialize(['foo' => 'bar']),
228  'ses_permanent' => 0,
229  'ses_anonymous' => 1 // sic!
230  ]
231  )->shouldBeCalled();
232 
233  $subject = new FrontendUserAuthentication();
234  $subject->setLogger(new NullLogger());
235  $subject->gc_probability = -1;
236  $subject->start();
237  $subject->lockIP = 0;
238  $this->assertEmpty($subject->getSessionData($uniqueSessionId));
239  $this->assertEmpty($subject->user);
240  $subject->setSessionData('foo', 'bar');
241  $this->assertAttributeNotEmpty('sessionData', $subject);
242 
243  // Suppress "headers already sent" errors - phpunit does that internally already
244  $prev = error_reporting(0);
245  $subject->storeSessionData();
246  error_reporting($prev);
247  }
248 
255  {
256  $uniqueSessionId = $this->getUniqueId('test');
257  $_COOKIE['fe_typo_user'] = $uniqueSessionId;
258  $currentTime = ‪$GLOBALS['EXEC_TIME'];
259 
260  // This setup fakes the "getAuthInfoArray() db call
261  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
262  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
263  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
264  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
265  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
266  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
267  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
268  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
269  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
270 
271  // Main session backend setup
272  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
273  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
274  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
275  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
276 
277  // a valid session is returned
278  $sessionBackendProphecy->get($uniqueSessionId)->shouldBeCalled()->willReturn(
279  [
280  'ses_id' => $uniqueSessionId . self::NOT_CHECKED_INDICATOR,
281  'ses_userid' => 1,
282  'ses_iplock' => '[DISABLED]',
283  'ses_tstamp' => $currentTime,
284  'ses_data' => serialize(['foo' => 'bar']),
285  'ses_permanent' => 0,
286  'ses_anonymous' => 0 // sic!
287  ]
288  );
289 
290  // Mock call to fe_users table and let it return a valid user row
291  $connectionPoolFeUserProphecy = $this->prophesize(ConnectionPool::class);
292  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolFeUserProphecy->reveal());
293  $queryBuilderFeUserProphecy = $this->prophesize(QueryBuilder::class);
294  $queryBuilderFeUserProphecyRevelation = $queryBuilderFeUserProphecy->reveal();
295  $connectionPoolFeUserProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderFeUserProphecyRevelation);
296  $queryBuilderFeUserProphecy->select('*')->willReturn($queryBuilderFeUserProphecyRevelation);
297  $queryBuilderFeUserProphecy->setRestrictions(Argument::cetera())->shouldBeCalled();
298  $queryBuilderFeUserProphecy->from('fe_users')->shouldBeCalled()->willReturn($queryBuilderFeUserProphecyRevelation);
299  $expressionBuilderFeUserProphecy = $this->prophesize(ExpressionBuilder::class);
300  $queryBuilderFeUserProphecy->expr()->willReturn($expressionBuilderFeUserProphecy->reveal());
301  $queryBuilderFeUserProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
302  $expressionBuilderFeUserProphecy->eq(Argument::cetera())->willReturn('1=1');
303  $queryBuilderFeUserProphecy->where(Argument::cetera())->shouldBeCalled()->willReturn($queryBuilderFeUserProphecyRevelation);
304  $statementFeUserProphecy = $this->prophesize(Statement::class);
305  $queryBuilderFeUserProphecy->execute()->shouldBeCalled()->willReturn($statementFeUserProphecy->reveal());
306  $statementFeUserProphecy->fetch()->willReturn(
307  [
308  'uid' => 1,
309  'username' => 'existingUserName',
310  'password' => 'abc',
311  'deleted' => 0,
312  'disabled' => 0
313  ]
314  );
315 
316  $subject = new FrontendUserAuthentication();
317  $subject->setLogger(new NullLogger());
318  $subject->gc_probability = -1;
319  $subject->start();
320 
321  $this->assertAttributeNotEmpty('user', $subject);
322  $this->assertEquals('existingUserName', $subject->user['username']);
323  }
324 
329  {
330  ‪$GLOBALS['BE_USER'] = [];
331  // This setup fakes the "getAuthInfoArray() db call
332  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
333  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
334  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
335  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
336  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
337  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
338  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
339  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
340  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
341 
342  // Main session backend setup
343  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
344  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
345  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
346  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
347 
348  // no session exists, yet
349  $sessionBackendProphecy->get('newSessionId')->willThrow(new SessionNotFoundException('testing', 1486676358));
350  $sessionBackendProphecy->remove('newSessionId')->shouldBeCalled();
351 
352  // Verify new session id is generated
353  $randomProphecy = $this->prophesize(Random::class);
354  $randomProphecy->generateRandomHexString(32)->shouldBeCalled()->willReturn('newSessionId');
355  GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
356 
357  // Mock the login data and auth services here since fully prophesize this is a lot of hassle
358  $subject = $this->getMockBuilder($this->buildAccessibleProxy(FrontendUserAuthentication::class))
359  ->setMethods([
360  'getLoginFormData',
361  'getAuthServices',
362  'createUserSession',
363  'getCookie',
364  ])
365  ->getMock();
366  $subject->setLogger(new NullLogger());
367  $subject->gc_probability = -1;
368 
369  // Mock a login attempt
370  $subject->method('getLoginFormData')->willReturn([
371  'status' => 'login',
372  'uname' => 'existingUserName',
373  'uident' => 'abc'
374  ]);
375 
376  $authServiceMock = $this->getMockBuilder(AuthenticationService::class)->getMock();
377  $authServiceMock->method('getUser')->willReturn([
378  'uid' => 1,
379  'username' => 'existingUserName'
380  ]);
381  // Auth services can return true or 200
382  $authServiceMock->method('authUser')->willReturn(true);
383  // We need to wrap the array to something thats is \Traversable, in PHP 7.1 we can use traversable pseudo type instead
384  $subject->method('getAuthServices')->willReturn(new \ArrayIterator([$authServiceMock]));
385 
386  $subject->method('createUserSession')->willReturn([
387  'ses_id' => 'newSessionId'
388  ]);
389 
390  $subject->method('getCookie')->willReturn(null);
391 
392  $subject->start();
393  $this->assertFalse($subject->_get('loginFailure'));
394  $this->assertEquals('existingUserName', $subject->user['username']);
395  }
396 
403  {
404  $this->markTestSkipped('Test is flaky, convert to a functional test');
405  // Mock SessionBackend
406  $sessionBackend = $this->getMockBuilder(SessionBackendInterface::class)->getMock();
407 
408  $oldSessionRecord = [
409  'ses_id' => 'oldSessionId',
410  'ses_data' => serialize(['foo' => 'bar']),
411  'ses_anonymous' => 1,
412  'ses_iplock' => 0,
413  ];
414 
415  // Return old, non authenticated session
416  $sessionBackend->method('get')->willReturn($oldSessionRecord);
417 
418  $expectedSessionRecord = array_merge(
419  $oldSessionRecord,
420  [
421  //ses_id is overwritten by the session backend
422  'ses_anonymous' => 0
423  ]
424  );
425 
426  $expectedUserId = 1;
427 
428  $sessionBackend->expects($this->once())->method('set')->with(
429  'newSessionId',
430  $this->equalTo($expectedSessionRecord)
431  )->willReturnArgument(1);
432 
433  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
434  // Load old sessions
435  $this->subject->method('getCookie')->willReturn('oldSessionId');
436  $this->subject->method('createSessionId')->willReturn('newSessionId');
437 
438  // Mock a login attempt
439  $this->subject->method('getLoginFormData')->willReturn([
440  'status' => 'login',
441  'uname' => 'existingUserName',
442  'uident' => 'abc'
443  ]);
444 
445  $authServiceMock = $this->getMockBuilder(AuthenticationService::class)->getMock();
446  $authServiceMock->method('getUser')->willReturn([
447  'uid' => 1,
448  'username' => 'existingUserName'
449  ]);
450 
451  $authServiceMock->method('authUser')->willReturn(true); // Auth services can return true or 200
452 
453  // We need to wrap the array to something thats is \Traversable, in PHP 7.1 we can use traversable pseudo type instead
454  $this->subject->method('getAuthServices')->willReturn(new \ArrayIterator([$authServiceMock]));
455 
456  // Should call regenerateSessionId
457  // New session should be stored with with old values
458  $this->subject->start();
459 
460  $this->assertEquals('newSessionId', $this->subject->id);
461  $this->assertEquals($expectedUserId, $this->subject->user['uid']);
462  $this->subject->setSessionData('foobar', 'baz');
463  $this->assertArraySubset(['foo' => 'bar'], $this->subject->_get('sessionData'));
464  $this->assertTrue($this->subject->sesData_change);
465  }
466 
472  public function ‪canRemoveSessionData()
473  {
474  $this->markTestSkipped('Test is flaky, convert to a functional test');
475  // Mock SessionBackend
476  $sessionBackend = $this->getMockBuilder(SessionBackendInterface::class)->getMock();
477  $sessionBackend->method('get')->willReturn(
478  [
479  'ses_id' => 'existingId',
480  'ses_userid' => 1, // fe_user with uid 0 assumed in database, see fixtures.xml
481  'ses_data' => serialize(['foo' => 'bar']),
482  'ses_iplock' => 0,
483  'ses_tstamp' => time() + 100 // Return a time in future to make avoid mocking $GLOBALS['EXEC_TIME']
484  ]
485  );
486  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
487  $this->subject->method('getCookie')->willReturn('existingId');
488 
489  $this->subject->start();
490 
491  $this->subject->removeSessionData();
492  $this->assertEmpty($this->subject->getSessionData('foo'));
493  $this->subject->storeSessionData();
494  $this->assertEmpty($this->subject->getSessionData('foo'));
495  }
496 
503  {
504  $this->markTestSkipped('Test is flaky, convert to a functional test');
505  $sessionBackend = $this->getMockBuilder(SessionBackendInterface::class)->getMock();
506  // Mock SessionBackend
507  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
508 
509  $this->subject->method('createSessionId')->willReturn('newSessionId');
510 
511  $expectedSessionRecord = [
512  'ses_anonymous' => 1,
513  'ses_data' => serialize(['foo' => 'bar'])
514  ];
515 
516  $sessionBackend->expects($this->at(0))->method('get')->willThrowException(new SessionNotFoundException('testing', 1486045419));
517  $sessionBackend->expects($this->at(1))->method('get')->willThrowException(new SessionNotFoundException('testing', 1486045420));
518  $sessionBackend->expects($this->at(2))->method('get')->willReturn(
519  [
520  'ses_id' => 'newSessionId',
521  'ses_anonymous' => 1
522  ]
523  );
524 
525  $sessionBackend->expects($this->once())
526  ->method('set')
527  ->with('newSessionId', new \PHPUnit_Framework_Constraint_ArraySubset($expectedSessionRecord))
528  ->willReturn([
529  'ses_id' => 'newSessionId',
530  'ses_anonymous' => 1,
531  'ses_data' => serialize(['foo' => 'bar']),
532  ]);
533 
534  // Can set and store session data
535  $this->subject->start();
536  $this->assertEmpty($this->subject->_get('sessionData'));
537  $this->assertEmpty($this->subject->user);
538  $this->subject->setSessionData('foo', 'bar');
539  $this->assertAttributeNotEmpty('sessionData', $this->subject);
540  $this->subject->storeSessionData();
541 
542  // Should delete session after setting to null
543  $this->subject->setSessionData('foo', null);
544  $this->assertAttributeEmpty('sessionData', $this->subject);
545  $sessionBackend->expects($this->once())->method('remove')->with('newSessionId');
546  $sessionBackend->expects($this->never())->method('update');
547 
548  $this->subject->storeSessionData();
549  }
550 
556  {
557  $this->markTestSkipped('Test is flaky, convert to a functional test');
558  $sessionBackend = $this->getMockBuilder(SessionBackendInterface::class)->getMock();
559  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
560  $this->subject->method('createSessionId')->willReturn('newSessionId');
561 
562  $sessionBackend->method('get')->willReturn(
563  [
564  'ses_id' => 'existingId',
565  'ses_userid' => 1,
566  'ses_data' => serialize(['foo' => 'bar']),
567  'ses_iplock' => 0,
568  'ses_tstamp' => time() + 100 // Return a time in future to make avoid mocking $GLOBALS['EXEC_TIME']
569  ]
570  );
571  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
572  $this->subject->method('getCookie')->willReturn('existingId');
573 
574  $this->subject->method('getRawUserByUid')->willReturn([
575  'uid' => 1,
576  ]);
577 
578  // fix logout data
579  // Mock a logout attempt
580  $this->subject->method('getLoginFormData')->willReturn([
581  'status' => 'logout',
582 
583  ]);
584 
585  $sessionBackend->expects($this->once())->method('set')->with('newSessionId', $this->anything())->willReturnArgument(1);
586  $sessionBackend->expects($this->once())->method('remove')->with('existingId');
587 
588  // start
589  $this->subject->start();
590  // asset that session data is there
591  $this->assertNotEmpty($this->subject->user);
592  $this->assertEquals(1, (int)$this->subject->user['ses_anonymous']);
593  $this->assertEquals(['foo' => 'bar'], $this->subject->_get('sessionData'));
594 
595  $this->assertEquals('newSessionId', $this->subject->id);
596  }
597 }
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:33
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\canSetAndUnsetSessionKey
‪canSetAndUnsetSessionKey()
Definition: FrontendUserAuthenticationTest.php:136
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\sessionDataShouldBePreservedOnLogout
‪sessionDataShouldBePreservedOnLogout()
Definition: FrontendUserAuthenticationTest.php:554
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication
Definition: FrontendUserAuthenticationTest.php:3
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\NOT_CHECKED_INDICATOR
‪const NOT_CHECKED_INDICATOR
Definition: FrontendUserAuthenticationTest.php:41
‪TYPO3\CMS\Core\Session\SessionManager
Definition: SessionManager.php:37
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\destroysAnonymousSessionIfDataIsNull
‪destroysAnonymousSessionIfDataIsNull()
Definition: FrontendUserAuthenticationTest.php:501
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\storeSessionDataOnAnonymousUserWithNoData
‪storeSessionDataOnAnonymousUserWithNoData()
Definition: FrontendUserAuthenticationTest.php:94
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\canRemoveSessionData
‪canRemoveSessionData()
Definition: FrontendUserAuthenticationTest.php:471
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression
Definition: CompositeExpression.php:23
‪TYPO3\CMS\Core\Session\Backend\SessionBackendInterface
Definition: SessionBackendInterface.php:26
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\canPreserveSessionDataWhenAuthenticating
‪canPreserveSessionDataWhenAuthenticating()
Definition: FrontendUserAuthenticationTest.php:401
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\userFieldIsNotSetForAnonymousSessions
‪userFieldIsNotSetForAnonymousSessions()
Definition: FrontendUserAuthenticationTest.php:52
‪TYPO3\CMS\Core\Authentication\AuthenticationService
Definition: AuthenticationService.php:30
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\canSetSessionDataForAnonymousUser
‪canSetSessionDataForAnonymousUser()
Definition: FrontendUserAuthenticationTest.php:185
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\canLogUserInWithoutAnonymousSession
‪canLogUserInWithoutAnonymousSession()
Definition: FrontendUserAuthenticationTest.php:327
‪TYPO3\CMS\Core\Crypto\Random
Definition: Random.php:22
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication
Definition: FrontendUserAuthentication.php:28
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\$resetSingletonInstances
‪bool $resetSingletonInstances
Definition: FrontendUserAuthenticationTest.php:45
‪TYPO3\CMS\Core\Session\Backend\Exception\SessionNotFoundException
Definition: SessionNotFoundException.php:22
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest
Definition: FrontendUserAuthenticationTest.php:40
‪TYPO3\CMS\Frontend\Tests\Unit\Authentication\FrontendUserAuthenticationTest\canLoadExistingAuthenticatedSession
‪canLoadExistingAuthenticatedSession()
Definition: FrontendUserAuthenticationTest.php:253