Esempio n. 1
0
 /**
  * Create a session corresponding to the passed SessionInfo
  * @private For use by a SessionProvider that needs to specially create its
  *  own session.
  * @param SessionInfo $info
  * @param WebRequest $request
  * @return Session
  */
 public function getSessionFromInfo(SessionInfo $info, WebRequest $request)
 {
     $id = $info->getId();
     if (!isset($this->allSessionBackends[$id])) {
         if (!isset($this->allSessionIds[$id])) {
             $this->allSessionIds[$id] = new SessionId($id);
         }
         $backend = new SessionBackend($this->allSessionIds[$id], $info, $this->store, $this->logger, $this->config->get('ObjectCacheSessionExpiry'));
         $this->allSessionBackends[$id] = $backend;
         $delay = $backend->delaySave();
     } else {
         $backend = $this->allSessionBackends[$id];
         $delay = $backend->delaySave();
         if ($info->wasPersisted()) {
             $backend->persist();
         }
         if ($info->wasRemembered()) {
             $backend->setRememberUser(true);
         }
     }
     $request->setSessionId($backend->getSessionId());
     $session = $backend->getSession($request);
     if (!$info->isIdSafe()) {
         $session->resetId();
     }
     \ScopedCallback::consume($delay);
     return $session;
 }
Esempio n. 2
0
 /**
  * Compare two SessionInfo objects by priority
  * @param SessionInfo $a
  * @param SessionInfo $b
  * @return int Negative if $a < $b, positive if $a > $b, zero if equal
  */
 public static function compare($a, $b)
 {
     return $a->getPriority() - $b->getPriority();
 }
Esempio n. 3
0
 public function testCompare()
 {
     $id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
     $info1 = new SessionInfo(SessionInfo::MIN_PRIORITY + 1, array('id' => $id));
     $info2 = new SessionInfo(SessionInfo::MIN_PRIORITY + 2, array('id' => $id));
     $this->assertTrue(SessionInfo::compare($info1, $info2) < 0, '<');
     $this->assertTrue(SessionInfo::compare($info2, $info1) > 0, '>');
     $this->assertTrue(SessionInfo::compare($info1, $info1) === 0, '==');
 }
Esempio n. 4
0
 public function testConstructor()
 {
     // Set variables
     $this->getBackend();
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $this->provider, 'id' => self::SESSIONID, 'persisted' => true, 'userInfo' => UserInfo::newFromName('UTSysop', false), 'idIsSafe' => true));
     $id = new SessionId($info->getId());
     $logger = new \Psr\Log\NullLogger();
     try {
         new SessionBackend($id, $info, $this->store, $this->store, $logger, 10);
         $this->fail('Expected exception not thrown');
     } catch (\InvalidArgumentException $ex) {
         $this->assertSame("Refusing to create session for unverified user {$info->getUserInfo()}", $ex->getMessage());
     }
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('id' => self::SESSIONID, 'userInfo' => UserInfo::newFromName('UTSysop', true), 'idIsSafe' => true));
     $id = new SessionId($info->getId());
     try {
         new SessionBackend($id, $info, $this->store, $this->store, $logger, 10);
         $this->fail('Expected exception not thrown');
     } catch (\InvalidArgumentException $ex) {
         $this->assertSame('Cannot create session without a provider', $ex->getMessage());
     }
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $this->provider, 'id' => self::SESSIONID, 'persisted' => true, 'userInfo' => UserInfo::newFromName('UTSysop', true), 'idIsSafe' => true));
     $id = new SessionId('!' . $info->getId());
     try {
         new SessionBackend($id, $info, $this->store, $this->store, $logger, 10);
         $this->fail('Expected exception not thrown');
     } catch (\InvalidArgumentException $ex) {
         $this->assertSame('SessionId and SessionInfo don\'t match', $ex->getMessage());
     }
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $this->provider, 'id' => self::SESSIONID, 'persisted' => true, 'userInfo' => UserInfo::newFromName('UTSysop', true), 'idIsSafe' => true));
     $id = new SessionId($info->getId());
     $backend = new SessionBackend($id, $info, $this->store, $this->store, $logger, 10);
     $this->assertSame(self::SESSIONID, $backend->getId());
     $this->assertSame($id, $backend->getSessionId());
     $this->assertSame($this->provider, $backend->getProvider());
     $this->assertInstanceOf('User', $backend->getUser());
     $this->assertSame('UTSysop', $backend->getUser()->getName());
     $this->assertSame($info->wasPersisted(), $backend->isPersistent());
     $this->assertSame($info->wasRemembered(), $backend->shouldRememberUser());
     $this->assertSame($info->forceHTTPS(), $backend->shouldForceHTTPS());
     $expire = time() + 100;
     $this->store->setSessionMeta(self::SESSIONID, array('expires' => $expire), 2);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $this->provider, 'id' => self::SESSIONID, 'persisted' => true, 'forceHTTPS' => true, 'metadata' => array('foo'), 'idIsSafe' => true));
     $id = new SessionId($info->getId());
     $backend = new SessionBackend($id, $info, $this->store, $this->store, $logger, 10);
     $this->assertSame(self::SESSIONID, $backend->getId());
     $this->assertSame($id, $backend->getSessionId());
     $this->assertSame($this->provider, $backend->getProvider());
     $this->assertInstanceOf('User', $backend->getUser());
     $this->assertTrue($backend->getUser()->isAnon());
     $this->assertSame($info->wasPersisted(), $backend->isPersistent());
     $this->assertSame($info->wasRemembered(), $backend->shouldRememberUser());
     $this->assertSame($info->forceHTTPS(), $backend->shouldForceHTTPS());
     $this->assertSame($expire, \TestingAccessWrapper::newFromObject($backend)->expires);
     $this->assertSame(array('foo'), $backend->getProviderMetadata());
 }
 public function testLoadSessionInfoFromStore()
 {
     $manager = $this->getManager();
     $logger = new \TestLogger(true, function ($m) {
         return preg_replace('/^Session \\[\\d+\\]\\w+<(?:null|anon|[+-]:\\d+:\\w+)>\\w+: /', 'Session X: ', $m);
     });
     $manager->setLogger($logger);
     $request = new \FauxRequest();
     // TestingAccessWrapper can't handle methods with reference arguments, sigh.
     $rClass = new \ReflectionClass($manager);
     $rMethod = $rClass->getMethod('loadSessionInfoFromStore');
     $rMethod->setAccessible(true);
     $loadSessionInfoFromStore = function (&$info) use($rMethod, $manager, $request) {
         return $rMethod->invokeArgs($manager, array(&$info, $request));
     };
     $userInfo = UserInfo::newFromName('UTSysop', true);
     $unverifiedUserInfo = UserInfo::newFromName('UTSysop', false);
     $id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
     $metadata = array('userId' => $userInfo->getId(), 'userName' => $userInfo->getName(), 'userToken' => $userInfo->getToken(true), 'provider' => 'Mock');
     $builder = $this->getMockBuilder('MediaWiki\\Session\\SessionProvider')->setMethods(array('__toString', 'mergeMetadata', 'refreshSessionInfo'));
     $provider = $builder->getMockForAbstractClass();
     $provider->setManager($manager);
     $provider->expects($this->any())->method('persistsSessionId')->will($this->returnValue(true));
     $provider->expects($this->any())->method('canChangeUser')->will($this->returnValue(true));
     $provider->expects($this->any())->method('refreshSessionInfo')->will($this->returnValue(true));
     $provider->expects($this->any())->method('__toString')->will($this->returnValue('Mock'));
     $provider->expects($this->any())->method('mergeMetadata')->will($this->returnCallback(function ($a, $b) {
         if ($b === array('Throw')) {
             throw new \UnexpectedValueException('no merge!');
         }
         return array('Merged');
     }));
     $provider2 = $builder->getMockForAbstractClass();
     $provider2->setManager($manager);
     $provider2->expects($this->any())->method('persistsSessionId')->will($this->returnValue(false));
     $provider2->expects($this->any())->method('canChangeUser')->will($this->returnValue(false));
     $provider2->expects($this->any())->method('__toString')->will($this->returnValue('Mock2'));
     $provider2->expects($this->any())->method('refreshSessionInfo')->will($this->returnCallback(function ($info, $request, &$metadata) {
         $metadata['changed'] = true;
         return true;
     }));
     $provider3 = $builder->getMockForAbstractClass();
     $provider3->setManager($manager);
     $provider3->expects($this->any())->method('persistsSessionId')->will($this->returnValue(true));
     $provider3->expects($this->any())->method('canChangeUser')->will($this->returnValue(true));
     $provider3->expects($this->once())->method('refreshSessionInfo')->will($this->returnValue(false));
     $provider3->expects($this->any())->method('__toString')->will($this->returnValue('Mock3'));
     \TestingAccessWrapper::newFromObject($manager)->sessionProviders = array((string) $provider => $provider, (string) $provider2 => $provider2, (string) $provider3 => $provider3);
     // No metadata, basic usage
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'userInfo' => $userInfo));
     $this->assertTrue($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider2, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     // Unverified user, no metadata
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $unverifiedUserInfo));
     $this->assertSame($unverifiedUserInfo, $info->getUserInfo());
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Unverified user provided and no metadata to auth it')), $logger->getBuffer());
     $logger->clearBuffer();
     // No metadata, missing data
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Null provider and no metadata')), $logger->getBuffer());
     $logger->clearBuffer();
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertInstanceOf('MediaWiki\\Session\\UserInfo', $info->getUserInfo());
     $this->assertTrue($info->getUserInfo()->isVerified());
     $this->assertTrue($info->getUserInfo()->isAnon());
     $this->assertFalse($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider2, 'id' => $id));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::INFO, 'Session X: No user provided and provider cannot set user')), $logger->getBuffer());
     $logger->clearBuffer();
     // Incomplete/bad metadata
     $this->store->setRawSession($id, true);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Bad data')), $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->setRawSession($id, array('data' => array()));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Bad data structure')), $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->deleteSession($id);
     $this->store->setRawSession($id, array('metadata' => $metadata));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Bad data structure')), $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->setRawSession($id, array('metadata' => $metadata, 'data' => true));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Bad data structure')), $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->setRawSession($id, array('metadata' => true, 'data' => array()));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Bad data structure')), $logger->getBuffer());
     $logger->clearBuffer();
     foreach ($metadata as $key => $dummy) {
         $tmp = $metadata;
         unset($tmp[$key]);
         $this->store->setRawSession($id, array('metadata' => $tmp, 'data' => array()));
         $this->assertFalse($loadSessionInfoFromStore($info));
         $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Bad metadata')), $logger->getBuffer());
         $logger->clearBuffer();
     }
     // Basic usage with metadata
     $this->store->setRawSession($id, array('metadata' => $metadata, 'data' => array()));
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     // Mismatched provider
     $this->store->setSessionMeta($id, array('provider' => 'Bad') + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Wrong provider, Bad !== Mock')), $logger->getBuffer());
     $logger->clearBuffer();
     // Unknown provider
     $this->store->setSessionMeta($id, array('provider' => 'Bad') + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Unknown provider, Bad')), $logger->getBuffer());
     $logger->clearBuffer();
     // Fill in provider
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     // Bad user metadata
     $this->store->setSessionMeta($id, array('userId' => -1, 'userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::ERROR, 'Session X: Invalid ID')), $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->setSessionMeta($id, array('userId' => 0, 'userName' => '<X>', 'userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::ERROR, 'Session X: Invalid user name')), $logger->getBuffer());
     $logger->clearBuffer();
     // Mismatched user by ID
     $this->store->setSessionMeta($id, array('userId' => $userInfo->getId() + 1, 'userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: User ID mismatch, 2 !== 1')), $logger->getBuffer());
     $logger->clearBuffer();
     // Mismatched user by name
     $this->store->setSessionMeta($id, array('userId' => 0, 'userName' => 'X', 'userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: User name mismatch, X !== UTSysop')), $logger->getBuffer());
     $logger->clearBuffer();
     // ID matches, name doesn't
     $this->store->setSessionMeta($id, array('userId' => $userInfo->getId(), 'userName' => 'X', 'userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: User ID matched but name didn\'t (rename?), X !== UTSysop')), $logger->getBuffer());
     $logger->clearBuffer();
     // Mismatched anon user
     $this->store->setSessionMeta($id, array('userId' => 0, 'userName' => null, 'userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Metadata has an anonymous user, but a non-anon user was provided')), $logger->getBuffer());
     $logger->clearBuffer();
     // Lookup user by ID
     $this->store->setSessionMeta($id, array('userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame($userInfo->getId(), $info->getUserInfo()->getId());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     // Lookup user by name
     $this->store->setSessionMeta($id, array('userId' => 0, 'userName' => 'UTSysop', 'userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame($userInfo->getId(), $info->getUserInfo()->getId());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     // Lookup anonymous user
     $this->store->setSessionMeta($id, array('userId' => 0, 'userName' => null, 'userToken' => null) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->getUserInfo()->isAnon());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     // Unverified user with metadata
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $unverifiedUserInfo));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->getUserInfo()->isVerified());
     $this->assertSame($unverifiedUserInfo->getId(), $info->getUserInfo()->getId());
     $this->assertSame($unverifiedUserInfo->getName(), $info->getUserInfo()->getName());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     // Unverified user with metadata
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $unverifiedUserInfo));
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->getUserInfo()->isVerified());
     $this->assertSame($unverifiedUserInfo->getId(), $info->getUserInfo()->getId());
     $this->assertSame($unverifiedUserInfo->getName(), $info->getUserInfo()->getName());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame(array(), $logger->getBuffer());
     // Wrong token
     $this->store->setSessionMeta($id, array('userToken' => 'Bad') + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: User token mismatch')), $logger->getBuffer());
     $logger->clearBuffer();
     // Provider metadata
     $this->store->setSessionMeta($id, array('provider' => 'Mock2') + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider2, 'id' => $id, 'userInfo' => $userInfo, 'metadata' => array('Info')));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame(array('Info', 'changed' => true), $info->getProviderMetadata());
     $this->assertSame(array(), $logger->getBuffer());
     $this->store->setSessionMeta($id, array('providerMetadata' => array('Saved')) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame(array('Saved'), $info->getProviderMetadata());
     $this->assertSame(array(), $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'metadata' => array('Info')));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame(array('Merged'), $info->getProviderMetadata());
     $this->assertSame(array(), $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'metadata' => array('Throw')));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Metadata merge failed: no merge!')), $logger->getBuffer());
     $logger->clearBuffer();
     // Remember from session
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($info->wasRemembered());
     $this->assertSame(array(), $logger->getBuffer());
     $this->store->setSessionMeta($id, array('remember' => true) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->wasRemembered());
     $this->assertSame(array(), $logger->getBuffer());
     $this->store->setSessionMeta($id, array('remember' => false) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->wasRemembered());
     $this->assertSame(array(), $logger->getBuffer());
     // forceHTTPS from session
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($info->forceHTTPS());
     $this->assertSame(array(), $logger->getBuffer());
     $this->store->setSessionMeta($id, array('forceHTTPS' => true) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->forceHTTPS());
     $this->assertSame(array(), $logger->getBuffer());
     $this->store->setSessionMeta($id, array('forceHTTPS' => false) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'forceHTTPS' => true));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->forceHTTPS());
     $this->assertSame(array(), $logger->getBuffer());
     // "Persist" flag from session
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($info->wasPersisted());
     $this->assertSame(array(), $logger->getBuffer());
     $this->store->setSessionMeta($id, array('persisted' => true) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->wasPersisted());
     $this->assertSame(array(), $logger->getBuffer());
     $this->store->setSessionMeta($id, array('persisted' => false) + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'persisted' => true));
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->wasPersisted());
     $this->assertSame(array(), $logger->getBuffer());
     // Provider refreshSessionInfo() returning false
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider3));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame(array(), $logger->getBuffer());
     // Hook
     $that = $this;
     $called = false;
     $data = array('foo' => 1);
     $this->store->setSession($id, array('metadata' => $metadata, 'data' => $data));
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, array('provider' => $provider, 'id' => $id, 'userInfo' => $userInfo));
     $this->mergeMwGlobalArrayValue('wgHooks', array('SessionCheckInfo' => array(function (&$reason, $i, $r, $m, $d) use($that, $info, $metadata, $data, $request, &$called) {
         $that->assertSame($info->getId(), $i->getId());
         $that->assertSame($info->getProvider(), $i->getProvider());
         $that->assertSame($info->getUserInfo(), $i->getUserInfo());
         $that->assertSame($request, $r);
         $that->assertEquals($metadata, $m);
         $that->assertEquals($data, $d);
         $called = true;
         return false;
     })));
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertTrue($called);
     $this->assertSame(array(array(LogLevel::WARNING, 'Session X: Hook aborted')), $logger->getBuffer());
     $logger->clearBuffer();
 }
 public function testCheckSessionInfo()
 {
     $logger = new \TestLogger(true, function ($m) {
         return preg_replace('/^Session \\[\\d+\\][a-zA-Z0-9_\\\\]+<(?:null|anon|[+-]:\\d+:\\w+)>\\w+: /', 'Session X: ', $m);
     });
     $provider = $this->getProvider();
     $provider->setLogger($logger);
     $user = \User::newFromName('UTSysop');
     $request = $this->getMock('FauxRequest', array('getIP'));
     $request->expects($this->any())->method('getIP')->will($this->returnValue('127.0.0.1'));
     $bp = \BotPassword::newFromUser($user, 'BotPasswordSessionProvider');
     $data = array('provider' => $provider, 'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'userInfo' => UserInfo::newFromUser($user, true), 'persisted' => false, 'metadata' => array('centralId' => $bp->getUserCentralId(), 'appId' => $bp->getAppId(), 'token' => $bp->getToken()));
     $dataMD = $data['metadata'];
     foreach (array_keys($data['metadata']) as $key) {
         $data['metadata'] = $dataMD;
         unset($data['metadata'][$key]);
         $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
         $metadata = $info->getProviderMetadata();
         $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
         $this->assertSame(array(array(LogLevel::INFO, "Session X: Missing metadata: {$key}")), $logger->getBuffer());
         $logger->clearBuffer();
     }
     $data['metadata'] = $dataMD;
     $data['metadata']['appId'] = 'Foobar';
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame(array(array(LogLevel::INFO, "Session X: No BotPassword for {$bp->getUserCentralId()} Foobar")), $logger->getBuffer());
     $logger->clearBuffer();
     $data['metadata'] = $dataMD;
     $data['metadata']['token'] = 'Foobar';
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame(array(array(LogLevel::INFO, 'Session X: BotPassword token check failed')), $logger->getBuffer());
     $logger->clearBuffer();
     $request2 = $this->getMock('FauxRequest', array('getIP'));
     $request2->expects($this->any())->method('getIP')->will($this->returnValue('10.0.0.1'));
     $data['metadata'] = $dataMD;
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request2, $metadata));
     $this->assertSame(array(array(LogLevel::INFO, 'Session X: Restrictions check failed')), $logger->getBuffer());
     $logger->clearBuffer();
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertTrue($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame(array(), $logger->getBuffer());
     $this->assertEquals($dataMD + array('rights' => array('read')), $metadata);
 }
Esempio n. 7
0
 /**
  * @param SessionId $id Session ID object
  * @param SessionInfo $info Session info to populate from
  * @param CachedBagOStuff $store Backend data store
  * @param LoggerInterface $logger
  * @param int $lifetime Session data lifetime in seconds
  */
 public function __construct(SessionId $id, SessionInfo $info, CachedBagOStuff $store, LoggerInterface $logger, $lifetime)
 {
     $phpSessionHandling = \RequestContext::getMain()->getConfig()->get('PHPSessionHandling');
     $this->usePhpSessionHandling = $phpSessionHandling !== 'disable';
     if ($info->getUserInfo() && !$info->getUserInfo()->isVerified()) {
         throw new \InvalidArgumentException("Refusing to create session for unverified user {$info->getUserInfo()}");
     }
     if ($info->getProvider() === null) {
         throw new \InvalidArgumentException('Cannot create session without a provider');
     }
     if ($info->getId() !== $id->getId()) {
         throw new \InvalidArgumentException('SessionId and SessionInfo don\'t match');
     }
     $this->id = $id;
     $this->user = $info->getUserInfo() ? $info->getUserInfo()->getUser() : new User();
     $this->store = $store;
     $this->logger = $logger;
     $this->lifetime = $lifetime;
     $this->provider = $info->getProvider();
     $this->persist = $info->wasPersisted();
     $this->remember = $info->wasRemembered();
     $this->forceHTTPS = $info->forceHTTPS();
     $this->providerMetadata = $info->getProviderMetadata();
     $blob = $store->get(wfMemcKey('MWSession', (string) $this->id));
     if (!is_array($blob) || !isset($blob['metadata']) || !is_array($blob['metadata']) || !isset($blob['data']) || !is_array($blob['data'])) {
         $this->data = [];
         $this->dataDirty = true;
         $this->metaDirty = true;
         $this->logger->debug('SessionBackend "{session}" is unsaved, marking dirty in constructor', ['session' => $this->id]);
     } else {
         $this->data = $blob['data'];
         if (isset($blob['metadata']['loggedOut'])) {
             $this->loggedOut = (int) $blob['metadata']['loggedOut'];
         }
         if (isset($blob['metadata']['expires'])) {
             $this->expires = (int) $blob['metadata']['expires'];
         } else {
             $this->metaDirty = true;
             $this->logger->debug('SessionBackend "{session}" metadata dirty due to missing expiration timestamp', ['session' => $this->id]);
         }
     }
     $this->dataHash = md5(serialize($this->data));
 }
Esempio n. 8
0
 public function testLoadSessionInfoFromStore()
 {
     $manager = $this->getManager();
     $logger = new \TestLogger(true);
     $manager->setLogger($logger);
     $request = new \FauxRequest();
     // TestingAccessWrapper can't handle methods with reference arguments, sigh.
     $rClass = new \ReflectionClass($manager);
     $rMethod = $rClass->getMethod('loadSessionInfoFromStore');
     $rMethod->setAccessible(true);
     $loadSessionInfoFromStore = function (&$info) use($rMethod, $manager, $request) {
         return $rMethod->invokeArgs($manager, [&$info, $request]);
     };
     $userInfo = UserInfo::newFromName('UTSysop', true);
     $unverifiedUserInfo = UserInfo::newFromName('UTSysop', false);
     $id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
     $metadata = ['userId' => $userInfo->getId(), 'userName' => $userInfo->getName(), 'userToken' => $userInfo->getToken(true), 'provider' => 'Mock'];
     $builder = $this->getMockBuilder(SessionProvider::class)->setMethods(['__toString', 'mergeMetadata', 'refreshSessionInfo']);
     $provider = $builder->getMockForAbstractClass();
     $provider->setManager($manager);
     $provider->expects($this->any())->method('persistsSessionId')->will($this->returnValue(true));
     $provider->expects($this->any())->method('canChangeUser')->will($this->returnValue(true));
     $provider->expects($this->any())->method('refreshSessionInfo')->will($this->returnValue(true));
     $provider->expects($this->any())->method('__toString')->will($this->returnValue('Mock'));
     $provider->expects($this->any())->method('mergeMetadata')->will($this->returnCallback(function ($a, $b) {
         if ($b === ['Throw']) {
             throw new MetadataMergeException('no merge!');
         }
         return ['Merged'];
     }));
     $provider2 = $builder->getMockForAbstractClass();
     $provider2->setManager($manager);
     $provider2->expects($this->any())->method('persistsSessionId')->will($this->returnValue(false));
     $provider2->expects($this->any())->method('canChangeUser')->will($this->returnValue(false));
     $provider2->expects($this->any())->method('__toString')->will($this->returnValue('Mock2'));
     $provider2->expects($this->any())->method('refreshSessionInfo')->will($this->returnCallback(function ($info, $request, &$metadata) {
         $metadata['changed'] = true;
         return true;
     }));
     $provider3 = $builder->getMockForAbstractClass();
     $provider3->setManager($manager);
     $provider3->expects($this->any())->method('persistsSessionId')->will($this->returnValue(true));
     $provider3->expects($this->any())->method('canChangeUser')->will($this->returnValue(true));
     $provider3->expects($this->once())->method('refreshSessionInfo')->will($this->returnValue(false));
     $provider3->expects($this->any())->method('__toString')->will($this->returnValue('Mock3'));
     \TestingAccessWrapper::newFromObject($manager)->sessionProviders = [(string) $provider => $provider, (string) $provider2 => $provider2, (string) $provider3 => $provider3];
     // No metadata, basic usage
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'userInfo' => $userInfo]);
     $this->assertTrue($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider2, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     // Unverified user, no metadata
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $unverifiedUserInfo]);
     $this->assertSame($unverifiedUserInfo, $info->getUserInfo());
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Unverified user provided and no metadata to auth it']], $logger->getBuffer());
     $logger->clearBuffer();
     // No metadata, missing data
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Null provider and no metadata']], $logger->getBuffer());
     $logger->clearBuffer();
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertInstanceOf(UserInfo::class, $info->getUserInfo());
     $this->assertTrue($info->getUserInfo()->isVerified());
     $this->assertTrue($info->getUserInfo()->isAnon());
     $this->assertFalse($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider2, 'id' => $id]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::INFO, 'Session "{session}": No user provided and provider cannot set user']], $logger->getBuffer());
     $logger->clearBuffer();
     // Incomplete/bad metadata
     $this->store->setRawSession($id, true);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Bad data']], $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->setRawSession($id, ['data' => []]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Bad data structure']], $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->deleteSession($id);
     $this->store->setRawSession($id, ['metadata' => $metadata]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Bad data structure']], $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->setRawSession($id, ['metadata' => $metadata, 'data' => true]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Bad data structure']], $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->setRawSession($id, ['metadata' => true, 'data' => []]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Bad data structure']], $logger->getBuffer());
     $logger->clearBuffer();
     foreach ($metadata as $key => $dummy) {
         $tmp = $metadata;
         unset($tmp[$key]);
         $this->store->setRawSession($id, ['metadata' => $tmp, 'data' => []]);
         $this->assertFalse($loadSessionInfoFromStore($info));
         $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Bad metadata']], $logger->getBuffer());
         $logger->clearBuffer();
     }
     // Basic usage with metadata
     $this->store->setRawSession($id, ['metadata' => $metadata, 'data' => []]);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     // Mismatched provider
     $this->store->setSessionMeta($id, ['provider' => 'Bad'] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Wrong provider Bad !== Mock']], $logger->getBuffer());
     $logger->clearBuffer();
     // Unknown provider
     $this->store->setSessionMeta($id, ['provider' => 'Bad'] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Unknown provider Bad']], $logger->getBuffer());
     $logger->clearBuffer();
     // Fill in provider
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     // Bad user metadata
     $this->store->setSessionMeta($id, ['userId' => -1, 'userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::ERROR, 'Session "{session}": {exception}']], $logger->getBuffer());
     $logger->clearBuffer();
     $this->store->setSessionMeta($id, ['userId' => 0, 'userName' => '<X>', 'userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::ERROR, 'Session "{session}": {exception}']], $logger->getBuffer());
     $logger->clearBuffer();
     // Mismatched user by ID
     $this->store->setSessionMeta($id, ['userId' => $userInfo->getId() + 1, 'userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": User ID mismatch, {uid_a} !== {uid_b}']], $logger->getBuffer());
     $logger->clearBuffer();
     // Mismatched user by name
     $this->store->setSessionMeta($id, ['userId' => 0, 'userName' => 'X', 'userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": User name mismatch, {uname_a} !== {uname_b}']], $logger->getBuffer());
     $logger->clearBuffer();
     // ID matches, name doesn't
     $this->store->setSessionMeta($id, ['userId' => $userInfo->getId(), 'userName' => 'X', 'userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": User ID matched but name didn\'t (rename?), {uname_a} !== {uname_b}']], $logger->getBuffer());
     $logger->clearBuffer();
     // Mismatched anon user
     $this->store->setSessionMeta($id, ['userId' => 0, 'userName' => null, 'userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Metadata has an anonymous user, ' . 'but a non-anon user was provided']], $logger->getBuffer());
     $logger->clearBuffer();
     // Lookup user by ID
     $this->store->setSessionMeta($id, ['userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame($userInfo->getId(), $info->getUserInfo()->getId());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     // Lookup user by name
     $this->store->setSessionMeta($id, ['userId' => 0, 'userName' => 'UTSysop', 'userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame($userInfo->getId(), $info->getUserInfo()->getId());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     // Lookup anonymous user
     $this->store->setSessionMeta($id, ['userId' => 0, 'userName' => null, 'userToken' => null] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->getUserInfo()->isAnon());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     // Unverified user with metadata
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $unverifiedUserInfo]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->getUserInfo()->isVerified());
     $this->assertSame($unverifiedUserInfo->getId(), $info->getUserInfo()->getId());
     $this->assertSame($unverifiedUserInfo->getName(), $info->getUserInfo()->getName());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     // Unverified user with metadata
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $unverifiedUserInfo]);
     $this->assertFalse($info->isIdSafe(), 'sanity check');
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->getUserInfo()->isVerified());
     $this->assertSame($unverifiedUserInfo->getId(), $info->getUserInfo()->getId());
     $this->assertSame($unverifiedUserInfo->getName(), $info->getUserInfo()->getName());
     $this->assertTrue($info->isIdSafe());
     $this->assertSame([], $logger->getBuffer());
     // Wrong token
     $this->store->setSessionMeta($id, ['userToken' => 'Bad'] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": User token mismatch']], $logger->getBuffer());
     $logger->clearBuffer();
     // Provider metadata
     $this->store->setSessionMeta($id, ['provider' => 'Mock2'] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider2, 'id' => $id, 'userInfo' => $userInfo, 'metadata' => ['Info']]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame(['Info', 'changed' => true], $info->getProviderMetadata());
     $this->assertSame([], $logger->getBuffer());
     $this->store->setSessionMeta($id, ['providerMetadata' => ['Saved']] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame(['Saved'], $info->getProviderMetadata());
     $this->assertSame([], $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'metadata' => ['Info']]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertSame(['Merged'], $info->getProviderMetadata());
     $this->assertSame([], $logger->getBuffer());
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'metadata' => ['Throw']]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Metadata merge failed: {exception}']], $logger->getBuffer());
     $logger->clearBuffer();
     // Remember from session
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($info->wasRemembered());
     $this->assertSame([], $logger->getBuffer());
     $this->store->setSessionMeta($id, ['remember' => true] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->wasRemembered());
     $this->assertSame([], $logger->getBuffer());
     $this->store->setSessionMeta($id, ['remember' => false] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->wasRemembered());
     $this->assertSame([], $logger->getBuffer());
     // forceHTTPS from session
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($info->forceHTTPS());
     $this->assertSame([], $logger->getBuffer());
     $this->store->setSessionMeta($id, ['forceHTTPS' => true] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->forceHTTPS());
     $this->assertSame([], $logger->getBuffer());
     $this->store->setSessionMeta($id, ['forceHTTPS' => false] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'forceHTTPS' => true]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->forceHTTPS());
     $this->assertSame([], $logger->getBuffer());
     // "Persist" flag from session
     $this->store->setSessionMeta($id, $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($info->wasPersisted());
     $this->assertSame([], $logger->getBuffer());
     $this->store->setSessionMeta($id, ['persisted' => true] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->wasPersisted());
     $this->assertSame([], $logger->getBuffer());
     $this->store->setSessionMeta($id, ['persisted' => false] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'persisted' => true]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertTrue($info->wasPersisted());
     $this->assertSame([], $logger->getBuffer());
     // Provider refreshSessionInfo() returning false
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider3]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertSame([], $logger->getBuffer());
     // Hook
     $called = false;
     $data = ['foo' => 1];
     $this->store->setSession($id, ['metadata' => $metadata, 'data' => $data]);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo]);
     $this->mergeMwGlobalArrayValue('wgHooks', ['SessionCheckInfo' => [function (&$reason, $i, $r, $m, $d) use($info, $metadata, $data, $request, &$called) {
         $this->assertSame($info->getId(), $i->getId());
         $this->assertSame($info->getProvider(), $i->getProvider());
         $this->assertSame($info->getUserInfo(), $i->getUserInfo());
         $this->assertSame($request, $r);
         $this->assertEquals($metadata, $m);
         $this->assertEquals($data, $d);
         $called = true;
         return false;
     }]]);
     $this->assertFalse($loadSessionInfoFromStore($info));
     $this->assertTrue($called);
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": Hook aborted']], $logger->getBuffer());
     $logger->clearBuffer();
     $this->mergeMwGlobalArrayValue('wgHooks', ['SessionCheckInfo' => []]);
     // forceUse deletes bad backend data
     $this->store->setSessionMeta($id, ['userToken' => 'Bad'] + $metadata);
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, ['provider' => $provider, 'id' => $id, 'userInfo' => $userInfo, 'forceUse' => true]);
     $this->assertTrue($loadSessionInfoFromStore($info));
     $this->assertFalse($this->store->getSession($id));
     $this->assertSame([[LogLevel::WARNING, 'Session "{session}": User token mismatch']], $logger->getBuffer());
     $logger->clearBuffer();
 }
Esempio n. 9
0
 /**
  * Create a Session corresponding to the passed SessionInfo
  * @private For use by a SessionProvider that needs to specially create its
  *  own Session. Most session providers won't need this.
  * @param SessionInfo $info
  * @param WebRequest $request
  * @return Session
  */
 public function getSessionFromInfo(SessionInfo $info, WebRequest $request)
 {
     // @codeCoverageIgnoreStart
     if (defined('MW_NO_SESSION')) {
         if (MW_NO_SESSION === 'warn') {
             // Undocumented safety case for converting existing entry points
             $this->logger->error('Sessions are supposed to be disabled for this entry point', ['exception' => new \BadMethodCallException('Sessions are disabled for this entry point')]);
         } else {
             throw new \BadMethodCallException('Sessions are disabled for this entry point');
         }
     }
     // @codeCoverageIgnoreEnd
     $id = $info->getId();
     if (!isset($this->allSessionBackends[$id])) {
         if (!isset($this->allSessionIds[$id])) {
             $this->allSessionIds[$id] = new SessionId($id);
         }
         $backend = new SessionBackend($this->allSessionIds[$id], $info, $this->store, $this->logger, $this->config->get('ObjectCacheSessionExpiry'));
         $this->allSessionBackends[$id] = $backend;
         $delay = $backend->delaySave();
     } else {
         $backend = $this->allSessionBackends[$id];
         $delay = $backend->delaySave();
         if ($info->wasPersisted()) {
             $backend->persist();
         }
         if ($info->wasRemembered()) {
             $backend->setRememberUser(true);
         }
     }
     $request->setSessionId($backend->getSessionId());
     $session = $backend->getSession($request);
     if (!$info->isIdSafe()) {
         $session->resetId();
     }
     \Wikimedia\ScopedCallback::consume($delay);
     return $session;
 }
 public function testCheckSessionInfo()
 {
     $logger = new \TestLogger(true);
     $provider = $this->getProvider();
     $provider->setLogger($logger);
     $user = static::getTestSysop()->getUser();
     $request = $this->getMock('FauxRequest', ['getIP']);
     $request->expects($this->any())->method('getIP')->will($this->returnValue('127.0.0.1'));
     $bp = \BotPassword::newFromUser($user, 'BotPasswordSessionProvider');
     $data = ['provider' => $provider, 'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'userInfo' => UserInfo::newFromUser($user, true), 'persisted' => false, 'metadata' => ['centralId' => $bp->getUserCentralId(), 'appId' => $bp->getAppId(), 'token' => $bp->getToken()]];
     $dataMD = $data['metadata'];
     foreach (array_keys($data['metadata']) as $key) {
         $data['metadata'] = $dataMD;
         unset($data['metadata'][$key]);
         $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
         $metadata = $info->getProviderMetadata();
         $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
         $this->assertSame([[LogLevel::INFO, 'Session "{session}": Missing metadata: {missing}']], $logger->getBuffer());
         $logger->clearBuffer();
     }
     $data['metadata'] = $dataMD;
     $data['metadata']['appId'] = 'Foobar';
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame([[LogLevel::INFO, 'Session "{session}": No BotPassword for {centralId} {appId}']], $logger->getBuffer());
     $logger->clearBuffer();
     $data['metadata'] = $dataMD;
     $data['metadata']['token'] = 'Foobar';
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame([[LogLevel::INFO, 'Session "{session}": BotPassword token check failed']], $logger->getBuffer());
     $logger->clearBuffer();
     $request2 = $this->getMock('FauxRequest', ['getIP']);
     $request2->expects($this->any())->method('getIP')->will($this->returnValue('10.0.0.1'));
     $data['metadata'] = $dataMD;
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertFalse($provider->refreshSessionInfo($info, $request2, $metadata));
     $this->assertSame([[LogLevel::INFO, 'Session "{session}": Restrictions check failed']], $logger->getBuffer());
     $logger->clearBuffer();
     $info = new SessionInfo(SessionInfo::MIN_PRIORITY, $data);
     $metadata = $info->getProviderMetadata();
     $this->assertTrue($provider->refreshSessionInfo($info, $request, $metadata));
     $this->assertSame([], $logger->getBuffer());
     $this->assertEquals($dataMD + ['rights' => ['read']], $metadata);
 }