]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blobdiff - tests/phpunit/includes/session/BotPasswordSessionProviderTest.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / tests / phpunit / includes / session / BotPasswordSessionProviderTest.php
diff --git a/tests/phpunit/includes/session/BotPasswordSessionProviderTest.php b/tests/phpunit/includes/session/BotPasswordSessionProviderTest.php
new file mode 100644 (file)
index 0000000..90550d2
--- /dev/null
@@ -0,0 +1,340 @@
+<?php
+
+namespace MediaWiki\Session;
+
+use Psr\Log\LogLevel;
+use MediaWikiTestCase;
+use Wikimedia\TestingAccessWrapper;
+
+/**
+ * @group Session
+ * @group Database
+ * @covers MediaWiki\Session\BotPasswordSessionProvider
+ */
+class BotPasswordSessionProviderTest extends MediaWikiTestCase {
+
+       private $config;
+
+       private function getProvider( $name = null, $prefix = null ) {
+               global $wgSessionProviders;
+
+               $params = [
+                       'priority' => 40,
+                       'sessionCookieName' => $name,
+                       'sessionCookieOptions' => [],
+               ];
+               if ( $prefix !== null ) {
+                       $params['sessionCookieOptions']['prefix'] = $prefix;
+               }
+
+               if ( !$this->config ) {
+                       $this->config = new \HashConfig( [
+                               'CookiePrefix' => 'wgCookiePrefix',
+                               'EnableBotPasswords' => true,
+                               'BotPasswordsDatabase' => false,
+                               'SessionProviders' => $wgSessionProviders + [
+                                       BotPasswordSessionProvider::class => [
+                                               'class' => BotPasswordSessionProvider::class,
+                                               'args' => [ $params ],
+                                       ]
+                               ],
+                       ] );
+               }
+               $manager = new SessionManager( [
+                       'config' => new \MultiConfig( [ $this->config, \RequestContext::getMain()->getConfig() ] ),
+                       'logger' => new \Psr\Log\NullLogger,
+                       'store' => new TestBagOStuff,
+               ] );
+
+               return $manager->getProvider( BotPasswordSessionProvider::class );
+       }
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( [
+                       'wgEnableBotPasswords' => true,
+                       'wgBotPasswordsDatabase' => false,
+                       'wgCentralIdLookupProvider' => 'local',
+                       'wgGrantPermissions' => [
+                               'test' => [ 'read' => true ],
+                       ],
+               ] );
+       }
+
+       public function addDBDataOnce() {
+               $passwordFactory = new \PasswordFactory();
+               $passwordFactory->init( \RequestContext::getMain()->getConfig() );
+               $passwordHash = $passwordFactory->newFromPlaintext( 'foobaz' );
+
+               $sysop = static::getTestSysop()->getUser();
+               $userId = \CentralIdLookup::factory( 'local' )->centralIdFromName( $sysop->getName() );
+
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->delete(
+                       'bot_passwords',
+                       [ 'bp_user' => $userId, 'bp_app_id' => 'BotPasswordSessionProvider' ],
+                       __METHOD__
+               );
+               $dbw->insert(
+                       'bot_passwords',
+                       [
+                               'bp_user' => $userId,
+                               'bp_app_id' => 'BotPasswordSessionProvider',
+                               'bp_password' => $passwordHash->toString(),
+                               'bp_token' => 'token!',
+                               'bp_restrictions' => '{"IPAddresses":["127.0.0.0/8"]}',
+                               'bp_grants' => '["test"]',
+                       ],
+                       __METHOD__
+               );
+       }
+
+       public function testConstructor() {
+               try {
+                       $provider = new BotPasswordSessionProvider();
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( \InvalidArgumentException $ex ) {
+                       $this->assertSame(
+                               'MediaWiki\\Session\\BotPasswordSessionProvider::__construct: priority must be specified',
+                               $ex->getMessage()
+                       );
+               }
+
+               try {
+                       $provider = new BotPasswordSessionProvider( [
+                               'priority' => SessionInfo::MIN_PRIORITY - 1
+                       ] );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( \InvalidArgumentException $ex ) {
+                       $this->assertSame(
+                               'MediaWiki\\Session\\BotPasswordSessionProvider::__construct: Invalid priority',
+                               $ex->getMessage()
+                       );
+               }
+
+               try {
+                       $provider = new BotPasswordSessionProvider( [
+                               'priority' => SessionInfo::MAX_PRIORITY + 1
+                       ] );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( \InvalidArgumentException $ex ) {
+                       $this->assertSame(
+                               'MediaWiki\\Session\\BotPasswordSessionProvider::__construct: Invalid priority',
+                               $ex->getMessage()
+                       );
+               }
+
+               $provider = new BotPasswordSessionProvider( [
+                       'priority' => 40
+               ] );
+               $priv = TestingAccessWrapper::newFromObject( $provider );
+               $this->assertSame( 40, $priv->priority );
+               $this->assertSame( '_BPsession', $priv->sessionCookieName );
+               $this->assertSame( [], $priv->sessionCookieOptions );
+
+               $provider = new BotPasswordSessionProvider( [
+                       'priority' => 40,
+                       'sessionCookieName' => null,
+               ] );
+               $priv = TestingAccessWrapper::newFromObject( $provider );
+               $this->assertSame( '_BPsession', $priv->sessionCookieName );
+
+               $provider = new BotPasswordSessionProvider( [
+                       'priority' => 40,
+                       'sessionCookieName' => 'Foo',
+                       'sessionCookieOptions' => [ 'Bar' ],
+               ] );
+               $priv = TestingAccessWrapper::newFromObject( $provider );
+               $this->assertSame( 'Foo', $priv->sessionCookieName );
+               $this->assertSame( [ 'Bar' ], $priv->sessionCookieOptions );
+       }
+
+       public function testBasics() {
+               $provider = $this->getProvider();
+
+               $this->assertTrue( $provider->persistsSessionId() );
+               $this->assertFalse( $provider->canChangeUser() );
+
+               $this->assertNull( $provider->newSessionInfo() );
+               $this->assertNull( $provider->newSessionInfo( 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ) );
+       }
+
+       public function testProvideSessionInfo() {
+               $provider = $this->getProvider();
+               $request = new \FauxRequest;
+               $request->setCookie( '_BPsession', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'wgCookiePrefix' );
+
+               if ( !defined( 'MW_API' ) ) {
+                       $this->assertNull( $provider->provideSessionInfo( $request ) );
+                       define( 'MW_API', 1 );
+               }
+
+               $info = $provider->provideSessionInfo( $request );
+               $this->assertInstanceOf( SessionInfo::class, $info );
+               $this->assertSame( 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $info->getId() );
+
+               $this->config->set( 'EnableBotPasswords', false );
+               $this->assertNull( $provider->provideSessionInfo( $request ) );
+               $this->config->set( 'EnableBotPasswords', true );
+
+               $this->assertNull( $provider->provideSessionInfo( new \FauxRequest ) );
+       }
+
+       public function testNewSessionInfoForRequest() {
+               $provider = $this->getProvider();
+               $user = static::getTestSysop()->getUser();
+               $request = $this->getMockBuilder( 'FauxRequest' )
+                       ->setMethods( [ 'getIP' ] )->getMock();
+               $request->expects( $this->any() )->method( 'getIP' )
+                       ->will( $this->returnValue( '127.0.0.1' ) );
+               $bp = \BotPassword::newFromUser( $user, 'BotPasswordSessionProvider' );
+
+               $session = $provider->newSessionForRequest( $user, $bp, $request );
+               $this->assertInstanceOf( Session::class, $session );
+
+               $this->assertEquals( $session->getId(), $request->getSession()->getId() );
+               $this->assertEquals( $user->getName(), $session->getUser()->getName() );
+
+               $this->assertEquals( [
+                       'centralId' => $bp->getUserCentralId(),
+                       'appId' => $bp->getAppId(),
+                       'token' => $bp->getToken(),
+                       'rights' => [ 'read' ],
+               ], $session->getProviderMetadata() );
+
+               $this->assertEquals( [ 'read' ], $session->getAllowedUserRights() );
+       }
+
+       public function testCheckSessionInfo() {
+               $logger = new \TestLogger( true );
+               $provider = $this->getProvider();
+               $provider->setLogger( $logger );
+
+               $user = static::getTestSysop()->getUser();
+               $request = $this->getMockBuilder( 'FauxRequest' )
+                       ->setMethods( [ 'getIP' ] )->getMock();
+               $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->getMockBuilder( 'FauxRequest' )
+                       ->setMethods( [ 'getIP' ] )->getMock();
+               $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 );
+       }
+
+       public function testGetAllowedUserRights() {
+               $logger = new \TestLogger( true );
+               $provider = $this->getProvider();
+               $provider->setLogger( $logger );
+
+               $backend = TestUtils::getDummySessionBackend();
+               $backendPriv = TestingAccessWrapper::newFromObject( $backend );
+
+               try {
+                       $provider->getAllowedUserRights( $backend );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( \InvalidArgumentException $ex ) {
+                       $this->assertSame( 'Backend\'s provider isn\'t $this', $ex->getMessage() );
+               }
+
+               $backendPriv->provider = $provider;
+               $backendPriv->providerMetadata = [ 'rights' => [ 'foo', 'bar', 'baz' ] ];
+               $this->assertSame( [ 'foo', 'bar', 'baz' ], $provider->getAllowedUserRights( $backend ) );
+               $this->assertSame( [], $logger->getBuffer() );
+
+               $backendPriv->providerMetadata = [ 'foo' => 'bar' ];
+               $this->assertSame( [], $provider->getAllowedUserRights( $backend ) );
+               $this->assertSame( [
+                       [
+                               LogLevel::DEBUG,
+                               'MediaWiki\\Session\\BotPasswordSessionProvider::getAllowedUserRights: ' .
+                                       'No provider metadata, returning no rights allowed'
+                       ]
+               ], $logger->getBuffer() );
+               $logger->clearBuffer();
+
+               $backendPriv->providerMetadata = [ 'rights' => 'bar' ];
+               $this->assertSame( [], $provider->getAllowedUserRights( $backend ) );
+               $this->assertSame( [
+                       [
+                               LogLevel::DEBUG,
+                               'MediaWiki\\Session\\BotPasswordSessionProvider::getAllowedUserRights: ' .
+                                       'No provider metadata, returning no rights allowed'
+                       ]
+               ], $logger->getBuffer() );
+               $logger->clearBuffer();
+
+               $backendPriv->providerMetadata = null;
+               $this->assertSame( [], $provider->getAllowedUserRights( $backend ) );
+               $this->assertSame( [
+                       [
+                               LogLevel::DEBUG,
+                               'MediaWiki\\Session\\BotPasswordSessionProvider::getAllowedUserRights: ' .
+                                       'No provider metadata, returning no rights allowed'
+                       ]
+               ], $logger->getBuffer() );
+               $logger->clearBuffer();
+       }
+}