22 'wgEnableBotPasswords' =>
true,
23 'wgBotPasswordsDatabase' =>
false,
24 'wgCentralIdLookupProvider' =>
'BotPasswordTest OkMock',
25 'wgGrantPermissions' => [
26 'test' => [
'read' =>
true ],
28 'wgUserrightsInterwikiDelimiter' =>
'@',
32 $this->testUserName = $this->testUser->getUser()->getName();
34 $mock1 = $this->getMockForAbstractClass(
'CentralIdLookup' );
35 $mock1->expects( $this->any() )->method(
'isAttached' )
36 ->will( $this->returnValue(
true ) );
37 $mock1->expects( $this->any() )->method(
'lookupUserNames' )
38 ->will( $this->returnValue( [ $this->testUserName => 42,
'UTDummy' => 43,
'UTInvalid' => 0 ] ) );
39 $mock1->expects( $this->never() )->method(
'lookupCentralIds' );
41 $mock2 = $this->getMockForAbstractClass(
'CentralIdLookup' );
42 $mock2->expects( $this->any() )->method(
'isAttached' )
43 ->will( $this->returnValue(
false ) );
44 $mock2->expects( $this->any() )->method(
'lookupUserNames' )
45 ->will( $this->returnArgument( 0 ) );
46 $mock2->expects( $this->never() )->method(
'lookupCentralIds' );
49 'BotPasswordTest OkMock' => [
'factory' =>
function ()
use ( $mock1 ) {
52 'BotPasswordTest FailMock' => [
'factory' =>
function ()
use ( $mock2 ) {
96 $user = $this->testUser->getUser();
97 $bp = BotPassword::newFromUser(
$user,
'BotPassword' );
98 $this->assertInstanceOf(
'BotPassword', $bp );
99 $this->assertTrue( $bp->isSaved() );
100 $this->assertSame( 42, $bp->getUserCentralId() );
101 $this->assertSame(
'BotPassword', $bp->getAppId() );
102 $this->assertSame(
'token!', trim( $bp->getToken(),
" \0" ) );
103 $this->assertEquals(
'{"IPAddresses":["127.0.0.0/8"]}', $bp->getRestrictions()->toJson() );
104 $this->assertSame( [
'test' ], $bp->getGrants() );
106 $this->assertNull( BotPassword::newFromUser(
$user,
'DoesNotExist' ) );
109 'wgCentralIdLookupProvider' =>
'BotPasswordTest FailMock'
111 $this->assertNull( BotPassword::newFromUser(
$user,
'BotPassword' ) );
113 $this->assertSame(
'@', BotPassword::getSeparator() );
115 'wgUserrightsInterwikiDelimiter' =>
'#',
117 $this->assertSame(
'#', BotPassword::getSeparator() );
121 $user = $this->testUser->getUser();
122 $bp = BotPassword::newUnsaved( [
124 'appId' =>
'DoesNotExist'
126 $this->assertInstanceOf(
'BotPassword', $bp );
127 $this->assertFalse( $bp->isSaved() );
128 $this->assertSame( 42, $bp->getUserCentralId() );
129 $this->assertSame(
'DoesNotExist', $bp->getAppId() );
131 $this->assertSame( [], $bp->getGrants() );
133 $bp = BotPassword::newUnsaved( [
134 'username' =>
'UTDummy',
135 'appId' =>
'DoesNotExist2',
137 'grants' => [
'test' ],
139 $this->assertInstanceOf(
'BotPassword', $bp );
140 $this->assertFalse( $bp->isSaved() );
141 $this->assertSame( 43, $bp->getUserCentralId() );
142 $this->assertSame(
'DoesNotExist2', $bp->getAppId() );
143 $this->assertEquals(
'{"IPAddresses":["127.0.0.0/8"]}', $bp->getRestrictions()->toJson() );
144 $this->assertSame( [
'test' ], $bp->getGrants() );
146 $user = $this->testUser->getUser();
147 $bp = BotPassword::newUnsaved( [
149 'appId' =>
'DoesNotExist'
151 $this->assertInstanceOf(
'BotPassword', $bp );
152 $this->assertFalse( $bp->isSaved() );
153 $this->assertSame( 45, $bp->getUserCentralId() );
154 $this->assertSame(
'DoesNotExist', $bp->getAppId() );
156 $user = $this->testUser->getUser();
157 $bp = BotPassword::newUnsaved( [
159 'appId' =>
'BotPassword'
161 $this->assertInstanceOf(
'BotPassword', $bp );
162 $this->assertFalse( $bp->isSaved() );
164 $this->assertNull( BotPassword::newUnsaved( [
168 $this->assertNull( BotPassword::newUnsaved( [
170 'appId' => str_repeat(
'X', BotPassword::APPID_MAXLENGTH + 1 ),
172 $this->assertNull( BotPassword::newUnsaved( [
173 'user' => $this->testUserName,
176 $this->assertNull( BotPassword::newUnsaved( [
177 'username' =>
'UTInvalid',
180 $this->assertNull( BotPassword::newUnsaved( [
186 $bp = TestingAccessWrapper::newFromObject( BotPassword::newFromCentralId( 42,
'BotPassword' ) );
188 $password = $bp->getPassword();
189 $this->assertInstanceOf(
'Password', $password );
190 $this->assertTrue( $password->equals(
'foobaz' ) );
193 $password = $bp->getPassword();
194 $this->assertInstanceOf(
'InvalidPassword', $password );
196 $bp = TestingAccessWrapper::newFromObject( BotPassword::newFromCentralId( 42,
'BotPassword' ) );
200 [
'bp_password' =>
'garbage' ],
201 [
'bp_user' => 42,
'bp_app_id' =>
'BotPassword' ],
204 $password = $bp->getPassword();
205 $this->assertInstanceOf(
'InvalidPassword', $password );
209 $bp1 = TestingAccessWrapper::newFromObject( BotPassword::newFromCentralId( 42,
'BotPassword' ) );
210 $bp2 = TestingAccessWrapper::newFromObject( BotPassword::newFromCentralId( 43,
'BotPassword' ) );
212 $this->assertNotInstanceOf(
'InvalidPassword', $bp1->getPassword(),
'sanity check' );
213 $this->assertNotInstanceOf(
'InvalidPassword', $bp2->getPassword(),
'sanity check' );
214 BotPassword::invalidateAllPasswordsForUser( $this->testUserName );
215 $this->assertInstanceOf(
'InvalidPassword', $bp1->getPassword() );
216 $this->assertNotInstanceOf(
'InvalidPassword', $bp2->getPassword() );
218 $bp = TestingAccessWrapper::newFromObject( BotPassword::newFromCentralId( 42,
'BotPassword' ) );
219 $this->assertInstanceOf(
'InvalidPassword', $bp->getPassword() );
223 $this->assertNotNull( BotPassword::newFromCentralId( 42,
'BotPassword' ),
'sanity check' );
224 $this->assertNotNull( BotPassword::newFromCentralId( 43,
'BotPassword' ),
'sanity check' );
226 BotPassword::removeAllPasswordsForUser( $this->testUserName );
228 $this->assertNull( BotPassword::newFromCentralId( 42,
'BotPassword' ) );
229 $this->assertNotNull( BotPassword::newFromCentralId( 43,
'BotPassword' ) );
263 $status = BotPassword::login(
"{$this->testUserName}@BotPassword",
'foobaz',
new FauxRequest );
264 $this->assertEquals( Status::newFatal(
'botpasswords-disabled' ),
$status );
269 'logger' =>
new Psr\Log\NullLogger,
272 $reset = MediaWiki\Session\TestUtils::setSessionManagerSingleton( $manager );
274 $manager->getProvider(
MediaWiki\Session\BotPasswordSessionProvider::class ),
277 $status = BotPassword::login(
"{$this->testUserName}@BotPassword",
'foobaz',
new FauxRequest );
278 $this->assertEquals( Status::newFatal(
'botpasswords-no-provider' ),
$status );
279 ScopedCallback::consume( $reset );
284 'SessionProviders' => $mainConfig->get(
'SessionProviders' ) + [
285 MediaWiki\Session\BotPasswordSessionProvider::class => [
286 'class' =>
MediaWiki\Session\BotPasswordSessionProvider::class,
287 'args' => [ [
'priority' => 40 ] ],
293 'logger' =>
new Psr\Log\NullLogger,
296 $reset = MediaWiki\Session\TestUtils::setSessionManagerSingleton( $manager );
300 $this->assertEquals( Status::newFatal(
'botpasswords-invalid-name',
'@' ),
$status );
304 $this->assertEquals( Status::newFatal(
'nosuchuser',
'UTDummy' ),
$status );
307 $status = BotPassword::login(
"{$this->testUserName}@DoesNotExist",
'foobaz',
new FauxRequest );
309 Status::newFatal(
'botpasswords-not-exist', $this->testUserName,
'DoesNotExist' ),
314 $request = $this->getMock(
'FauxRequest', [
'getIP' ] );
315 $request->expects( $this->any() )->method(
'getIP' )
316 ->will( $this->returnValue(
'10.0.0.1' ) );
317 $status = BotPassword::login(
"{$this->testUserName}@BotPassword",
'foobaz',
$request );
318 $this->assertEquals( Status::newFatal(
'botpasswords-restriction-failed' ),
$status );
322 "{$this->testUserName}@BotPassword", $this->testUser->getPassword(),
new FauxRequest );
323 $this->assertEquals( Status::newFatal(
'wrongpassword' ),
$status );
327 $this->assertNotInstanceOf(
328 MediaWiki\Session\BotPasswordSessionProvider::class,
329 $request->getSession()->getProvider(),
332 $status = BotPassword::login(
"{$this->testUserName}@BotPassword",
'foobaz',
$request );
333 $this->assertInstanceOf(
'Status',
$status );
334 $this->assertTrue(
$status->isGood() );
335 $session =
$status->getValue();
336 $this->assertInstanceOf(
MediaWiki\Session\Session::class, $session );
337 $this->assertInstanceOf(
338 MediaWiki\Session\BotPasswordSessionProvider::class, $session->getProvider()
340 $this->assertSame( $session->getId(),
$request->getSession()->getId() );
342 ScopedCallback::consume( $reset );
350 $passwordFactory = new \PasswordFactory();
353 $bp = BotPassword::newUnsaved( [
355 'appId' =>
'TestSave',
357 'grants' => [
'test' ],
359 $this->assertFalse( $bp->isSaved(),
'sanity check' );
361 BotPassword::newFromCentralId( 42,
'TestSave', BotPassword::READ_LATEST ),
'sanity check'
364 $passwordHash = $password ? $passwordFactory->newFromPlaintext( $password ) :
null;
365 $this->assertFalse( $bp->save(
'update', $passwordHash ) );
366 $this->assertTrue( $bp->save(
'insert', $passwordHash ) );
367 $bp2 = BotPassword::newFromCentralId( 42,
'TestSave', BotPassword::READ_LATEST );
368 $this->assertInstanceOf(
'BotPassword', $bp2 );
369 $this->assertEquals( $bp->getUserCentralId(), $bp2->getUserCentralId() );
370 $this->assertEquals( $bp->getAppId(), $bp2->getAppId() );
371 $this->assertEquals( $bp->getToken(), $bp2->getToken() );
372 $this->assertEquals( $bp->getRestrictions(), $bp2->getRestrictions() );
373 $this->assertEquals( $bp->getGrants(), $bp2->getGrants() );
374 $pw = TestingAccessWrapper::newFromObject( $bp )->getPassword();
375 if ( $password ===
null ) {
376 $this->assertInstanceOf(
'InvalidPassword', $pw );
378 $this->assertTrue( $pw->equals( $password ) );
381 $token = $bp->getToken();
382 $this->assertFalse( $bp->save(
'insert' ) );
383 $this->assertTrue( $bp->save(
'update' ) );
384 $this->assertNotEquals( $token, $bp->getToken() );
385 $bp2 = BotPassword::newFromCentralId( 42,
'TestSave', BotPassword::READ_LATEST );
386 $this->assertInstanceOf(
'BotPassword', $bp2 );
387 $this->assertEquals( $bp->getToken(), $bp2->getToken() );
388 $pw = TestingAccessWrapper::newFromObject( $bp )->getPassword();
389 if ( $password ===
null ) {
390 $this->assertInstanceOf(
'InvalidPassword', $pw );
392 $this->assertTrue( $pw->equals( $password ) );
395 $passwordHash = $passwordFactory->newFromPlaintext(
'XXX' );
396 $token = $bp->getToken();
397 $this->assertTrue( $bp->save(
'update', $passwordHash ) );
398 $this->assertNotEquals( $token, $bp->getToken() );
399 $pw = TestingAccessWrapper::newFromObject( $bp )->getPassword();
400 $this->assertTrue( $pw->equals(
'XXX' ) );
402 $this->assertTrue( $bp->delete() );
403 $this->assertFalse( $bp->isSaved() );
404 $this->assertNull( BotPassword::newFromCentralId( 42,
'TestSave', BotPassword::READ_LATEST ) );
406 $this->assertFalse( $bp->save(
'foobar' ) );