$this->setMwGlobals( [
'wgGroupPermissions' => [],
'wgRevokePermissions' => [],
+ 'wgActorTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH,
] );
+ $this->overrideMwServices();
$this->setUpPermissionGlobals();
$this->assertContains( 'nukeworld', $rights );
// Add a Session that limits rights
- $mock = $this->getMockBuilder( stdclass::class )
+ $mock = $this->getMockBuilder( stdClass::class )
->setMethods( [ 'getAllowedUserRights', 'deregisterSession', 'getSessionId' ] )
->getMock();
$mock->method( 'getAllowedUserRights' )->willReturn( [ 'test', 'writetest' ] );
[ 'Ab/cd', false, 'Contains slash' ],
[ 'Ab cd', true, 'Whitespace' ],
[ '192.168.1.1', false, 'IP' ],
+ [ '116.17.184.5/32', false, 'IP range' ],
+ [ '::e:f:2001/96', false, 'IPv6 range' ],
[ 'User:Abcd', false, 'Reserved Namespace' ],
[ '12abcd232', true, 'Starts with Numbers' ],
[ '?abcd', true, 'Start with ? mark' ],
* Test, if for all rights a right- message exist,
* which is used on Special:ListGroupRights as help text
* Extensions and core
+ *
+ * @coversNothing
*/
public function testAllRightsWithMessage() {
// Getting all user rights, for core: User::$mCoreRights, for extensions: $wgAvailableRights
'wgSecretKey' => MWCryptRand::generateHex( 64, true ),
] );
+ // Unregister the hooks for proper unit testing
+ $this->mergeMwGlobalArrayValue( 'wgHooks', [
+ 'PerformRetroactiveAutoblock' => []
+ ] );
+
// 1. Log in a test user, and block them.
+ $userBlocker = $this->getTestSysop()->getUser();
$user1tmp = $this->getTestUser()->getUser();
$request1 = new FauxRequest();
$request1->getSession()->setUser( $user1tmp );
'enableAutoblock' => true,
'expiry' => wfTimestamp( TS_MW, $expiryFiveHours ),
] );
+ $block->setBlocker( $this->getTestSysop()->getUser() );
$block->setTarget( $user1tmp );
- $block->insert();
+ $block->setBlocker( $userBlocker );
+ $res = $block->insert();
+ $this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
$user1 = User::newFromSession( $request1 );
$user1->mBlock = $block;
$user1->load();
$this->assertTrue( $user2->isAnon() );
$this->assertFalse( $user2->isLoggedIn() );
$this->assertTrue( $user2->isBlocked() );
- $this->assertEquals( true, $user2->getBlock()->isAutoblocking() ); // Non-strict type-check.
+ // Non-strict type-check.
+ $this->assertEquals( true, $user2->getBlock()->isAutoblocking(), 'Autoblock does not work' );
// Can't directly compare the objects becuase of member type differences.
// One day this will work: $this->assertEquals( $block, $user2->getBlock() );
$this->assertEquals( $block->getId(), $user2->getBlock()->getId() );
'wgSecretKey' => MWCryptRand::generateHex( 64, true ),
] );
+ // Unregister the hooks for proper unit testing
+ $this->mergeMwGlobalArrayValue( 'wgHooks', [
+ 'PerformRetroactiveAutoblock' => []
+ ] );
+
// 1. Log in a test user, and block them.
+ $userBlocker = $this->getTestSysop()->getUser();
$testUser = $this->getTestUser()->getUser();
$request1 = new FauxRequest();
$request1->getSession()->setUser( $testUser );
$block = new Block( [ 'enableAutoblock' => true ] );
+ $block->setBlocker( $this->getTestSysop()->getUser() );
$block->setTarget( $testUser );
- $block->insert();
+ $block->setBlocker( $userBlocker );
+ $res = $block->insert();
+ $this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
$user = User::newFromSession( $request1 );
$user->mBlock = $block;
$user->load();
'wgCookiePrefix' => 'wm_infinite_block',
'wgSecretKey' => MWCryptRand::generateHex( 64, true ),
] );
+
+ // Unregister the hooks for proper unit testing
+ $this->mergeMwGlobalArrayValue( 'wgHooks', [
+ 'PerformRetroactiveAutoblock' => []
+ ] );
+
// 1. Log in a test user, and block them indefinitely.
+ $userBlocker = $this->getTestSysop()->getUser();
$user1Tmp = $this->getTestUser()->getUser();
$request1 = new FauxRequest();
$request1->getSession()->setUser( $user1Tmp );
$block = new Block( [ 'enableAutoblock' => true, 'expiry' => 'infinity' ] );
+ $block->setBlocker( $this->getTestSysop()->getUser() );
$block->setTarget( $user1Tmp );
- $block->insert();
+ $block->setBlocker( $userBlocker );
+ $res = $block->insert();
+ $this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
$user1 = User::newFromSession( $request1 );
$user1->mBlock = $block;
$user1->load();
'wgSecretKey' => MWCryptRand::generateHex( 64, true ),
] );
+ // Unregister the hooks for proper unit testing
+ $this->mergeMwGlobalArrayValue( 'wgHooks', [
+ 'PerformRetroactiveAutoblock' => []
+ ] );
+
// 1. Log in a blocked test user.
+ $userBlocker = $this->getTestSysop()->getUser();
$user1tmp = $this->getTestUser()->getUser();
$request1 = new FauxRequest();
$request1->getSession()->setUser( $user1tmp );
$block = new Block( [ 'enableAutoblock' => true ] );
+ $block->setBlocker( $this->getTestSysop()->getUser() );
$block->setTarget( $user1tmp );
- $block->insert();
+ $block->setBlocker( $userBlocker );
+ $res = $block->insert();
+ $this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
$user1 = User::newFromSession( $request1 );
$user1->mBlock = $block;
$user1->load();
'wgSecretKey' => null,
] );
+ // Unregister the hooks for proper unit testing
+ $this->mergeMwGlobalArrayValue( 'wgHooks', [
+ 'PerformRetroactiveAutoblock' => []
+ ] );
+
// 1. Log in a blocked test user.
+ $userBlocker = $this->getTestSysop()->getUser();
$user1tmp = $this->getTestUser()->getUser();
$request1 = new FauxRequest();
$request1->getSession()->setUser( $user1tmp );
$block = new Block( [ 'enableAutoblock' => true ] );
+ $block->setBlocker( $this->getTestSysop()->getUser() );
$block->setTarget( $user1tmp );
- $block->insert();
+ $block->setBlocker( $userBlocker );
+ $res = $block->insert();
+ $this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
$user1 = User::newFromSession( $request1 );
$user1->mBlock = $block;
$user1->load();
$block->delete();
}
+ /**
+ * @covers User::isPingLimitable
+ */
public function testIsPingLimitable() {
$request = new FauxRequest();
$request->setIP( '1.2.3.4' );
}
/**
+ * @covers User::getExperienceLevel
* @dataProvider provideExperienceLevel
*/
public function testExperienceLevel( $editCount, $memberSince, $expLevel ) {
] );
$db = wfGetDB( DB_MASTER );
-
- $data = new stdClass();
- $data->user_id = 1;
- $data->user_name = 'name';
- $data->user_real_name = 'Real Name';
- $data->user_touched = 1;
- $data->user_token = 'token';
- $data->user_email = 'a@a.a';
- $data->user_email_authenticated = null;
- $data->user_email_token = 'token';
- $data->user_email_token_expires = null;
- $data->user_editcount = $editCount;
- $data->user_registration = $db->timestamp( time() - $memberSince * 86400 );
- $user = User::newFromRow( $data );
+ $userQuery = User::getQueryInfo();
+ $row = $db->selectRow(
+ $userQuery['tables'],
+ $userQuery['fields'],
+ [ 'user_id' => $this->getTestUser()->getUser()->getId() ],
+ __METHOD__,
+ [],
+ $userQuery['joins']
+ );
+ $row->user_editcount = $editCount;
+ $row->user_registration = $db->timestamp( time() - $memberSince * 86400 );
+ $user = User::newFromRow( $row );
$this->assertEquals( $expLevel, $user->getExperienceLevel() );
}
+ /**
+ * @covers User::getExperienceLevel
+ */
public function testExperienceLevelAnon() {
$user = User::newFromName( '10.11.12.13', false );
);
$this->assertTrue( User::isLocallyBlockedProxy( $ip ) );
}
+
+ public function testActorId() {
+ $this->hideDeprecated( 'User::selectFields' );
+
+ // Newly-created user has an actor ID
+ $user = User::createNew( 'UserTestActorId1' );
+ $id = $user->getId();
+ $this->assertTrue( $user->getActorId() > 0, 'User::createNew sets an actor ID' );
+
+ $user = User::newFromName( 'UserTestActorId2' );
+ $user->addToDatabase();
+ $this->assertTrue( $user->getActorId() > 0, 'User::addToDatabase sets an actor ID' );
+
+ $user = User::newFromName( 'UserTestActorId1' );
+ $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be retrieved for user loaded by name' );
+
+ $user = User::newFromId( $id );
+ $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be retrieved for user loaded by ID' );
+
+ $user2 = User::newFromActorId( $user->getActorId() );
+ $this->assertEquals( $user->getId(), $user2->getId(),
+ 'User::newFromActorId works for an existing user' );
+
+ $row = $this->db->selectRow( 'user', User::selectFields(), [ 'user_id' => $id ], __METHOD__ );
+ $user = User::newFromRow( $row );
+ $this->assertTrue( $user->getActorId() > 0,
+ 'Actor ID can be retrieved for user loaded with User::selectFields()' );
+
+ $this->db->delete( 'actor', [ 'actor_user' => $id ], __METHOD__ );
+ User::purge( wfWikiId(), $id );
+ // Because WANObjectCache->delete() stupidly doesn't delete from the process cache.
+ ObjectCache::getMainWANInstance()->clearProcessCache();
+
+ $user = User::newFromId( $id );
+ $this->assertFalse( $user->getActorId() > 0, 'No Actor ID by default if none in database' );
+ $this->assertTrue( $user->getActorId( $this->db ) > 0, 'Actor ID can be created if none in db' );
+
+ $user->setName( 'UserTestActorId4-renamed' );
+ $user->saveSettings();
+ $this->assertEquals(
+ $user->getName(),
+ $this->db->selectField(
+ 'actor', 'actor_name', [ 'actor_id' => $user->getActorId() ], __METHOD__
+ ),
+ 'User::saveSettings updates actor table for name change'
+ );
+
+ // For sanity
+ $ip = '192.168.12.34';
+ $this->db->delete( 'actor', [ 'actor_name' => $ip ], __METHOD__ );
+
+ $user = User::newFromName( $ip, false );
+ $this->assertFalse( $user->getActorId() > 0, 'Anonymous user has no actor ID by default' );
+ $this->assertTrue( $user->getActorId( $this->db ) > 0,
+ 'Actor ID can be created for an anonymous user' );
+
+ $user = User::newFromName( $ip, false );
+ $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be loaded for an anonymous user' );
+ $user2 = User::newFromActorId( $user->getActorId() );
+ $this->assertEquals( $user->getName(), $user2->getName(),
+ 'User::newFromActorId works for an anonymous user' );
+ }
+
+ public function testNewFromAnyId() {
+ // Registered user
+ $user = $this->getTestUser()->getUser();
+ for ( $i = 1; $i <= 7; $i++ ) {
+ $test = User::newFromAnyId(
+ ( $i & 1 ) ? $user->getId() : null,
+ ( $i & 2 ) ? $user->getName() : null,
+ ( $i & 4 ) ? $user->getActorId() : null
+ );
+ $this->assertSame( $user->getId(), $test->getId() );
+ $this->assertSame( $user->getName(), $test->getName() );
+ $this->assertSame( $user->getActorId(), $test->getActorId() );
+ }
+
+ // Anon user. Can't load by only user ID when that's 0.
+ $user = User::newFromName( '192.168.12.34', false );
+ $user->getActorId( $this->db ); // Make sure an actor ID exists
+
+ $test = User::newFromAnyId( null, '192.168.12.34', null );
+ $this->assertSame( $user->getId(), $test->getId() );
+ $this->assertSame( $user->getName(), $test->getName() );
+ $this->assertSame( $user->getActorId(), $test->getActorId() );
+ $test = User::newFromAnyId( null, null, $user->getActorId() );
+ $this->assertSame( $user->getId(), $test->getId() );
+ $this->assertSame( $user->getName(), $test->getName() );
+ $this->assertSame( $user->getActorId(), $test->getActorId() );
+
+ // Bogus data should still "work" as long as nothing triggers a ->load(),
+ // and accessing the specified data shouldn't do that.
+ $test = User::newFromAnyId( 123456, 'Bogus', 654321 );
+ $this->assertSame( 123456, $test->getId() );
+ $this->assertSame( 'Bogus', $test->getName() );
+ $this->assertSame( 654321, $test->getActorId() );
+
+ // Exceptional cases
+ try {
+ User::newFromAnyId( null, null, null );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ }
+ try {
+ User::newFromAnyId( 0, null, 0 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ }
+ }
}