3 namespace MediaWiki\Session
;
12 * @covers MediaWiki\Session\BotPasswordSessionProvider
14 class BotPasswordSessionProviderTest
extends MediaWikiTestCase
{
18 private function getProvider( $name = null, $prefix = null ) {
19 global $wgSessionProviders;
23 'sessionCookieName' => $name,
24 'sessionCookieOptions' => array(),
26 if ( $prefix !== null ) {
27 $params['sessionCookieOptions']['prefix'] = $prefix;
30 if ( !$this->config
) {
31 $this->config
= new \
HashConfig( array(
32 'CookiePrefix' => 'wgCookiePrefix',
33 'EnableBotPasswords' => true,
34 'BotPasswordsDatabase' => false,
35 'SessionProviders' => $wgSessionProviders +
array(
36 'MediaWiki\\Session\\BotPasswordSessionProvider' => array(
37 'class' => 'MediaWiki\\Session\\BotPasswordSessionProvider',
38 'args' => array( $params ),
43 $manager = new SessionManager( array(
44 'config' => new \
MultiConfig( array( $this->config
, \RequestContext
::getMain()->getConfig() ) ),
45 'logger' => new \Psr\Log\NullLogger
,
46 'store' => new TestBagOStuff
,
49 return $manager->getProvider( 'MediaWiki\\Session\\BotPasswordSessionProvider' );
52 protected function setUp() {
55 $this->setMwGlobals( array(
56 'wgEnableBotPasswords' => true,
57 'wgBotPasswordsDatabase' => false,
58 'wgCentralIdLookupProvider' => 'local',
59 'wgGrantPermissions' => array(
60 'test' => array( 'read' => true ),
65 public function addDBData() {
66 $passwordFactory = new \
PasswordFactory();
67 $passwordFactory->init( \RequestContext
::getMain()->getConfig() );
68 // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
69 $passwordFactory->setDefaultType( 'A' );
70 $pwhash = $passwordFactory->newFromPlaintext( 'foobaz' );
72 $userId = \CentralIdLookup
::factory( 'local' )->centralIdFromName( 'UTSysop' );
74 $dbw = wfGetDB( DB_MASTER
);
77 array( 'bp_user' => $userId, 'bp_app_id' => 'BotPasswordSessionProvider' ),
84 'bp_app_id' => 'BotPasswordSessionProvider',
85 'bp_password' => $pwhash->toString(),
86 'bp_token' => 'token!',
87 'bp_restrictions' => '{"IPAddresses":["127.0.0.0/8"]}',
88 'bp_grants' => '["test"]',
94 public function testConstructor() {
96 $provider = new BotPasswordSessionProvider();
97 $this->fail( 'Expected exception not thrown' );
98 } catch ( \InvalidArgumentException
$ex ) {
100 'MediaWiki\\Session\\BotPasswordSessionProvider::__construct: priority must be specified',
106 $provider = new BotPasswordSessionProvider( array(
107 'priority' => SessionInfo
::MIN_PRIORITY
- 1
109 $this->fail( 'Expected exception not thrown' );
110 } catch ( \InvalidArgumentException
$ex ) {
112 'MediaWiki\\Session\\BotPasswordSessionProvider::__construct: Invalid priority',
118 $provider = new BotPasswordSessionProvider( array(
119 'priority' => SessionInfo
::MAX_PRIORITY +
1
121 $this->fail( 'Expected exception not thrown' );
122 } catch ( \InvalidArgumentException
$ex ) {
124 'MediaWiki\\Session\\BotPasswordSessionProvider::__construct: Invalid priority',
129 $provider = new BotPasswordSessionProvider( array(
132 $priv = \TestingAccessWrapper
::newFromObject( $provider );
133 $this->assertSame( 40, $priv->priority
);
134 $this->assertSame( '_BPsession', $priv->sessionCookieName
);
135 $this->assertSame( array(), $priv->sessionCookieOptions
);
137 $provider = new BotPasswordSessionProvider( array(
139 'sessionCookieName' => null,
141 $priv = \TestingAccessWrapper
::newFromObject( $provider );
142 $this->assertSame( '_BPsession', $priv->sessionCookieName
);
144 $provider = new BotPasswordSessionProvider( array(
146 'sessionCookieName' => 'Foo',
147 'sessionCookieOptions' => array( 'Bar' ),
149 $priv = \TestingAccessWrapper
::newFromObject( $provider );
150 $this->assertSame( 'Foo', $priv->sessionCookieName
);
151 $this->assertSame( array( 'Bar' ), $priv->sessionCookieOptions
);
154 public function testBasics() {
155 $provider = $this->getProvider();
157 $this->assertTrue( $provider->persistsSessionID() );
158 $this->assertFalse( $provider->canChangeUser() );
160 $this->assertNull( $provider->newSessionInfo() );
161 $this->assertNull( $provider->newSessionInfo( 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' ) );
164 public function testProvideSessionInfo() {
165 $provider = $this->getProvider();
166 $request = new \FauxRequest
;
167 $request->setCookie( '_BPsession', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'wgCookiePrefix' );
169 if ( !defined( 'MW_API' ) ) {
170 $this->assertNull( $provider->provideSessionInfo( $request ) );
171 define( 'MW_API', 1 );
174 $info = $provider->provideSessionInfo( $request );
175 $this->assertInstanceOf( 'MediaWiki\\Session\\SessionInfo', $info );
176 $this->assertSame( 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $info->getId() );
178 $this->config
->set( 'EnableBotPasswords', false );
179 $this->assertNull( $provider->provideSessionInfo( $request ) );
180 $this->config
->set( 'EnableBotPasswords', true );
182 $this->assertNull( $provider->provideSessionInfo( new \FauxRequest
) );
185 public function testNewSessionInfoForRequest() {
186 $provider = $this->getProvider();
187 $user = \User
::newFromName( 'UTSysop' );
188 $request = $this->getMock( 'FauxRequest', array( 'getIP' ) );
189 $request->expects( $this->any() )->method( 'getIP' )
190 ->will( $this->returnValue( '127.0.0.1' ) );
191 $bp = \BotPassword
::newFromUser( $user, 'BotPasswordSessionProvider' );
193 $session = $provider->newSessionForRequest( $user, $bp, $request );
194 $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
196 $this->assertEquals( $session->getId(), $request->getSession()->getId() );
197 $this->assertEquals( $user->getName(), $session->getUser()->getName() );
199 $this->assertEquals( array(
200 'centralId' => $bp->getUserCentralId(),
201 'appId' => $bp->getAppId(),
202 'token' => $bp->getToken(),
203 'rights' => array( 'read' ),
204 ), $session->getProviderMetadata() );
206 $this->assertEquals( array( 'read' ), $session->getAllowedUserRights() );
209 public function testCheckSessionInfo() {
210 $logger = new \
TestLogger( true, function ( $m ) {
212 '/^Session \[\d+\][a-zA-Z0-9_\\\\]+<(?:null|anon|[+-]:\d+:\w+)>\w+: /', 'Session X: ', $m
215 $provider = $this->getProvider();
216 $provider->setLogger( $logger );
218 $user = \User
::newFromName( 'UTSysop' );
219 $request = $this->getMock( 'FauxRequest', array( 'getIP' ) );
220 $request->expects( $this->any() )->method( 'getIP' )
221 ->will( $this->returnValue( '127.0.0.1' ) );
222 $bp = \BotPassword
::newFromUser( $user, 'BotPasswordSessionProvider' );
225 'provider' => $provider,
226 'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
227 'userInfo' => UserInfo
::newFromUser( $user, true ),
228 'persisted' => false,
230 'centralId' => $bp->getUserCentralId(),
231 'appId' => $bp->getAppId(),
232 'token' => $bp->getToken(),
235 $dataMD = $data['metadata'];
237 foreach ( array_keys( $data['metadata'] ) as $key ) {
238 $data['metadata'] = $dataMD;
239 unset( $data['metadata'][$key] );
240 $info = new SessionInfo( SessionInfo
::MIN_PRIORITY
, $data );
241 $metadata = $info->getProviderMetadata();
243 $this->assertFalse( $provider->refreshSessionInfo( $info, $request, $metadata ) );
244 $this->assertSame( array(
245 array( LogLevel
::INFO
, "Session X: Missing metadata: $key" )
246 ), $logger->getBuffer() );
247 $logger->clearBuffer();
250 $data['metadata'] = $dataMD;
251 $data['metadata']['appId'] = 'Foobar';
252 $info = new SessionInfo( SessionInfo
::MIN_PRIORITY
, $data );
253 $metadata = $info->getProviderMetadata();
254 $this->assertFalse( $provider->refreshSessionInfo( $info, $request, $metadata ) );
255 $this->assertSame( array(
256 array( LogLevel
::INFO
, "Session X: No BotPassword for {$bp->getUserCentralId()} Foobar" ),
257 ), $logger->getBuffer() );
258 $logger->clearBuffer();
260 $data['metadata'] = $dataMD;
261 $data['metadata']['token'] = 'Foobar';
262 $info = new SessionInfo( SessionInfo
::MIN_PRIORITY
, $data );
263 $metadata = $info->getProviderMetadata();
264 $this->assertFalse( $provider->refreshSessionInfo( $info, $request, $metadata ) );
265 $this->assertSame( array(
266 array( LogLevel
::INFO
, 'Session X: BotPassword token check failed' ),
267 ), $logger->getBuffer() );
268 $logger->clearBuffer();
270 $request2 = $this->getMock( 'FauxRequest', array( 'getIP' ) );
271 $request2->expects( $this->any() )->method( 'getIP' )
272 ->will( $this->returnValue( '10.0.0.1' ) );
273 $data['metadata'] = $dataMD;
274 $info = new SessionInfo( SessionInfo
::MIN_PRIORITY
, $data );
275 $metadata = $info->getProviderMetadata();
276 $this->assertFalse( $provider->refreshSessionInfo( $info, $request2, $metadata ) );
277 $this->assertSame( array(
278 array( LogLevel
::INFO
, 'Session X: Restrictions check failed' ),
279 ), $logger->getBuffer() );
280 $logger->clearBuffer();
282 $info = new SessionInfo( SessionInfo
::MIN_PRIORITY
, $data );
283 $metadata = $info->getProviderMetadata();
284 $this->assertTrue( $provider->refreshSessionInfo( $info, $request, $metadata ) );
285 $this->assertSame( array(), $logger->getBuffer() );
286 $this->assertEquals( $dataMD +
array( 'rights' => array( 'read' ) ), $metadata );