public function testGetGlobalSession() { $context = \RequestContext::getMain(); if (!PHPSessionHandler::isInstalled()) { PHPSessionHandler::install(SessionManager::singleton()); } $rProp = new \ReflectionProperty(PHPSessionHandler::class, 'instance'); $rProp->setAccessible(true); $handler = \TestingAccessWrapper::newFromObject($rProp->getValue()); $oldEnable = $handler->enable; $reset[] = new \Wikimedia\ScopedCallback(function () use($handler, $oldEnable) { if ($handler->enable) { session_write_close(); } $handler->enable = $oldEnable; }); $reset[] = TestUtils::setSessionManagerSingleton($this->getManager()); $handler->enable = true; $request = new \FauxRequest(); $context->setRequest($request); $id = $request->getSession()->getId(); session_id(''); $session = SessionManager::getGlobalSession(); $this->assertSame($id, $session->getId()); session_id('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); $session = SessionManager::getGlobalSession(); $this->assertSame('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', $session->getId()); $this->assertSame('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', $request->getSession()->getId()); session_write_close(); $handler->enable = false; $request = new \FauxRequest(); $context->setRequest($request); $id = $request->getSession()->getId(); session_id(''); $session = SessionManager::getGlobalSession(); $this->assertSame($id, $session->getId()); session_id('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); $session = SessionManager::getGlobalSession(); $this->assertSame($id, $session->getId()); $this->assertSame($id, $request->getSession()->getId()); }
/** * Setup SessionManager with a mock session provider * @param bool|null $canChangeUser If non-null, canChangeUser will be mocked to return this * @param array $methods Additional methods to mock * @return array (MediaWiki\Session\SessionProvider, ScopedCallback) */ protected function getMockSessionProvider($canChangeUser = null, array $methods = []) { if (!$this->config) { $this->config = new \HashConfig(); $this->initializeConfig(); } $this->config->set('ObjectCacheSessionExpiry', 100); $methods[] = '__toString'; $methods[] = 'describe'; if ($canChangeUser !== null) { $methods[] = 'canChangeUser'; } $provider = $this->getMockBuilder('DummySessionProvider')->setMethods($methods)->getMock(); $provider->expects($this->any())->method('__toString')->will($this->returnValue('MockSessionProvider')); $provider->expects($this->any())->method('describe')->will($this->returnValue('MockSessionProvider sessions')); if ($canChangeUser !== null) { $provider->expects($this->any())->method('canChangeUser')->will($this->returnValue($canChangeUser)); } $this->config->set('SessionProviders', [['factory' => function () use($provider) { return $provider; }]]); $manager = new \MediaWiki\Session\SessionManager(['config' => $this->config, 'logger' => new \Psr\Log\NullLogger(), 'store' => new \HashBagOStuff()]); \TestingAccessWrapper::newFromObject($manager)->getProvider((string) $provider); $reset = \MediaWiki\Session\TestUtils::setSessionManagerSingleton($manager); if ($this->request) { $manager->getSessionForRequest($this->request); } return [$provider, $reset]; }
public function testAutoCreateUser() { global $wgGroupPermissions; $that = $this; \ObjectCache::$instances[__METHOD__] = new \HashBagOStuff(); $this->setMwGlobals(array('wgMainCacheType' => __METHOD__)); $this->stashMwGlobals(array('wgGroupPermissions')); $wgGroupPermissions['*']['createaccount'] = true; $wgGroupPermissions['*']['autocreateaccount'] = false; // Replace the global singleton with one configured for testing $manager = $this->getManager(); $reset = TestUtils::setSessionManagerSingleton($manager); $logger = new \TestLogger(true, function ($m) { if (substr($m, 0, 15) === 'SessionBackend ') { // Don't care. return null; } $m = str_replace('MediaWiki\\Session\\SessionManager::autoCreateUser: '******'', $m); $m = preg_replace('/ - from: .*$/', ' - from: XXX', $m); return $m; }); $manager->setLogger($logger); $session = SessionManager::getGlobalSession(); // Can't create an already-existing user $user = User::newFromName('UTSysop'); $id = $user->getId(); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame($id, $user->getId()); $this->assertSame('UTSysop', $user->getName()); $this->assertSame(array(), $logger->getBuffer()); $logger->clearBuffer(); // Sanity check that creation works at all $user = User::newFromName('UTSessionAutoCreate1'); $this->assertSame(0, $user->getId(), 'sanity check'); $this->assertTrue($manager->autoCreateUser($user)); $this->assertNotEquals(0, $user->getId()); $this->assertSame('UTSessionAutoCreate1', $user->getName()); $this->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate1', User::READ_LATEST)); $this->assertSame(array(array(LogLevel::INFO, 'creating new user (UTSessionAutoCreate1) - from: XXX')), $logger->getBuffer()); $logger->clearBuffer(); // Check lack of permissions $wgGroupPermissions['*']['createaccount'] = false; $wgGroupPermissions['*']['autocreateaccount'] = false; $user = User::newFromName('UTDoesNotExist'); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); $session->clear(); $this->assertSame(array(array(LogLevel::DEBUG, 'user is blocked from this wiki, blacklisting')), $logger->getBuffer()); $logger->clearBuffer(); // Check other permission $wgGroupPermissions['*']['createaccount'] = false; $wgGroupPermissions['*']['autocreateaccount'] = true; $user = User::newFromName('UTSessionAutoCreate2'); $this->assertSame(0, $user->getId(), 'sanity check'); $this->assertTrue($manager->autoCreateUser($user)); $this->assertNotEquals(0, $user->getId()); $this->assertSame('UTSessionAutoCreate2', $user->getName()); $this->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate2', User::READ_LATEST)); $this->assertSame(array(array(LogLevel::INFO, 'creating new user (UTSessionAutoCreate2) - from: XXX')), $logger->getBuffer()); $logger->clearBuffer(); // Test account-creation block $anon = new User(); $block = new \Block(array('address' => $anon->getName(), 'user' => $id, 'reason' => __METHOD__, 'expiry' => time() + 100500, 'createAccount' => true)); $block->insert(); $this->assertInstanceOf('Block', $anon->isBlockedFromCreateAccount(), 'sanity check'); $reset2 = new \ScopedCallback(array($block, 'delete')); $user = User::newFromName('UTDoesNotExist'); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); \ScopedCallback::consume($reset2); $session->clear(); $this->assertSame(array(array(LogLevel::DEBUG, 'user is blocked from this wiki, blacklisting')), $logger->getBuffer()); $logger->clearBuffer(); // Sanity check that creation still works $user = User::newFromName('UTSessionAutoCreate3'); $this->assertSame(0, $user->getId(), 'sanity check'); $this->assertTrue($manager->autoCreateUser($user)); $this->assertNotEquals(0, $user->getId()); $this->assertSame('UTSessionAutoCreate3', $user->getName()); $this->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate3', User::READ_LATEST)); $this->assertSame(array(array(LogLevel::INFO, 'creating new user (UTSessionAutoCreate3) - from: XXX')), $logger->getBuffer()); $logger->clearBuffer(); // Test prevention by AuthPlugin global $wgAuth; $oldWgAuth = $wgAuth; $mockWgAuth = $this->getMock('AuthPlugin', array('autoCreate')); $mockWgAuth->expects($this->once())->method('autoCreate')->will($this->returnValue(false)); $this->setMwGlobals(array('wgAuth' => $mockWgAuth)); $user = User::newFromName('UTDoesNotExist'); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); $this->setMwGlobals(array('wgAuth' => $oldWgAuth)); $session->clear(); $this->assertSame(array(array(LogLevel::DEBUG, 'denied by AuthPlugin')), $logger->getBuffer()); $logger->clearBuffer(); // Test prevention by wfReadOnly() $this->setMwGlobals(array('wgReadOnly' => 'Because')); $user = User::newFromName('UTDoesNotExist'); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); $this->setMwGlobals(array('wgReadOnly' => false)); $session->clear(); $this->assertSame(array(array(LogLevel::DEBUG, 'denied by wfReadOnly()')), $logger->getBuffer()); $logger->clearBuffer(); // Test prevention by a previous session $session->set('MWSession::AutoCreateBlacklist', 'test'); $user = User::newFromName('UTDoesNotExist'); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); $session->clear(); $this->assertSame(array(array(LogLevel::DEBUG, 'blacklisted in session (test)')), $logger->getBuffer()); $logger->clearBuffer(); // Test uncreatable name $user = User::newFromName('UTDoesNotExist@'); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist@', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); $session->clear(); $this->assertSame(array(array(LogLevel::DEBUG, 'Invalid username, blacklisting')), $logger->getBuffer()); $logger->clearBuffer(); // Test AbortAutoAccount hook $mock = $this->getMock(__CLASS__, array('onAbortAutoAccount')); $mock->expects($this->once())->method('onAbortAutoAccount')->will($this->returnCallback(function (User $user, &$msg) { $msg = 'No way!'; return false; })); $this->mergeMwGlobalArrayValue('wgHooks', array('AbortAutoAccount' => array($mock))); $user = User::newFromName('UTDoesNotExist'); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); $this->mergeMwGlobalArrayValue('wgHooks', array('AbortAutoAccount' => array())); $session->clear(); $this->assertSame(array(array(LogLevel::DEBUG, 'denied by hook: No way!')), $logger->getBuffer()); $logger->clearBuffer(); // Test AbortAutoAccount hook screwing up the name $mock = $this->getMock('stdClass', array('onAbortAutoAccount')); $mock->expects($this->once())->method('onAbortAutoAccount')->will($this->returnCallback(function (User $user) { $user->setName('UTDoesNotExistEither'); })); $this->mergeMwGlobalArrayValue('wgHooks', array('AbortAutoAccount' => array($mock))); try { $user = User::newFromName('UTDoesNotExist'); $manager->autoCreateUser($user); $this->fail('Expected exception not thrown'); } catch (\UnexpectedValueException $ex) { $this->assertSame('AbortAutoAccount hook tried to change the user name', $ex->getMessage()); } $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist', $user->getName()); $this->assertNotSame('UTDoesNotExistEither', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); $this->assertEquals(0, User::idFromName('UTDoesNotExistEither', User::READ_LATEST)); $this->mergeMwGlobalArrayValue('wgHooks', array('AbortAutoAccount' => array())); $session->clear(); $this->assertSame(array(), $logger->getBuffer()); $logger->clearBuffer(); // Test for "exception backoff" $user = User::newFromName('UTDoesNotExist'); $cache = \ObjectCache::getLocalClusterInstance(); $backoffKey = wfMemcKey('MWSession', 'autocreate-failed', md5($user->getName())); $cache->set($backoffKey, 1, 60 * 10); $this->assertFalse($manager->autoCreateUser($user)); $this->assertSame(0, $user->getId()); $this->assertNotSame('UTDoesNotExist', $user->getName()); $this->assertEquals(0, User::idFromName('UTDoesNotExist', User::READ_LATEST)); $cache->delete($backoffKey); $session->clear(); $this->assertSame(array(array(LogLevel::DEBUG, 'denied by prior creation attempt failures')), $logger->getBuffer()); $logger->clearBuffer(); // Sanity check that creation still works, and test completion hook $cb = $this->callback(function (User $user) use($that) { $that->assertNotEquals(0, $user->getId()); $that->assertSame('UTSessionAutoCreate4', $user->getName()); $that->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate4', User::READ_LATEST)); return true; }); $mock = $this->getMock('stdClass', array('onAuthPluginAutoCreate', 'onLocalUserCreated')); $mock->expects($this->once())->method('onAuthPluginAutoCreate')->with($cb); $mock->expects($this->once())->method('onLocalUserCreated')->with($cb, $this->identicalTo(true)); $this->mergeMwGlobalArrayValue('wgHooks', array('AuthPluginAutoCreate' => array($mock), 'LocalUserCreated' => array($mock))); $user = User::newFromName('UTSessionAutoCreate4'); $this->assertSame(0, $user->getId(), 'sanity check'); $this->assertTrue($manager->autoCreateUser($user)); $this->assertNotEquals(0, $user->getId()); $this->assertSame('UTSessionAutoCreate4', $user->getName()); $this->assertEquals($user->getId(), User::idFromName('UTSessionAutoCreate4', User::READ_LATEST)); $this->mergeMwGlobalArrayValue('wgHooks', array('AuthPluginAutoCreate' => array(), 'LocalUserCreated' => array())); $this->assertSame(array(array(LogLevel::INFO, 'creating new user (UTSessionAutoCreate4) - from: XXX')), $logger->getBuffer()); $logger->clearBuffer(); }
public function testResetIdOfGlobalSession() { if (!PHPSessionHandler::isInstalled()) { PHPSessionHandler::install(SessionManager::singleton()); } if (!PHPSessionHandler::isEnabled()) { $rProp = new \ReflectionProperty('MediaWiki\\Session\\PHPSessionHandler', 'instance'); $rProp->setAccessible(true); $handler = \TestingAccessWrapper::newFromObject($rProp->getValue()); $resetHandler = new \ScopedCallback(function () use($handler) { session_write_close(); $handler->enable = false; }); $handler->enable = true; } $backend = $this->getBackend(User::newFromName('UTSysop')); \TestingAccessWrapper::newFromObject($backend)->usePhpSessionHandling = true; TestUtils::setSessionManagerSingleton($this->manager); $manager = \TestingAccessWrapper::newFromObject($this->manager); $request = \RequestContext::getMain()->getRequest(); $manager->globalSession = $backend->getSession($request); $manager->globalSessionRequest = $request; session_id(self::SESSIONID); \MediaWiki\quietCall('session_start'); $backend->resetId(); $this->assertNotEquals(self::SESSIONID, $backend->getId()); $this->assertSame($backend->getId(), session_id()); session_write_close(); session_id(''); $this->assertNotSame($backend->getId(), session_id(), 'sanity check'); $backend->persist(); $this->assertSame($backend->getId(), session_id()); session_write_close(); }