$this->assertTrue( SessionManager::validateSessionId( $id ), "Generated ID: $id" );
}
- public function testAutoCreateUser() {
- global $wgGroupPermissions, $wgDisableAuthManager;
-
- if ( !$wgDisableAuthManager ) {
- $this->markTestSkipped( 'AuthManager is not disabled' );
- }
-
- \ObjectCache::$instances[__METHOD__] = new TestBagOStuff();
- $this->setMwGlobals( [ 'wgMainCacheType' => __METHOD__ ] );
- $this->setMwGlobals( [
- 'wgAuth' => new AuthPlugin,
- ] );
-
- $this->stashMwGlobals( [ '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 );
- 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( [], $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( [
- [ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
- ], $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( [
- [
- 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( [
- [ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
- ], $logger->getBuffer() );
- $logger->clearBuffer();
-
- // Test account-creation block
- $anon = new User;
- $block = new \Block( [
- 'address' => $anon->getName(),
- 'user' => $id,
- 'reason' => __METHOD__,
- 'expiry' => time() + 100500,
- 'createAccount' => true,
- ] );
- $block->insert();
- $this->assertInstanceOf( 'Block', $anon->isBlockedFromCreateAccount(), 'sanity check' );
- $reset2 = new \ScopedCallback( [ $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( [
- [ 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( [
- [ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
- ], $logger->getBuffer() );
- $logger->clearBuffer();
-
- // Test prevention by AuthPlugin
- global $wgAuth;
- $oldWgAuth = $wgAuth;
- $mockWgAuth = $this->getMock( 'AuthPlugin', [ 'autoCreate' ] );
- $mockWgAuth->expects( $this->once() )->method( 'autoCreate' )
- ->will( $this->returnValue( false ) );
- $this->setMwGlobals( [
- '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( [
- 'wgAuth' => $oldWgAuth,
- ] );
- $session->clear();
- $this->assertSame( [
- [ LogLevel::DEBUG, 'denied by AuthPlugin' ],
- ], $logger->getBuffer() );
- $logger->clearBuffer();
-
- // Test prevention by wfReadOnly()
- $this->setMwGlobals( [
- '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( [
- 'wgReadOnly' => false,
- ] );
- $session->clear();
- $this->assertSame( [
- [ 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( [
- [ 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( [
- [ LogLevel::DEBUG, 'Invalid username, blacklisting' ],
- ], $logger->getBuffer() );
- $logger->clearBuffer();
-
- // Test AbortAutoAccount hook
- $mock = $this->getMock( __CLASS__, [ 'onAbortAutoAccount' ] );
- $mock->expects( $this->once() )->method( 'onAbortAutoAccount' )
- ->will( $this->returnCallback( function ( User $user, &$msg ) {
- $msg = 'No way!';
- return false;
- } ) );
- $this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [ $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', [ 'AbortAutoAccount' => [] ] );
- $session->clear();
- $this->assertSame( [
- [ LogLevel::DEBUG, 'denied by hook: No way!' ],
- ], $logger->getBuffer() );
- $logger->clearBuffer();
-
- // Test AbortAutoAccount hook screwing up the name
- $mock = $this->getMock( 'stdClass', [ 'onAbortAutoAccount' ] );
- $mock->expects( $this->once() )->method( 'onAbortAutoAccount' )
- ->will( $this->returnCallback( function ( User $user ) {
- $user->setName( 'UTDoesNotExistEither' );
- } ) );
- $this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [ $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', [ 'AbortAutoAccount' => [] ] );
- $session->clear();
- $this->assertSame( [], $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( [
- [ 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 ) {
- $this->assertNotEquals( 0, $user->getId() );
- $this->assertSame( 'UTSessionAutoCreate4', $user->getName() );
- $this->assertEquals(
- $user->getId(), User::idFromName( 'UTSessionAutoCreate4', User::READ_LATEST )
- );
- return true;
- } );
- $mock = $this->getMock( 'stdClass',
- [ 'onAuthPluginAutoCreate', 'onLocalUserCreated' ] );
- $mock->expects( $this->once() )->method( 'onAuthPluginAutoCreate' )
- ->with( $cb );
- $mock->expects( $this->once() )->method( 'onLocalUserCreated' )
- ->with( $cb, $this->identicalTo( true ) );
- $this->mergeMwGlobalArrayValue( 'wgHooks', [
- 'AuthPluginAutoCreate' => [ $mock ],
- 'LocalUserCreated' => [ $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', [
- 'AuthPluginAutoCreate' => [],
- 'LocalUserCreated' => [],
- ] );
- $this->assertSame( [
- [ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
- ], $logger->getBuffer() );
- $logger->clearBuffer();
- }
-
- public function onAbortAutoAccount( User $user, &$msg ) {
- }
-
public function testPreventSessionsForUser() {
$manager = $this->getManager();