8 use Wikimedia\TestingAccessWrapper;
28 $this->config = new \HashConfig( [
29 'LanguageCode' =>
'en',
30 'SessionCacheType' =>
'testSessionStore',
31 'ObjectCacheSessionExpiry' => 100,
32 'SessionProviders' => [
36 $this->logger = new \TestLogger(
false,
function ( $m ) {
37 return substr( $m, 0, 15 ) ===
'SessionBackend ' ? null : $m;
42 'config' => $this->config,
43 'logger' => $this->logger,
44 'store' => $this->store,
49 return [
'factory' =>
function ()
use ( $object ) {
69 $rProp->setAccessible(
true );
70 $handler = TestingAccessWrapper::newFromObject( $rProp->getValue() );
72 $reset[] = new \Wikimedia\ScopedCallback(
function ()
use (
$handler, $oldEnable ) {
74 session_write_close();
83 $id =
$request->getSession()->getId();
87 $this->assertSame( $id, $session->getId() );
89 session_id(
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' );
91 $this->assertSame(
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', $session->getId() );
92 $this->assertSame(
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
$request->getSession()->getId() );
94 session_write_close();
98 $id =
$request->getSession()->getId();
102 $this->assertSame( $id, $session->getId() );
104 session_id(
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' );
106 $this->assertSame( $id, $session->getId() );
107 $this->assertSame( $id,
$request->getSession()->getId() );
111 $manager = TestingAccessWrapper::newFromObject( $this->
getManager() );
112 $this->assertSame( $this->config, $manager->config );
113 $this->assertSame( $this->logger, $manager->logger );
114 $this->assertSame( $this->
store, $manager->store );
116 $manager = TestingAccessWrapper::newFromObject(
new SessionManager() );
119 $manager = TestingAccessWrapper::newFromObject(
new SessionManager( [
120 'config' => $this->config,
125 'config' =>
'$options[\'config\'] must be an instance of Config',
126 'logger' =>
'$options[\'logger\'] must be an instance of LoggerInterface',
127 'store' =>
'$options[\'store\'] must be an instance of BagOStuff',
128 ]
as $key => $error ) {
131 $this->fail(
'Expected exception not thrown' );
132 }
catch ( \InvalidArgumentException $ex ) {
133 $this->assertSame( $error, $ex->getMessage() );
146 $idEmpty =
'empty-session-------------------';
150 [
'provideSessionInfo',
'newSessionInfo',
'__toString',
'describe',
'unpersistSession' ]
153 $provider1 = $providerBuilder->getMock();
154 $provider1->expects( $this->
any() )->method(
'provideSessionInfo' )
155 ->with( $this->identicalTo(
$request ) )
156 ->will( $this->returnCallback(
function (
$request ) {
159 $provider1->expects( $this->
any() )->method(
'newSessionInfo' )
160 ->will( $this->returnCallback(
function ()
use ( $idEmpty, $provider1 ) {
162 'provider' => $provider1,
168 $provider1->expects( $this->
any() )->method(
'__toString' )
169 ->will( $this->returnValue(
'Provider1' ) );
170 $provider1->expects( $this->
any() )->method(
'describe' )
171 ->will( $this->returnValue(
'#1 sessions' ) );
172 $provider1->expects( $this->
any() )->method(
'unpersistSession' )
173 ->will( $this->returnCallback(
function (
$request ) {
177 $provider2 = $providerBuilder->getMock();
178 $provider2->expects( $this->
any() )->method(
'provideSessionInfo' )
179 ->with( $this->identicalTo(
$request ) )
180 ->will( $this->returnCallback(
function (
$request ) {
183 $provider2->expects( $this->
any() )->method(
'__toString' )
184 ->will( $this->returnValue(
'Provider2' ) );
185 $provider2->expects( $this->
any() )->method(
'describe' )
186 ->will( $this->returnValue(
'#2 sessions' ) );
187 $provider2->expects( $this->
any() )->method(
'unpersistSession' )
188 ->will( $this->returnCallback(
function (
$request ) {
192 $this->config->set(
'SessionProviders', [
200 $session = $manager->getSessionForRequest(
$request );
202 $this->assertSame( $idEmpty, $session->getId() );
203 $this->assertFalse(
$request->unpersist1 );
204 $this->assertFalse(
$request->unpersist2 );
208 'provider' => $provider1,
209 'id' => ( $id1 = $manager->generateSessionId() ),
214 'provider' => $provider2,
215 'id' => ( $id2 = $manager->generateSessionId() ),
219 $session = $manager->getSessionForRequest(
$request );
221 $this->assertSame( $id2, $session->getId() );
222 $this->assertFalse(
$request->unpersist1 );
223 $this->assertFalse(
$request->unpersist2 );
226 'provider' => $provider1,
227 'id' => ( $id1 = $manager->generateSessionId() ),
232 'provider' => $provider2,
233 'id' => ( $id2 = $manager->generateSessionId() ),
237 $session = $manager->getSessionForRequest(
$request );
239 $this->assertSame( $id1, $session->getId() );
240 $this->assertFalse(
$request->unpersist1 );
241 $this->assertFalse(
$request->unpersist2 );
245 'provider' => $provider1,
246 'id' => ( $id1 = $manager->generateSessionId() ),
252 'provider' => $provider2,
253 'id' => ( $id2 = $manager->generateSessionId() ),
259 $manager->getSessionForRequest(
$request );
260 $this->fail(
'Expcected exception not thrown' );
261 }
catch ( \OverflowException $ex ) {
262 $this->assertStringStartsWith(
263 'Multiple sessions for this request tied for top priority: ',
266 $this->assertCount( 2, $ex->sessionInfos );
267 $this->assertContains(
$request->info1, $ex->sessionInfos );
268 $this->assertContains(
$request->info2, $ex->sessionInfos );
270 $this->assertFalse(
$request->unpersist1 );
271 $this->assertFalse(
$request->unpersist2 );
275 'provider' => $provider2,
276 'id' => ( $id1 = $manager->generateSessionId() ),
282 $manager->getSessionForRequest(
$request );
283 $this->fail(
'Expcected exception not thrown' );
284 }
catch ( \UnexpectedValueException $ex ) {
286 'Provider1 returned session info for a different provider: ' .
$request->info1,
290 $this->assertFalse(
$request->unpersist1 );
291 $this->assertFalse(
$request->unpersist2 );
294 $this->logger->setCollect(
true );
296 'provider' => $provider1,
297 'id' => ( $id1 = $manager->generateSessionId() ),
303 'provider' => $provider2,
304 'id' => ( $id2 = $manager->generateSessionId() ),
308 $session = $manager->getSessionForRequest(
$request );
310 $this->assertSame( $id2, $session->getId() );
311 $this->logger->setCollect(
false );
312 $this->assertTrue(
$request->unpersist1 );
313 $this->assertFalse(
$request->unpersist2 );
316 $this->logger->setCollect(
true );
318 'provider' => $provider1,
319 'id' => ( $id1 = $manager->generateSessionId() ),
324 'provider' => $provider2,
325 'id' => ( $id2 = $manager->generateSessionId() ),
330 $session = $manager->getSessionForRequest(
$request );
332 $this->assertSame( $id1, $session->
getId() );
333 $this->logger->setCollect(
false );
334 $this->assertFalse(
$request->unpersist1 );
335 $this->assertTrue(
$request->unpersist2 );
340 'provider' => $provider1,
341 'id' => ( $id1 = $manager->generateSessionId() ),
342 'persisted' =>
false,
347 $session = $manager->getSessionForRequest(
$request );
349 $this->assertSame( $id1, $session->
getId() );
350 $this->assertTrue(
$request->unpersist1 );
351 $this->assertFalse(
$request->unpersist2 );
353 $this->assertTrue( $session->isPersistent(),
'sanity check' );
359 $manager->getSessionById(
'bad' );
360 $this->fail(
'Expected exception not thrown' );
361 }
catch ( \InvalidArgumentException $ex ) {
362 $this->assertSame(
'Invalid session ID', $ex->getMessage() );
366 $id = $manager->generateSessionId();
367 $session = $manager->getSessionById( $id,
true );
369 $this->assertSame( $id, $session->getId() );
371 $id = $manager->generateSessionId();
372 $this->assertNull( $manager->getSessionById( $id,
false ) );
375 $this->logger->setCollect(
true );
376 $id = $manager->generateSessionId();
377 $this->
store->setSession( $id, [
'metadata' => [
379 'userToken' =>
'bad',
382 $this->assertNull( $manager->getSessionById( $id,
true ) );
383 $this->assertNull( $manager->getSessionById( $id,
false ) );
384 $this->logger->setCollect(
false );
387 $this->
store->setSession( $id, [] );
388 $session = $manager->getSessionById( $id,
false );
390 $this->assertSame( $id, $session->getId() );
393 $this->
store->setSession( $id, [
'metadata' => [
395 'userToken' =>
'bad',
397 $session2 = $manager->getSessionById( $id,
false );
399 $this->assertSame( $id, $session2->getId() );
400 unset( $session, $session2 );
401 $this->logger->setCollect(
true );
402 $this->assertNull( $manager->getSessionById( $id,
true ) );
403 $this->logger->setCollect(
false );
408 ->setMethods( [
'provideSessionInfo',
'newSessionInfo',
'__toString' ] )
410 $provider->expects( $this->
any() )->method(
'provideSessionInfo' )
411 ->will( $this->returnValue(
null ) );
412 $provider->expects( $this->
any() )->method(
'newSessionInfo' )
413 ->will( $this->returnValue(
null ) );
414 $provider->expects( $this->
any() )->method(
'__toString' )
415 ->will( $this->returnValue(
'MockProvider' ) );
416 $this->config->set(
'SessionProviders', [
419 $this->logger->setCollect(
true );
420 $this->assertNull( $manager->getSessionById( $id,
true ) );
421 $this->logger->setCollect(
false );
423 [ LogLevel::ERROR,
'Failed to create empty session: {exception}' ]
424 ], $this->logger->getBuffer() );
429 $pmanager = TestingAccessWrapper::newFromObject( $manager );
433 ->setMethods( [
'provideSessionInfo',
'newSessionInfo',
'__toString' ] );
439 $provider1 = $providerBuilder->getMock();
440 $provider1->expects( $this->
any() )->method(
'provideSessionInfo' )
441 ->will( $this->returnValue(
null ) );
442 $provider1->expects( $this->
any() )->method(
'newSessionInfo' )
443 ->with( $this->callback(
function ( $id )
use ( &$expectId ) {
444 return $id === $expectId;
446 ->will( $this->returnCallback(
function ()
use ( &$info1 ) {
449 $provider1->expects( $this->
any() )->method(
'__toString' )
450 ->will( $this->returnValue(
'MockProvider1' ) );
452 $provider2 = $providerBuilder->getMock();
453 $provider2->expects( $this->
any() )->method(
'provideSessionInfo' )
454 ->will( $this->returnValue(
null ) );
455 $provider2->expects( $this->
any() )->method(
'newSessionInfo' )
456 ->with( $this->callback(
function ( $id )
use ( &$expectId ) {
457 return $id === $expectId;
459 ->will( $this->returnCallback(
function ()
use ( &$info2 ) {
462 $provider1->expects( $this->
any() )->method(
'__toString' )
463 ->will( $this->returnValue(
'MockProvider2' ) );
465 $this->config->set(
'SessionProviders', [
475 $manager->getEmptySession();
476 $this->fail(
'Expected exception not thrown' );
477 }
catch ( \UnexpectedValueException $ex ) {
479 'No provider could provide an empty session!',
487 'provider' => $provider1,
488 'id' =>
'empty---------------------------',
493 $session = $manager->getEmptySession();
495 $this->assertSame(
'empty---------------------------', $session->getId() );
498 $expectId =
'expected------------------------';
500 'provider' => $provider1,
506 $session = $pmanager->getEmptySessionInternal(
null, $expectId );
508 $this->assertSame( $expectId, $session->getId() );
511 $expectId =
'expected-----------------------2';
513 'provider' => $provider1,
514 'id' =>
"un$expectId",
520 $pmanager->getEmptySessionInternal(
null, $expectId );
521 $this->fail(
'Expected exception not thrown' );
522 }
catch ( \UnexpectedValueException $ex ) {
524 'MockProvider1 returned empty session info with a wrong id: ' .
525 "un$expectId != $expectId",
531 $expectId =
'expected-----------------------2';
533 'provider' => $provider1,
539 $pmanager->getEmptySessionInternal(
null, $expectId );
540 $this->fail(
'Expected exception not thrown' );
541 }
catch ( \UnexpectedValueException $ex ) {
543 'MockProvider1 returned empty session info with id flagged unsafe',
551 'provider' => $provider2,
552 'id' =>
'empty---------------------------',
558 $manager->getEmptySession();
559 $this->fail(
'Expected exception not thrown' );
560 }
catch ( \UnexpectedValueException $ex ) {
562 'MockProvider1 returned an empty session info for a different provider: ' . $info1,
570 'provider' => $provider1,
571 'id' =>
'empty1--------------------------',
576 'provider' => $provider2,
577 'id' =>
'empty2--------------------------',
581 $session = $manager->getEmptySession();
583 $this->assertSame(
'empty1--------------------------', $session->getId() );
587 'provider' => $provider1,
588 'id' =>
'empty1--------------------------',
593 'provider' => $provider2,
594 'id' =>
'empty2--------------------------',
598 $session = $manager->getEmptySession();
600 $this->assertSame(
'empty2--------------------------', $session->getId() );
605 'provider' => $provider1,
606 'id' =>
'empty1--------------------------',
612 'provider' => $provider2,
613 'id' =>
'empty2--------------------------',
619 $manager->getEmptySession();
620 $this->fail(
'Expected exception not thrown' );
621 }
catch ( \UnexpectedValueException $ex ) {
622 $this->assertStringStartsWith(
623 'Multiple empty sessions tied for top priority: ',
630 $pmanager->getEmptySessionInternal(
null,
'bad' );
631 $this->fail(
'Expected exception not thrown' );
632 }
catch ( \InvalidArgumentException $ex ) {
633 $this->assertSame(
'Invalid session ID', $ex->getMessage() );
637 $expectId =
'expected-----------------------3';
638 $this->
store->setSessionMeta( $expectId, [
639 'provider' =>
'MockProvider2',
645 $pmanager->getEmptySessionInternal(
null, $expectId );
646 $this->fail(
'Expected exception not thrown' );
647 }
catch ( \InvalidArgumentException $ex ) {
648 $this->assertSame(
'Session ID already exists', $ex->getMessage() );
657 ->setMethods( [
'invalidateSessionsForUser',
'__toString' ] );
659 $provider1 = $providerBuilder->getMock();
660 $provider1->expects( $this->once() )->method(
'invalidateSessionsForUser' )
661 ->with( $this->identicalTo(
$user ) );
662 $provider1->expects( $this->
any() )->method(
'__toString' )
663 ->will( $this->returnValue(
'MockProvider1' ) );
665 $provider2 = $providerBuilder->getMock();
666 $provider2->expects( $this->once() )->method(
'invalidateSessionsForUser' )
667 ->with( $this->identicalTo(
$user ) );
668 $provider2->expects( $this->
any() )->method(
'__toString' )
669 ->will( $this->returnValue(
'MockProvider2' ) );
671 $this->config->set(
'SessionProviders', [
676 $oldToken =
$user->getToken(
true );
677 $manager->invalidateSessionsForUser(
$user );
678 $this->assertNotEquals( $oldToken,
$user->getToken() );
685 ->setMethods( [
'getVaryHeaders',
'__toString' ] );
687 $provider1 = $providerBuilder->getMock();
688 $provider1->expects( $this->once() )->method(
'getVaryHeaders' )
689 ->will( $this->returnValue( [
691 'Bar' => [
'X',
'Bar1' ],
694 $provider1->expects( $this->
any() )->method(
'__toString' )
695 ->will( $this->returnValue(
'MockProvider1' ) );
697 $provider2 = $providerBuilder->getMock();
698 $provider2->expects( $this->once() )->method(
'getVaryHeaders' )
699 ->will( $this->returnValue( [
701 'Bar' => [
'X',
'Bar2' ],
702 'Quux' => [
'Quux' ],
704 $provider2->expects( $this->
any() )->method(
'__toString' )
705 ->will( $this->returnValue(
'MockProvider2' ) );
707 $this->config->set(
'SessionProviders', [
714 'Bar' => [
'X',
'Bar1', 3 =>
'Bar2' ],
715 'Quux' => [
'Quux' ],
719 $this->assertEquals( $expect, $manager->getVaryHeaders() );
722 $this->assertEquals( $expect, $manager->getVaryHeaders() );
729 ->setMethods( [
'getVaryCookies',
'__toString' ] );
731 $provider1 = $providerBuilder->getMock();
732 $provider1->expects( $this->once() )->method(
'getVaryCookies' )
733 ->will( $this->returnValue( [
'Foo',
'Bar' ] ) );
734 $provider1->expects( $this->
any() )->method(
'__toString' )
735 ->will( $this->returnValue(
'MockProvider1' ) );
737 $provider2 = $providerBuilder->getMock();
738 $provider2->expects( $this->once() )->method(
'getVaryCookies' )
739 ->will( $this->returnValue( [
'Foo',
'Baz' ] ) );
740 $provider2->expects( $this->
any() )->method(
'__toString' )
741 ->will( $this->returnValue(
'MockProvider2' ) );
743 $this->config->set(
'SessionProviders', [
748 $expect = [
'Foo',
'Bar',
'Baz' ];
750 $this->assertEquals( $expect, $manager->getVaryCookies() );
753 $this->assertEquals( $expect, $manager->getVaryCookies() );
758 $manager = TestingAccessWrapper::newFromObject( $realManager );
760 $this->config->set(
'SessionProviders', [
763 $providers = $manager->getProviders();
764 $this->assertArrayHasKey(
'DummySessionProvider', $providers );
765 $provider = TestingAccessWrapper::newFromObject( $providers[
'DummySessionProvider'] );
766 $this->assertSame( $manager->logger, $provider->logger );
767 $this->assertSame( $manager->config, $provider->config );
768 $this->assertSame( $realManager, $provider->getManager() );
770 $this->config->set(
'SessionProviders', [
774 $manager->sessionProviders =
null;
776 $manager->getProviders();
777 $this->fail(
'Expected exception not thrown' );
778 }
catch ( \UnexpectedValueException $ex ) {
780 'Duplicate provider name "DummySessionProvider"',
787 $manager = TestingAccessWrapper::newFromObject( $this->
getManager() );
788 $manager->setLogger(
new \Psr\Log\NullLogger() );
791 ->setMethods( [
'shutdown' ] )->getMock();
792 $mock->expects( $this->once() )->method(
'shutdown' );
794 $manager->allSessionBackends = [ $mock ];
795 $manager->shutdown();
799 $manager = TestingAccessWrapper::newFromObject( $this->
getManager() );
802 $id =
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
805 'provider' => $manager->getProvider(
'DummySessionProvider' ),
811 TestingAccessWrapper::newFromObject( $info )->idIsSafe =
true;
812 $session1 = TestingAccessWrapper::newFromObject(
813 $manager->getSessionFromInfo( $info,
$request )
815 $session2 = TestingAccessWrapper::newFromObject(
816 $manager->getSessionFromInfo( $info,
$request )
819 $this->assertSame( $session1->backend, $session2->backend );
820 $this->assertNotEquals( $session1->index, $session2->index );
821 $this->assertSame( $session1->getSessionId(), $session2->getSessionId() );
822 $this->assertSame( $id, $session1->getId() );
824 TestingAccessWrapper::newFromObject( $info )->idIsSafe =
false;
825 $session3 = $manager->getSessionFromInfo( $info,
$request );
826 $this->assertNotSame( $id, $session3->getId() );
832 $session = $manager->getSessionForRequest(
new \
FauxRequest );
833 $backend = TestingAccessWrapper::newFromObject( $session )->backend;
834 $sessionId = $session->getSessionId();
837 $this->assertSame( $sessionId, $manager->getSessionById( $id,
true )->getSessionId() );
839 $manager->changeBackendId( $backend );
840 $this->assertSame( $sessionId, $session->getSessionId() );
841 $this->assertNotEquals( $id, (
string)$sessionId );
844 $this->assertSame( $sessionId, $manager->getSessionById( $id,
true )->getSessionId() );
850 $manager->changeBackendId( $backend );
851 $this->fail(
'Expected exception not thrown' );
852 }
catch ( \InvalidArgumentException $ex ) {
854 'Backend was not registered with this SessionManager', $ex->getMessage()
859 $manager->deregisterSessionBackend( $backend );
860 $this->fail(
'Expected exception not thrown' );
861 }
catch ( \InvalidArgumentException $ex ) {
863 'Backend was not registered with this SessionManager', $ex->getMessage()
867 $session = $manager->getSessionById( $id,
true );
868 $this->assertSame( $sessionId, $session->getSessionId() );
874 $id = $manager->generateSessionId();
882 ->setMethods( [
'preventSessionsForUser',
'__toString' ] );
884 $provider1 = $providerBuilder->getMock();
885 $provider1->expects( $this->once() )->method(
'preventSessionsForUser' )
886 ->with( $this->equalTo(
'UTSysop' ) );
887 $provider1->expects( $this->
any() )->method(
'__toString' )
888 ->will( $this->returnValue(
'MockProvider1' ) );
890 $this->config->set(
'SessionProviders', [
894 $this->assertFalse( $manager->isUserSessionPrevented(
'UTSysop' ) );
895 $manager->preventSessionsForUser(
'UTSysop' );
896 $this->assertTrue( $manager->isUserSessionPrevented(
'UTSysop' ) );
901 $logger = new \TestLogger(
true );
902 $manager->setLogger(
$logger );
906 $rClass = new \ReflectionClass( $manager );
907 $rMethod = $rClass->getMethod(
'loadSessionInfoFromStore' );
908 $rMethod->setAccessible(
true );
909 $loadSessionInfoFromStore =
function ( &$info )
use ( $rMethod, $manager,
$request ) {
910 return $rMethod->invokeArgs( $manager, [ &$info,
$request ] );
916 $id =
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
918 'userId' => $userInfo->getId(),
919 'userName' => $userInfo->getName(),
920 'userToken' => $userInfo->getToken(
true ),
921 'provider' =>
'Mock',
925 ->setMethods( [
'__toString',
'mergeMetadata',
'refreshSessionInfo' ] );
927 $provider = $builder->getMockForAbstractClass();
928 $provider->setManager( $manager );
929 $provider->expects( $this->
any() )->method(
'persistsSessionId' )
930 ->will( $this->returnValue(
true ) );
931 $provider->expects( $this->
any() )->method(
'canChangeUser' )
932 ->will( $this->returnValue(
true ) );
933 $provider->expects( $this->
any() )->method(
'refreshSessionInfo' )
934 ->will( $this->returnValue(
true ) );
935 $provider->expects( $this->
any() )->method(
'__toString' )
936 ->will( $this->returnValue(
'Mock' ) );
937 $provider->expects( $this->
any() )->method(
'mergeMetadata' )
938 ->will( $this->returnCallback(
function ( $a, $b ) {
939 if ( $b === [
'Throw' ] ) {
945 $provider2 = $builder->getMockForAbstractClass();
946 $provider2->setManager( $manager );
947 $provider2->expects( $this->
any() )->method(
'persistsSessionId' )
948 ->will( $this->returnValue(
false ) );
949 $provider2->expects( $this->
any() )->method(
'canChangeUser' )
950 ->will( $this->returnValue(
false ) );
951 $provider2->expects( $this->
any() )->method(
'__toString' )
952 ->will( $this->returnValue(
'Mock2' ) );
953 $provider2->expects( $this->
any() )->method(
'refreshSessionInfo' )
954 ->will( $this->returnCallback(
function ( $info,
$request, &$metadata ) {
955 $metadata[
'changed'] =
true;
959 $provider3 = $builder->getMockForAbstractClass();
960 $provider3->setManager( $manager );
961 $provider3->expects( $this->
any() )->method(
'persistsSessionId' )
962 ->will( $this->returnValue(
true ) );
963 $provider3->expects( $this->
any() )->method(
'canChangeUser' )
964 ->will( $this->returnValue(
true ) );
965 $provider3->expects( $this->once() )->method(
'refreshSessionInfo' )
966 ->will( $this->returnValue(
false ) );
967 $provider3->expects( $this->
any() )->method(
'__toString' )
968 ->will( $this->returnValue(
'Mock3' ) );
970 TestingAccessWrapper::newFromObject( $manager )->sessionProviders = [
971 (
string)$provider => $provider,
972 (
string)$provider2 => $provider2,
973 (
string)$provider3 => $provider3,
978 'provider' => $provider,
980 'userInfo' => $userInfo
982 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
983 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
984 $this->assertFalse( $info->isIdSafe() );
988 'provider' => $provider,
989 'userInfo' => $userInfo
991 $this->assertTrue( $info->isIdSafe(),
'sanity check' );
992 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
993 $this->assertTrue( $info->isIdSafe() );
997 'provider' => $provider2,
999 'userInfo' => $userInfo
1001 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1002 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1003 $this->assertTrue( $info->isIdSafe() );
1008 'provider' => $provider,
1010 'userInfo' => $unverifiedUserInfo
1012 $this->assertSame( $unverifiedUserInfo, $info->getUserInfo() );
1013 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1014 $this->assertSame( [
1017 'Session "{session}": Unverified user provided and no metadata to auth it',
1025 'userInfo' => $userInfo
1027 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1028 $this->assertSame( [
1029 [ LogLevel::WARNING,
'Session "{session}": Null provider and no metadata' ],
1034 'provider' => $provider,
1037 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1038 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1040 $this->assertTrue( $info->getUserInfo()->isVerified() );
1041 $this->assertTrue( $info->getUserInfo()->isAnon() );
1042 $this->assertFalse( $info->isIdSafe() );
1046 'provider' => $provider2,
1049 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1050 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1051 $this->assertSame( [
1052 [ LogLevel::INFO,
'Session "{session}": No user provided and provider cannot set user' ]
1057 $this->
store->setRawSession( $id,
true );
1058 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1059 $this->assertSame( [
1060 [ LogLevel::WARNING,
'Session "{session}": Bad data' ],
1064 $this->
store->setRawSession( $id, [
'data' => [] ] );
1065 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1066 $this->assertSame( [
1067 [ LogLevel::WARNING,
'Session "{session}": Bad data structure' ],
1071 $this->
store->deleteSession( $id );
1072 $this->
store->setRawSession( $id, [
'metadata' => $metadata ] );
1073 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1074 $this->assertSame( [
1075 [ LogLevel::WARNING,
'Session "{session}": Bad data structure' ],
1079 $this->
store->setRawSession( $id, [
'metadata' => $metadata,
'data' =>
true ] );
1080 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1081 $this->assertSame( [
1082 [ LogLevel::WARNING,
'Session "{session}": Bad data structure' ],
1086 $this->
store->setRawSession( $id, [
'metadata' =>
true,
'data' => [] ] );
1087 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1088 $this->assertSame( [
1089 [ LogLevel::WARNING,
'Session "{session}": Bad data structure' ],
1093 foreach ( $metadata
as $key => $dummy ) {
1095 unset( $tmp[$key] );
1096 $this->
store->setRawSession( $id, [
'metadata' => $tmp,
'data' => [] ] );
1097 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1098 $this->assertSame( [
1099 [ LogLevel::WARNING,
'Session "{session}": Bad metadata' ],
1105 $this->
store->setRawSession( $id, [
'metadata' => $metadata,
'data' => [] ] );
1107 'provider' => $provider,
1109 'userInfo' => $userInfo
1111 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1112 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1113 $this->assertTrue( $info->isIdSafe() );
1117 $this->
store->setSessionMeta( $id, [
'provider' =>
'Bad' ] + $metadata );
1119 'provider' => $provider,
1121 'userInfo' => $userInfo
1123 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1124 $this->assertSame( [
1125 [ LogLevel::WARNING,
'Session "{session}": Wrong provider Bad !== Mock' ],
1130 $this->
store->setSessionMeta( $id, [
'provider' =>
'Bad' ] + $metadata );
1133 'userInfo' => $userInfo
1135 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1136 $this->assertSame( [
1137 [ LogLevel::WARNING,
'Session "{session}": Unknown provider Bad' ],
1142 $this->
store->setSessionMeta( $id, $metadata );
1145 'userInfo' => $userInfo
1147 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1148 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1149 $this->assertTrue( $info->isIdSafe() );
1153 $this->
store->setSessionMeta( $id, [
'userId' => -1,
'userToken' =>
null ] + $metadata );
1155 'provider' => $provider,
1158 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1159 $this->assertSame( [
1160 [ LogLevel::ERROR,
'Session "{session}": {exception}' ],
1164 $this->
store->setSessionMeta(
1165 $id, [
'userId' => 0,
'userName' =>
'<X>',
'userToken' =>
null ] + $metadata
1168 'provider' => $provider,
1171 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1172 $this->assertSame( [
1173 [ LogLevel::ERROR,
'Session "{session}": {exception}', ],
1178 $this->
store->setSessionMeta(
1179 $id, [
'userId' => $userInfo->getId() + 1,
'userToken' => null ] + $metadata
1182 'provider' => $provider,
1184 'userInfo' => $userInfo
1186 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1187 $this->assertSame( [
1188 [ LogLevel::WARNING,
'Session "{session}": User ID mismatch, {uid_a} !== {uid_b}' ],
1193 $this->
store->setSessionMeta(
1194 $id, [
'userId' => 0,
'userName' =>
'X',
'userToken' =>
null ] + $metadata
1197 'provider' => $provider,
1199 'userInfo' => $userInfo
1201 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1202 $this->assertSame( [
1203 [ LogLevel::WARNING,
'Session "{session}": User name mismatch, {uname_a} !== {uname_b}' ],
1208 $this->
store->setSessionMeta(
1209 $id, [
'userId' => $userInfo->getId(),
'userName' =>
'X',
'userToken' => null ] + $metadata
1212 'provider' => $provider,
1214 'userInfo' => $userInfo
1216 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1217 $this->assertSame( [
1220 'Session "{session}": User ID matched but name didn\'t (rename?), {uname_a} !== {uname_b}'
1226 $this->
store->setSessionMeta(
1227 $id, [
'userId' => 0,
'userName' =>
null,
'userToken' =>
null ] + $metadata
1230 'provider' => $provider,
1232 'userInfo' => $userInfo
1234 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1235 $this->assertSame( [
1238 'Session "{session}": Metadata has an anonymous user, ' .
1239 'but a non-anon user was provided',
1245 $this->
store->setSessionMeta( $id, [
'userToken' =>
null ] + $metadata );
1247 'provider' => $provider,
1250 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1251 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1252 $this->assertSame( $userInfo->getId(), $info->getUserInfo()->getId() );
1253 $this->assertTrue( $info->isIdSafe() );
1257 $this->
store->setSessionMeta(
1258 $id, [
'userId' => 0,
'userName' =>
'UTSysop',
'userToken' =>
null ] + $metadata
1261 'provider' => $provider,
1264 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1265 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1266 $this->assertSame( $userInfo->getId(), $info->getUserInfo()->getId() );
1267 $this->assertTrue( $info->isIdSafe() );
1271 $this->
store->setSessionMeta(
1272 $id, [
'userId' => 0,
'userName' =>
null,
'userToken' =>
null ] + $metadata
1275 'provider' => $provider,
1278 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1279 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1280 $this->assertTrue( $info->getUserInfo()->isAnon() );
1281 $this->assertTrue( $info->isIdSafe() );
1285 $this->
store->setSessionMeta( $id, $metadata );
1287 'provider' => $provider,
1289 'userInfo' => $unverifiedUserInfo
1291 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1292 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1293 $this->assertTrue( $info->getUserInfo()->isVerified() );
1294 $this->assertSame( $unverifiedUserInfo->getId(), $info->getUserInfo()->getId() );
1295 $this->assertSame( $unverifiedUserInfo->getName(), $info->getUserInfo()->getName() );
1296 $this->assertTrue( $info->isIdSafe() );
1300 $this->
store->setSessionMeta( $id, $metadata );
1302 'provider' => $provider,
1304 'userInfo' => $unverifiedUserInfo
1306 $this->assertFalse( $info->isIdSafe(),
'sanity check' );
1307 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1308 $this->assertTrue( $info->getUserInfo()->isVerified() );
1309 $this->assertSame( $unverifiedUserInfo->getId(), $info->getUserInfo()->getId() );
1310 $this->assertSame( $unverifiedUserInfo->getName(), $info->getUserInfo()->getName() );
1311 $this->assertTrue( $info->isIdSafe() );
1315 $this->
store->setSessionMeta( $id, [
'userToken' =>
'Bad' ] + $metadata );
1317 'provider' => $provider,
1319 'userInfo' => $userInfo
1321 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1322 $this->assertSame( [
1323 [ LogLevel::WARNING,
'Session "{session}": User token mismatch' ],
1328 $this->
store->setSessionMeta( $id, [
'provider' =>
'Mock2' ] + $metadata );
1330 'provider' => $provider2,
1332 'userInfo' => $userInfo,
1333 'metadata' => [
'Info' ],
1335 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1336 $this->assertSame( [
'Info',
'changed' =>
true ], $info->getProviderMetadata() );
1339 $this->
store->setSessionMeta( $id, [
'providerMetadata' => [
'Saved' ] ] + $metadata );
1341 'provider' => $provider,
1343 'userInfo' => $userInfo,
1345 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1346 $this->assertSame( [
'Saved' ], $info->getProviderMetadata() );
1350 'provider' => $provider,
1352 'userInfo' => $userInfo,
1353 'metadata' => [
'Info' ],
1355 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1356 $this->assertSame( [
'Merged' ], $info->getProviderMetadata() );
1360 'provider' => $provider,
1362 'userInfo' => $userInfo,
1363 'metadata' => [
'Throw' ],
1365 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1366 $this->assertSame( [
1369 'Session "{session}": Metadata merge failed: {exception}',
1375 $this->
store->setSessionMeta( $id, $metadata );
1377 'provider' => $provider,
1380 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1381 $this->assertFalse( $info->wasRemembered() );
1384 $this->
store->setSessionMeta( $id, [
'remember' =>
true ] + $metadata );
1386 'provider' => $provider,
1389 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1390 $this->assertTrue( $info->wasRemembered() );
1393 $this->
store->setSessionMeta( $id, [
'remember' =>
false ] + $metadata );
1395 'provider' => $provider,
1397 'userInfo' => $userInfo
1399 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1400 $this->assertTrue( $info->wasRemembered() );
1404 $this->
store->setSessionMeta( $id, $metadata );
1406 'provider' => $provider,
1408 'userInfo' => $userInfo
1410 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1411 $this->assertFalse( $info->forceHTTPS() );
1414 $this->
store->setSessionMeta( $id, [
'forceHTTPS' =>
true ] + $metadata );
1416 'provider' => $provider,
1418 'userInfo' => $userInfo
1420 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1421 $this->assertTrue( $info->forceHTTPS() );
1424 $this->
store->setSessionMeta( $id, [
'forceHTTPS' =>
false ] + $metadata );
1426 'provider' => $provider,
1428 'userInfo' => $userInfo,
1429 'forceHTTPS' =>
true
1431 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1432 $this->assertTrue( $info->forceHTTPS() );
1436 $this->
store->setSessionMeta( $id, $metadata );
1438 'provider' => $provider,
1440 'userInfo' => $userInfo
1442 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1443 $this->assertFalse( $info->wasPersisted() );
1446 $this->
store->setSessionMeta( $id, [
'persisted' =>
true ] + $metadata );
1448 'provider' => $provider,
1450 'userInfo' => $userInfo
1452 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1453 $this->assertTrue( $info->wasPersisted() );
1456 $this->
store->setSessionMeta( $id, [
'persisted' =>
false ] + $metadata );
1458 'provider' => $provider,
1460 'userInfo' => $userInfo,
1463 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1464 $this->assertTrue( $info->wasPersisted() );
1469 'provider' => $provider3,
1471 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1476 $data = [
'foo' => 1 ];
1477 $this->
store->setSession( $id, [
'metadata' => $metadata,
'data' => $data ] );
1479 'provider' => $provider,
1481 'userInfo' => $userInfo
1484 'SessionCheckInfo' => [
function ( &$reason, $i, $r, $m, $d )
use (
1487 $this->assertSame( $info->getId(), $i->getId() );
1488 $this->assertSame( $info->getProvider(), $i->getProvider() );
1489 $this->assertSame( $info->getUserInfo(), $i->getUserInfo() );
1491 $this->assertEquals( $metadata, $m );
1492 $this->assertEquals( $data, $d );
1497 $this->assertFalse( $loadSessionInfoFromStore( $info ) );
1499 $this->assertSame( [
1500 [ LogLevel::WARNING,
'Session "{session}": Hook aborted' ],
1506 $this->
store->setSessionMeta( $id, [
'userToken' =>
'Bad' ] + $metadata );
1508 'provider' => $provider,
1510 'userInfo' => $userInfo,
1513 $this->assertTrue( $loadSessionInfoFromStore( $info ) );
1514 $this->assertFalse( $this->
store->getSession( $id ) );
1515 $this->assertSame( [
1516 [ LogLevel::WARNING,
'Session "{session}": User token mismatch' ],