TYPO3 CMS  TYPO3_8-7
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 
32 
38 class FrontendUserAuthenticationTest extends UnitTestCase
39 {
43  protected $singletonInstances = [];
44 
48  protected function setUp()
49  {
50  $this->singletonInstances = GeneralUtility::getSingletonInstances();
51  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['writeDevLog'] = false;
52  }
53 
57  protected function tearDown()
58  {
60  GeneralUtility::resetSingletonInstances($this->singletonInstances);
61  parent::tearDown();
62  }
63 
70  {
71  $uniqueSessionId = $this->getUniqueId('test');
72  $_COOKIE['fe_typo_user'] = $uniqueSessionId;
73 
74  // This setup fakes the "getAuthInfoArray() db call
75  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
76  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
77  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
78  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
79  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
80  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
81  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
82  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
83  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
84 
85  // Main session backend setup
86  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
87  $sessionRecord = [
88  'ses_id' => $uniqueSessionId,
89  'ses_data' => serialize(['foo' => 'bar']),
90  'ses_anonymous' => true,
91  'ses_iplock' => '[DISABLED]',
92  ];
93  $sessionBackendProphecy->get($uniqueSessionId)->shouldBeCalled()->willReturn($sessionRecord);
94  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
95  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
96  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
97 
98  $subject = new FrontendUserAuthentication();
99  $subject->gc_probability = -1;
100  $subject->start();
101 
102  $this->assertArrayNotHasKey('uid', $subject->user);
103  $this->assertEquals('bar', $subject->getSessionData('foo'));
104  $this->assertEquals($uniqueSessionId, $subject->id);
105  }
106 
111  {
112  // This setup fakes the "getAuthInfoArray() db call
113  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
114  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
115  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
116  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
117  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
118  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
119  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
120  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
121  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
122 
123  // Main session backend setup
124  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
125  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
126  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
127  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
128 
129  // Verify new session id is generated
130  $randomProphecy = $this->prophesize(Random::class);
131  $randomProphecy->generateRandomHexString(32)->shouldBeCalled()->willReturn('newSessionId');
132  GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
133 
134  // set() and update() shouldn't be called since no session cookie is set
135  $sessionBackendProphecy->set(Argument::cetera())->shouldNotBeCalled();
136  $sessionBackendProphecy->update(Argument::cetera())->shouldNotBeCalled();
137 
138  $subject = new FrontendUserAuthentication();
139  $subject->gc_probability = -1;
140  $subject->start();
141  $subject->storeSessionData();
142  }
143 
150  public function canSetAndUnsetSessionKey()
151  {
152  $uniqueSessionId = $this->getUniqueId('test');
153  $_COOKIE['fe_typo_user'] = $uniqueSessionId;
154 
155  // This setup fakes the "getAuthInfoArray() db call
156  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
157  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
158  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
159  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
160  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
161  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
162  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
163  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
164  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
165 
166  // Main session backend setup
167  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
168  $sessionRecord = [
169  'ses_id' => $uniqueSessionId,
170  'ses_data' => serialize(['foo' => 'bar']),
171  'ses_anonymous' => true,
172  'ses_iplock' => '[DISABLED]',
173  ];
174  $sessionBackendProphecy->get($uniqueSessionId)->shouldBeCalled()->willReturn($sessionRecord);
175  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
176  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
177  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
178 
179  // set() and update() shouldn't be called since no session cookie is set
180  $sessionBackendProphecy->set(Argument::cetera())->shouldNotBeCalled();
181  $sessionBackendProphecy->update(Argument::cetera())->shouldNotBeCalled();
182  // remove() should be called with given session id
183  $sessionBackendProphecy->remove($uniqueSessionId)->shouldBeCalled();
184 
185  $subject = new FrontendUserAuthentication();
186  $subject->gc_probability = -1;
187  $subject->start();
188  $subject->setSessionData('foo', 'bar');
189  $subject->removeSessionData();
190  $this->assertAttributeEmpty('sessionData', $subject);
191  }
192 
199  {
200  $uniqueSessionId = $this->getUniqueId('test');
201  $_COOKIE['fe_typo_user'] = $uniqueSessionId;
202  $currentTime = $GLOBALS['EXEC_TIME'];
203 
204  // This setup fakes the "getAuthInfoArray() db call
205  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
206  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
207  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
208  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
209  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
210  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
211  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
212  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
213  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
214 
215  // Main session backend setup
216  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
217  $sessionBackendProphecy->get($uniqueSessionId)->shouldBeCalled()->willThrow(new SessionNotFoundException('testing', 1486676313));
218  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
219  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
220  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
221 
222  // Verify new session id is generated
223  $randomProphecy = $this->prophesize(Random::class);
224  $randomProphecy->generateRandomHexString(32)->shouldBeCalled()->willReturn('newSessionId');
225  GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
226 
227  // set() and update() shouldn't be called since no session cookie is set
228  $sessionBackendProphecy->update(Argument::cetera())->shouldNotBeCalled();
229  $sessionBackendProphecy->get('newSessionId')->shouldBeCalled()->willThrow(new SessionNotFoundException('testing', 1486676314));
230 
231  // new session should be written
232  $sessionBackendProphecy->set(
233  'newSessionId',
234  [
235  'ses_id' => 'newSessionId',
236  'ses_iplock' => '',
237  'ses_userid' => 0,
238  'ses_tstamp' => $currentTime,
239  'ses_data' => serialize(['foo' => 'bar']),
240  'ses_permanent' => 0,
241  'ses_anonymous' => 1 // sic!
242  ]
243  )->shouldBeCalled();
244 
245  $subject = new FrontendUserAuthentication();
246  $subject->gc_probability = -1;
247  $subject->start();
248  $this->assertEmpty($subject->getSessionData($uniqueSessionId));
249  $this->assertEmpty($subject->user);
250  $subject->setSessionData('foo', 'bar');
251  $this->assertAttributeNotEmpty('sessionData', $subject);
252 
253  // Suppress "headers already sent" errors - phpunit does that internally already
254  $prev = error_reporting(0);
255  $subject->storeSessionData();
256  error_reporting($prev);
257  }
258 
265  {
266  $uniqueSessionId = $this->getUniqueId('test');
267  $_COOKIE['fe_typo_user'] = $uniqueSessionId;
268  $currentTime = $GLOBALS['EXEC_TIME'];
269 
270  // This setup fakes the "getAuthInfoArray() db call
271  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
272  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
273  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
274  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
275  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
276  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
277  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
278  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
279  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
280 
281  // Main session backend setup
282  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
283  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
284  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
285  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
286 
287  // a valid session is returned
288  $sessionBackendProphecy->get($uniqueSessionId)->shouldBeCalled()->willReturn(
289  [
290  'ses_id' => $uniqueSessionId,
291  'ses_userid' => 1,
292  'ses_iplock' => '[DISABLED]',
293  'ses_tstamp' => $currentTime,
294  'ses_data' => serialize(['foo' => 'bar']),
295  'ses_permanent' => 0,
296  'ses_anonymous' => 0 // sic!
297  ]
298  );
299 
300  // Mock call to fe_users table and let it return a valid user row
301  $connectionPoolFeUserProphecy = $this->prophesize(ConnectionPool::class);
302  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolFeUserProphecy->reveal());
303  $queryBuilderFeUserProphecy = $this->prophesize(QueryBuilder::class);
304  $queryBuilderFeUserProphecyRevelation = $queryBuilderFeUserProphecy->reveal();
305  $connectionPoolFeUserProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderFeUserProphecyRevelation);
306  $queryBuilderFeUserProphecy->select('*')->willReturn($queryBuilderFeUserProphecyRevelation);
307  $queryBuilderFeUserProphecy->setRestrictions(Argument::cetera())->shouldBeCalled();
308  $queryBuilderFeUserProphecy->from('fe_users')->shouldBeCalled()->willReturn($queryBuilderFeUserProphecyRevelation);
309  $expressionBuilderFeUserProphecy = $this->prophesize(ExpressionBuilder::class);
310  $queryBuilderFeUserProphecy->expr()->willReturn($expressionBuilderFeUserProphecy->reveal());
311  $queryBuilderFeUserProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
312  $expressionBuilderFeUserProphecy->eq(Argument::cetera())->willReturn('1=1');
313  $queryBuilderFeUserProphecy->where(Argument::cetera())->shouldBeCalled()->willReturn($queryBuilderFeUserProphecyRevelation);
314  $statementFeUserProphecy = $this->prophesize(Statement::class);
315  $queryBuilderFeUserProphecy->execute()->shouldBeCalled()->willReturn($statementFeUserProphecy->reveal());
316  $statementFeUserProphecy->fetch()->willReturn(
317  [
318  'uid' => 1,
319  'username' => 'existingUserName',
320  'password' => 'abc',
321  'deleted' => 0,
322  'disabled' => 0
323  ]
324  );
325 
326  $subject = new FrontendUserAuthentication();
327  $subject->gc_probability = -1;
328  $subject->start();
329 
330  $this->assertAttributeNotEmpty('user', $subject);
331  $this->assertEquals('existingUserName', $subject->user['username']);
332  }
333 
338  {
339  // This setup fakes the "getAuthInfoArray() db call
340  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
341  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
342  $connectionPoolProphecy->getQueryBuilderForTable('fe_users')->willReturn($queryBuilderProphecy->reveal());
343  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
344  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
345  $queryBuilderProphecy->expr()->willReturn($expressionBuilderProphecy->reveal());
346  $compositeExpressionProphecy = $this->prophesize(CompositeExpression::class);
347  $expressionBuilderProphecy->andX(Argument::cetera())->willReturn($compositeExpressionProphecy->reveal());
348  $expressionBuilderProphecy->in(Argument::cetera())->willReturn('');
349 
350  // Main session backend setup
351  $sessionBackendProphecy = $this->prophesize(SessionBackendInterface::class);
352  $sessionManagerProphecy = $this->prophesize(SessionManager::class);
353  GeneralUtility::setSingletonInstance(SessionManager::class, $sessionManagerProphecy->reveal());
354  $sessionManagerProphecy->getSessionBackend('FE')->willReturn($sessionBackendProphecy->reveal());
355 
356  // no session exists, yet
357  $sessionBackendProphecy->get('newSessionId')->willThrow(new SessionNotFoundException('testing', 1486676358));
358  $sessionBackendProphecy->remove('newSessionId')->shouldBeCalled();
359 
360  // Verify new session id is generated
361  $randomProphecy = $this->prophesize(Random::class);
362  $randomProphecy->generateRandomHexString(32)->shouldBeCalled()->willReturn('newSessionId');
363  GeneralUtility::addInstance(Random::class, $randomProphecy->reveal());
364 
365  // Mock the login data and auth services here since fully prophesize this is a lot of hassle
366  $subject = $this->getMockBuilder($this->buildAccessibleProxy(FrontendUserAuthentication::class))
367  ->setMethods([
368  'getLoginFormData',
369  'getAuthServices',
370  'createUserSession',
371  'getCookie',
372  ])
373  ->getMock();
374  $subject->gc_probability = -1;
375 
376  // Mock a login attempt
377  $subject->method('getLoginFormData')->willReturn([
378  'status' => 'login',
379  'uname' => 'existingUserName',
380  'uident' => 'abc'
381  ]);
382 
383  $authServiceMock = $this->getMockBuilder(AuthenticationService::class)->getMock();
384  $authServiceMock->method('getUser')->willReturn([
385  'uid' => 1,
386  'username' => 'existingUserName'
387  ]);
388  // Auth services can return true or 200
389  $authServiceMock->method('authUser')->willReturn(true);
390  // We need to wrap the array to something thats is \Traversable, in PHP 7.1 we can use traversable pseudo type instead
391  $subject->method('getAuthServices')->willReturn(new \ArrayIterator([$authServiceMock]));
392 
393  $subject->method('createUserSession')->willReturn([
394  'ses_id' => 'newSessionId'
395  ]);
396 
397  $subject->method('getCookie')->willReturn(null);
398 
399  $subject->start();
400  $this->assertFalse($subject->_get('loginFailure'));
401  $this->assertEquals('existingUserName', $subject->user['username']);
402  }
403 
410  {
411  $this->markTestSkipped('Test is flaky, convert to a functional test');
412  // Mock SessionBackend
413  $sessionBackend = $this->getMockBuilder(SessionBackendInterface::class)->getMock();
414 
415  $oldSessionRecord = [
416  'ses_id' => 'oldSessionId',
417  'ses_data' => serialize(['foo' => 'bar']),
418  'ses_anonymous' => 1,
419  'ses_iplock' => 0,
420  ];
421 
422  // Return old, non authenticated session
423  $sessionBackend->method('get')->willReturn($oldSessionRecord);
424 
425  $expectedSessionRecord = array_merge(
426  $oldSessionRecord,
427  [
428  //ses_id is overwritten by the session backend
429  'ses_anonymous' => 0
430  ]
431  );
432 
433  $expectedUserId = 1;
434 
435  $sessionBackend->expects($this->once())->method('set')->with(
436  'newSessionId',
437  $this->equalTo($expectedSessionRecord)
438  )->willReturnArgument(1);
439 
440  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
441  // Load old sessions
442  $this->subject->method('getCookie')->willReturn('oldSessionId');
443  $this->subject->method('createSessionId')->willReturn('newSessionId');
444 
445  // Mock a login attempt
446  $this->subject->method('getLoginFormData')->willReturn([
447  'status' => 'login',
448  'uname' => 'existingUserName',
449  'uident' => 'abc'
450  ]);
451 
452  $authServiceMock = $this->getMockBuilder(AuthenticationService::class)->getMock();
453  $authServiceMock->method('getUser')->willReturn([
454  'uid' => 1,
455  'username' => 'existingUserName'
456  ]);
457 
458  $authServiceMock->method('authUser')->willReturn(true); // Auth services can return true or 200
459 
460  // We need to wrap the array to something thats is \Traversable, in PHP 7.1 we can use traversable pseudo type instead
461  $this->subject->method('getAuthServices')->willReturn(new \ArrayIterator([$authServiceMock]));
462 
463  // Should call regenerateSessionId
464  // New session should be stored with with old values
465  $this->subject->start();
466 
467  $this->assertEquals('newSessionId', $this->subject->id);
468  $this->assertEquals($expectedUserId, $this->subject->user['uid']);
469  $this->subject->setSessionData('foobar', 'baz');
470  $this->assertArraySubset(['foo' => 'bar'], $this->subject->_get('sessionData'));
471  $this->assertTrue($this->subject->sesData_change);
472  }
473 
479  public function canRemoveSessionData()
480  {
481  $this->markTestSkipped('Test is flaky, convert to a functional test');
482  // Mock SessionBackend
483  $sessionBackend = $this->getMockBuilder(SessionBackendInterface::class)->getMock();
484  $sessionBackend->method('get')->willReturn(
485  [
486  'ses_id' => 'existingId',
487  'ses_userid' => 1, // fe_user with uid 0 assumed in database, see fixtures.xml
488  'ses_data' => serialize(['foo' => 'bar']),
489  'ses_iplock' => 0,
490  'ses_tstamp' => time() + 100 // Return a time in future to make avoid mocking $GLOBALS['EXEC_TIME']
491  ]
492  );
493  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
494  $this->subject->method('getCookie')->willReturn('existingId');
495 
496  $this->subject->start();
497 
498  $this->subject->removeSessionData();
499  $this->assertEmpty($this->subject->getSessionData('foo'));
500  $this->subject->storeSessionData();
501  $this->assertEmpty($this->subject->getSessionData('foo'));
502  }
503 
510  {
511  $this->markTestSkipped('Test is flaky, convert to a functional test');
512  $sessionBackend = $this->getMockBuilder(SessionBackendInterface::class)->getMock();
513  // Mock SessionBackend
514  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
515 
516  $this->subject->method('createSessionId')->willReturn('newSessionId');
517 
518  $expectedSessionRecord = [
519  'ses_anonymous' => 1,
520  'ses_data' => serialize(['foo' => 'bar'])
521  ];
522 
523  $sessionBackend->expects($this->at(0))->method('get')->willThrowException(new SessionNotFoundException('testing', 1486045419));
524  $sessionBackend->expects($this->at(1))->method('get')->willThrowException(new SessionNotFoundException('testing', 1486045420));
525  $sessionBackend->expects($this->at(2))->method('get')->willReturn(
526  [
527  'ses_id' => 'newSessionId',
528  'ses_anonymous' => 1
529  ]
530  );
531 
532  $sessionBackend->expects($this->once())
533  ->method('set')
534  ->with('newSessionId', new \PHPUnit_Framework_Constraint_ArraySubset($expectedSessionRecord))
535  ->willReturn([
536  'ses_id' => 'newSessionId',
537  'ses_anonymous' => 1,
538  'ses_data' => serialize(['foo' => 'bar']),
539  ]);
540 
541  // Can set and store session data
542  $this->subject->start();
543  $this->assertEmpty($this->subject->_get('sessionData'));
544  $this->assertEmpty($this->subject->user);
545  $this->subject->setSessionData('foo', 'bar');
546  $this->assertAttributeNotEmpty('sessionData', $this->subject);
547  $this->subject->storeSessionData();
548 
549  // Should delete session after setting to null
550  $this->subject->setSessionData('foo', null);
551  $this->assertAttributeEmpty('sessionData', $this->subject);
552  $sessionBackend->expects($this->once())->method('remove')->with('newSessionId');
553  $sessionBackend->expects($this->never())->method('update');
554 
555  $this->subject->storeSessionData();
556  }
557 
563  {
564  $this->markTestSkipped('Test is flaky, convert to a functional test');
565  $sessionBackend = $this->getMockBuilder(SessionBackendInterface::class)->getMock();
566  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
567  $this->subject->method('createSessionId')->willReturn('newSessionId');
568 
569  $sessionBackend->method('get')->willReturn(
570  [
571  'ses_id' => 'existingId',
572  'ses_userid' => 1,
573  'ses_data' => serialize(['foo' => 'bar']),
574  'ses_iplock' => 0,
575  'ses_tstamp' => time() + 100 // Return a time in future to make avoid mocking $GLOBALS['EXEC_TIME']
576  ]
577  );
578  $this->subject->method('getSessionBackend')->willReturn($sessionBackend);
579  $this->subject->method('getCookie')->willReturn('existingId');
580 
581  $this->subject->method('getRawUserByUid')->willReturn([
582  'uid' => 1,
583  ]);
584 
585  // fix logout data
586  // Mock a logout attempt
587  $this->subject->method('getLoginFormData')->willReturn([
588  'status' => 'logout',
589 
590  ]);
591 
592  $sessionBackend->expects($this->once())->method('set')->with('newSessionId', $this->anything())->willReturnArgument(1);
593  $sessionBackend->expects($this->once())->method('remove')->with('existingId');
594 
595  // start
596  $this->subject->start();
597  // asset that session data is there
598  $this->assertNotEmpty($this->subject->user);
599  $this->assertEquals(1, (int)$this->subject->user['ses_anonymous']);
600  $this->assertEquals(['foo' => 'bar'], $this->subject->_get('sessionData'));
601 
602  $this->assertEquals('newSessionId', $this->subject->id);
603  }
604 }
static addInstance($className, $instance)
static setSingletonInstance($className, SingletonInterface $instance)
static resetSingletonInstances(array $newSingletonInstances)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']