2011-07-11 18:36:29 +00:00
|
|
|
|
<?php
|
|
|
|
|
|
|
2011-07-16 16:09:00 +00:00
|
|
|
|
define( 'NS_UNITTEST', 5600 );
|
|
|
|
|
|
define( 'NS_UNITTEST_TALK', 5601 );
|
|
|
|
|
|
|
2016-11-17 00:38:09 +00:00
|
|
|
|
use MediaWiki\MediaWikiServices;
|
2017-04-19 19:37:35 +00:00
|
|
|
|
use Wikimedia\TestingAccessWrapper;
|
2016-11-17 00:38:09 +00:00
|
|
|
|
|
2011-07-19 21:41:25 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @group Database
|
|
|
|
|
|
*/
|
2011-07-11 18:36:29 +00:00
|
|
|
|
class UserTest extends MediaWikiTestCase {
|
2012-01-19 14:56:18 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @var User
|
|
|
|
|
|
*/
|
2011-07-16 16:09:00 +00:00
|
|
|
|
protected $user;
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
|
protected function setUp() {
|
2011-07-11 18:36:29 +00:00
|
|
|
|
parent::setUp();
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgGroupPermissions' => [],
|
|
|
|
|
|
'wgRevokePermissions' => [],
|
|
|
|
|
|
] );
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2011-07-11 18:36:29 +00:00
|
|
|
|
$this->setUpPermissionGlobals();
|
2012-10-08 10:56:20 +00:00
|
|
|
|
|
2017-05-18 20:16:55 +00:00
|
|
|
|
$this->user = $this->getTestUser( [ 'unittesters' ] )->getUser();
|
2011-07-11 18:36:29 +00:00
|
|
|
|
}
|
2012-10-08 10:56:20 +00:00
|
|
|
|
|
2011-07-11 18:36:29 +00:00
|
|
|
|
private function setUpPermissionGlobals() {
|
|
|
|
|
|
global $wgGroupPermissions, $wgRevokePermissions;
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2011-07-16 16:09:00 +00:00
|
|
|
|
# Data for regular $wgGroupPermissions test
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$wgGroupPermissions['unittesters'] = [
|
2011-07-16 16:09:00 +00:00
|
|
|
|
'test' => true,
|
2011-07-11 18:36:29 +00:00
|
|
|
|
'runtest' => true,
|
|
|
|
|
|
'writetest' => false,
|
|
|
|
|
|
'nukeworld' => false,
|
2016-02-17 09:09:32 +00:00
|
|
|
|
];
|
|
|
|
|
|
$wgGroupPermissions['testwriters'] = [
|
2011-07-16 16:09:00 +00:00
|
|
|
|
'test' => true,
|
2011-07-11 18:36:29 +00:00
|
|
|
|
'writetest' => true,
|
|
|
|
|
|
'modifytest' => true,
|
2016-02-17 09:09:32 +00:00
|
|
|
|
];
|
2012-10-08 10:56:20 +00:00
|
|
|
|
|
2011-07-16 16:09:00 +00:00
|
|
|
|
# Data for regular $wgRevokePermissions test
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$wgRevokePermissions['formertesters'] = [
|
2011-07-11 18:36:29 +00:00
|
|
|
|
'runtest' => true,
|
2016-02-17 09:09:32 +00:00
|
|
|
|
];
|
2013-06-10 19:30:43 +00:00
|
|
|
|
|
|
|
|
|
|
# For the options test
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$wgGroupPermissions['*'] = [
|
2013-06-10 19:30:43 +00:00
|
|
|
|
'editmyoptions' => true,
|
2016-02-17 09:09:32 +00:00
|
|
|
|
];
|
2011-07-16 16:09:00 +00:00
|
|
|
|
}
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::getGroupPermissions
|
|
|
|
|
|
*/
|
2011-07-11 18:36:29 +00:00
|
|
|
|
public function testGroupPermissions() {
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$rights = User::getGroupPermissions( [ 'unittesters' ] );
|
2011-07-11 18:36:29 +00:00
|
|
|
|
$this->assertContains( 'runtest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'writetest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'modifytest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'nukeworld', $rights );
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$rights = User::getGroupPermissions( [ 'unittesters', 'testwriters' ] );
|
2011-07-11 18:36:29 +00:00
|
|
|
|
$this->assertContains( 'runtest', $rights );
|
|
|
|
|
|
$this->assertContains( 'writetest', $rights );
|
|
|
|
|
|
$this->assertContains( 'modifytest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'nukeworld', $rights );
|
|
|
|
|
|
}
|
2013-02-14 11:36:35 +00:00
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::getGroupPermissions
|
|
|
|
|
|
*/
|
2011-07-11 18:36:29 +00:00
|
|
|
|
public function testRevokePermissions() {
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$rights = User::getGroupPermissions( [ 'unittesters', 'formertesters' ] );
|
2011-07-11 18:36:29 +00:00
|
|
|
|
$this->assertNotContains( 'runtest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'writetest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'modifytest', $rights );
|
2011-10-11 10:02:50 +00:00
|
|
|
|
$this->assertNotContains( 'nukeworld', $rights );
|
2011-07-11 18:36:29 +00:00
|
|
|
|
}
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::getRights
|
|
|
|
|
|
*/
|
2011-07-16 16:09:00 +00:00
|
|
|
|
public function testUserPermissions() {
|
|
|
|
|
|
$rights = $this->user->getRights();
|
|
|
|
|
|
$this->assertContains( 'runtest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'writetest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'modifytest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'nukeworld', $rights );
|
|
|
|
|
|
}
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2016-07-07 21:24:50 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::getRights
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testUserGetRightsHooks() {
|
2017-05-18 20:16:55 +00:00
|
|
|
|
$user = $this->getTestUser( [ 'unittesters', 'testwriters' ] )->getUser();
|
2016-07-07 21:24:50 +00:00
|
|
|
|
$userWrapper = TestingAccessWrapper::newFromObject( $user );
|
|
|
|
|
|
|
|
|
|
|
|
$rights = $user->getRights();
|
|
|
|
|
|
$this->assertContains( 'test', $rights, 'sanity check' );
|
|
|
|
|
|
$this->assertContains( 'runtest', $rights, 'sanity check' );
|
|
|
|
|
|
$this->assertContains( 'writetest', $rights, 'sanity check' );
|
|
|
|
|
|
$this->assertNotContains( 'nukeworld', $rights, 'sanity check' );
|
|
|
|
|
|
|
|
|
|
|
|
// Add a hook manipluating the rights
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue( 'wgHooks', [ 'UserGetRights' => [ function ( $user, &$rights ) {
|
|
|
|
|
|
$rights[] = 'nukeworld';
|
|
|
|
|
|
$rights = array_diff( $rights, [ 'writetest' ] );
|
|
|
|
|
|
} ] ] );
|
|
|
|
|
|
|
|
|
|
|
|
$userWrapper->mRights = null;
|
|
|
|
|
|
$rights = $user->getRights();
|
|
|
|
|
|
$this->assertContains( 'test', $rights );
|
|
|
|
|
|
$this->assertContains( 'runtest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'writetest', $rights );
|
|
|
|
|
|
$this->assertContains( 'nukeworld', $rights );
|
|
|
|
|
|
|
|
|
|
|
|
// Add a Session that limits rights
|
2018-01-13 00:02:09 +00:00
|
|
|
|
$mock = $this->getMockBuilder( stdClass::class )
|
2016-07-07 21:24:50 +00:00
|
|
|
|
->setMethods( [ 'getAllowedUserRights', 'deregisterSession', 'getSessionId' ] )
|
|
|
|
|
|
->getMock();
|
|
|
|
|
|
$mock->method( 'getAllowedUserRights' )->willReturn( [ 'test', 'writetest' ] );
|
|
|
|
|
|
$mock->method( 'getSessionId' )->willReturn(
|
|
|
|
|
|
new MediaWiki\Session\SessionId( str_repeat( 'X', 32 ) )
|
|
|
|
|
|
);
|
|
|
|
|
|
$session = MediaWiki\Session\TestUtils::getDummySession( $mock );
|
|
|
|
|
|
$mockRequest = $this->getMockBuilder( FauxRequest::class )
|
|
|
|
|
|
->setMethods( [ 'getSession' ] )
|
|
|
|
|
|
->getMock();
|
|
|
|
|
|
$mockRequest->method( 'getSession' )->willReturn( $session );
|
|
|
|
|
|
$userWrapper->mRequest = $mockRequest;
|
|
|
|
|
|
|
|
|
|
|
|
$userWrapper->mRights = null;
|
|
|
|
|
|
$rights = $user->getRights();
|
|
|
|
|
|
$this->assertContains( 'test', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'runtest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'writetest', $rights );
|
|
|
|
|
|
$this->assertNotContains( 'nukeworld', $rights );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-07-16 16:09:00 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @dataProvider provideGetGroupsWithPermission
|
2013-10-21 21:09:13 +00:00
|
|
|
|
* @covers User::getGroupsWithPermission
|
2011-07-16 16:09:00 +00:00
|
|
|
|
*/
|
2011-12-12 06:03:01 +00:00
|
|
|
|
public function testGetGroupsWithPermission( $expected, $right ) {
|
|
|
|
|
|
$result = User::getGroupsWithPermission( $right );
|
2011-07-16 16:09:00 +00:00
|
|
|
|
sort( $result );
|
|
|
|
|
|
sort( $expected );
|
2011-10-11 10:02:50 +00:00
|
|
|
|
|
2011-12-12 06:03:01 +00:00
|
|
|
|
$this->assertEquals( $expected, $result, "Groups with permission $right" );
|
2011-07-16 16:09:00 +00:00
|
|
|
|
}
|
2012-01-19 14:56:18 +00:00
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
|
public static function provideGetGroupsWithPermission() {
|
2016-02-17 09:09:32 +00:00
|
|
|
|
return [
|
|
|
|
|
|
[
|
|
|
|
|
|
[ 'unittesters', 'testwriters' ],
|
2011-12-12 06:03:01 +00:00
|
|
|
|
'test'
|
2016-02-17 09:09:32 +00:00
|
|
|
|
],
|
|
|
|
|
|
[
|
|
|
|
|
|
[ 'unittesters' ],
|
2011-12-12 06:03:01 +00:00
|
|
|
|
'runtest'
|
2016-02-17 09:09:32 +00:00
|
|
|
|
],
|
|
|
|
|
|
[
|
|
|
|
|
|
[ 'testwriters' ],
|
2011-12-12 06:03:01 +00:00
|
|
|
|
'writetest'
|
2016-02-17 09:09:32 +00:00
|
|
|
|
],
|
|
|
|
|
|
[
|
|
|
|
|
|
[ 'testwriters' ],
|
2011-12-12 06:03:01 +00:00
|
|
|
|
'modifytest'
|
2016-02-17 09:09:32 +00:00
|
|
|
|
],
|
|
|
|
|
|
];
|
2011-07-16 16:09:00 +00:00
|
|
|
|
}
|
2011-10-11 09:17:36 +00:00
|
|
|
|
|
2014-07-01 16:31:07 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @dataProvider provideIPs
|
|
|
|
|
|
* @covers User::isIP
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testIsIP( $value, $result, $message ) {
|
|
|
|
|
|
$this->assertEquals( $this->user->isIP( $value ), $result, $message );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static function provideIPs() {
|
2016-02-17 09:09:32 +00:00
|
|
|
|
return [
|
|
|
|
|
|
[ '', false, 'Empty string' ],
|
|
|
|
|
|
[ ' ', false, 'Blank space' ],
|
|
|
|
|
|
[ '10.0.0.0', true, 'IPv4 private 10/8' ],
|
|
|
|
|
|
[ '10.255.255.255', true, 'IPv4 private 10/8' ],
|
|
|
|
|
|
[ '192.168.1.1', true, 'IPv4 private 192.168/16' ],
|
|
|
|
|
|
[ '203.0.113.0', true, 'IPv4 example' ],
|
|
|
|
|
|
[ '2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff', true, 'IPv6 example' ],
|
2014-07-01 16:31:07 +00:00
|
|
|
|
// Not valid IPs but classified as such by MediaWiki for negated asserting
|
|
|
|
|
|
// of whether this might be the identifier of a logged-out user or whether
|
|
|
|
|
|
// to allow usernames like it.
|
2016-02-17 09:09:32 +00:00
|
|
|
|
[ '300.300.300.300', true, 'Looks too much like an IPv4 address' ],
|
|
|
|
|
|
[ '203.0.113.xxx', true, 'Assigned by UseMod to cloaked logged-out users' ],
|
|
|
|
|
|
];
|
2014-07-01 16:31:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-10-11 10:25:58 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @dataProvider provideUserNames
|
2013-10-21 21:09:13 +00:00
|
|
|
|
* @covers User::isValidUserName
|
2011-10-11 10:25:58 +00:00
|
|
|
|
*/
|
|
|
|
|
|
public function testIsValidUserName( $username, $result, $message ) {
|
|
|
|
|
|
$this->assertEquals( $this->user->isValidUserName( $username ), $result, $message );
|
2011-10-11 09:17:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
|
public static function provideUserNames() {
|
2016-02-17 09:09:32 +00:00
|
|
|
|
return [
|
|
|
|
|
|
[ '', false, 'Empty string' ],
|
|
|
|
|
|
[ ' ', false, 'Blank space' ],
|
|
|
|
|
|
[ 'abcd', false, 'Starts with small letter' ],
|
|
|
|
|
|
[ 'Ab/cd', false, 'Contains slash' ],
|
|
|
|
|
|
[ 'Ab cd', true, 'Whitespace' ],
|
|
|
|
|
|
[ '192.168.1.1', false, 'IP' ],
|
2017-04-21 16:17:59 +00:00
|
|
|
|
[ '116.17.184.5/32', false, 'IP range' ],
|
|
|
|
|
|
[ '::e:f:2001/96', false, 'IPv6 range' ],
|
2016-02-17 09:09:32 +00:00
|
|
|
|
[ 'User:Abcd', false, 'Reserved Namespace' ],
|
|
|
|
|
|
[ '12abcd232', true, 'Starts with Numbers' ],
|
|
|
|
|
|
[ '?abcd', true, 'Start with ? mark' ],
|
|
|
|
|
|
[ '#abcd', false, 'Start with #' ],
|
|
|
|
|
|
[ 'Abcdകഖഗഘ', true, ' Mixed scripts' ],
|
|
|
|
|
|
[ 'ജോസ്തോമസ്', false, 'ZWNJ- Format control character' ],
|
|
|
|
|
|
[ 'Ab cd', false, ' Ideographic space' ],
|
|
|
|
|
|
[ '300.300.300.300', false, 'Looks too much like an IPv4 address' ],
|
|
|
|
|
|
[ '302.113.311.900', false, 'Looks too much like an IPv4 address' ],
|
|
|
|
|
|
[ '203.0.113.xxx', false, 'Reserved for usage by UseMod for cloaked logged-out users' ],
|
|
|
|
|
|
];
|
2011-10-11 10:25:58 +00:00
|
|
|
|
}
|
2012-08-13 08:18:18 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Test, if for all rights a right- message exist,
|
|
|
|
|
|
* which is used on Special:ListGroupRights as help text
|
|
|
|
|
|
* Extensions and core
|
2017-12-28 08:38:21 +00:00
|
|
|
|
*
|
|
|
|
|
|
* @coversNothing
|
2012-08-13 08:18:18 +00:00
|
|
|
|
*/
|
|
|
|
|
|
public function testAllRightsWithMessage() {
|
2014-07-01 16:31:07 +00:00
|
|
|
|
// Getting all user rights, for core: User::$mCoreRights, for extensions: $wgAvailableRights
|
2012-08-13 08:18:18 +00:00
|
|
|
|
$allRights = User::getAllRights();
|
|
|
|
|
|
$allMessageKeys = Language::getMessageKeysFor( 'en' );
|
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$rightsWithMessage = [];
|
2012-08-13 08:18:18 +00:00
|
|
|
|
foreach ( $allMessageKeys as $message ) {
|
|
|
|
|
|
// === 0: must be at beginning of string (position 0)
|
|
|
|
|
|
if ( strpos( $message, 'right-' ) === 0 ) {
|
|
|
|
|
|
$rightsWithMessage[] = substr( $message, strlen( 'right-' ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sort( $allRights );
|
|
|
|
|
|
sort( $rightsWithMessage );
|
|
|
|
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
|
$allRights,
|
|
|
|
|
|
$rightsWithMessage,
|
|
|
|
|
|
'Each user rights (core/extensions) has a corresponding right- message.'
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2012-10-18 03:03:10 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Test User::editCount
|
2012-10-26 11:02:48 +00:00
|
|
|
|
* @group medium
|
2013-10-21 21:09:13 +00:00
|
|
|
|
* @covers User::getEditCount
|
2012-10-18 03:03:10 +00:00
|
|
|
|
*/
|
2016-08-03 15:26:47 +00:00
|
|
|
|
public function testGetEditCount() {
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = $this->getMutableTestUser()->getUser();
|
2012-10-18 03:03:10 +00:00
|
|
|
|
|
2012-10-26 11:02:48 +00:00
|
|
|
|
// let the user have a few (3) edits
|
2012-11-08 17:05:46 +00:00
|
|
|
|
$page = WikiPage::factory( Title::newFromText( 'Help:UserTest_EditCount' ) );
|
2013-02-14 11:36:35 +00:00
|
|
|
|
for ( $i = 0; $i < 3; $i++ ) {
|
2016-09-15 20:13:22 +00:00
|
|
|
|
$page->doEditContent(
|
|
|
|
|
|
ContentHandler::makeContent( (string)$i, $page->getTitle() ),
|
|
|
|
|
|
'test',
|
|
|
|
|
|
0,
|
|
|
|
|
|
false,
|
|
|
|
|
|
$user
|
|
|
|
|
|
);
|
2012-10-18 03:03:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
|
$this->assertEquals(
|
|
|
|
|
|
3,
|
|
|
|
|
|
$user->getEditCount(),
|
|
|
|
|
|
'After three edits, the user edit count should be 3'
|
|
|
|
|
|
);
|
2012-10-18 03:03:10 +00:00
|
|
|
|
|
2016-08-03 15:26:47 +00:00
|
|
|
|
// increase the edit count
|
2012-10-18 03:03:10 +00:00
|
|
|
|
$user->incEditCount();
|
|
|
|
|
|
|
2014-04-24 12:50:36 +00:00
|
|
|
|
$this->assertEquals(
|
|
|
|
|
|
4,
|
|
|
|
|
|
$user->getEditCount(),
|
|
|
|
|
|
'After increasing the edit count manually, the user edit count should be 4'
|
|
|
|
|
|
);
|
2012-10-18 03:03:10 +00:00
|
|
|
|
}
|
2012-10-29 20:07:49 +00:00
|
|
|
|
|
2016-08-03 15:26:47 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Test User::editCount
|
|
|
|
|
|
* @group medium
|
|
|
|
|
|
* @covers User::getEditCount
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testGetEditCountForAnons() {
|
|
|
|
|
|
$user = User::newFromName( 'Anonymous' );
|
|
|
|
|
|
|
|
|
|
|
|
$this->assertNull(
|
|
|
|
|
|
$user->getEditCount(),
|
|
|
|
|
|
'Edit count starts null for anonymous users.'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
$user->incEditCount();
|
|
|
|
|
|
|
|
|
|
|
|
$this->assertNull(
|
|
|
|
|
|
$user->getEditCount(),
|
|
|
|
|
|
'Edit count remains null for anonymous users despite calls to increase it.'
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Test User::editCount
|
|
|
|
|
|
* @group medium
|
|
|
|
|
|
* @covers User::incEditCount
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testIncEditCount() {
|
|
|
|
|
|
$user = $this->getMutableTestUser()->getUser();
|
|
|
|
|
|
$user->incEditCount();
|
|
|
|
|
|
|
|
|
|
|
|
$reloadedUser = User::newFromId( $user->getId() );
|
|
|
|
|
|
$reloadedUser->incEditCount();
|
|
|
|
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
|
2,
|
|
|
|
|
|
$reloadedUser->getEditCount(),
|
|
|
|
|
|
'Increasing the edit count after a fresh load leaves the object up to date.'
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-10-29 20:07:49 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Test changing user options.
|
2013-10-21 21:09:13 +00:00
|
|
|
|
* @covers User::setOption
|
|
|
|
|
|
* @covers User::getOption
|
2012-10-29 20:07:49 +00:00
|
|
|
|
*/
|
|
|
|
|
|
public function testOptions() {
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = $this->getMutableTestUser()->getUser();
|
2012-10-29 20:07:49 +00:00
|
|
|
|
|
2014-09-20 16:56:04 +00:00
|
|
|
|
$user->setOption( 'userjs-someoption', 'test' );
|
2017-01-09 10:56:41 +00:00
|
|
|
|
$user->setOption( 'rclimit', 200 );
|
2012-10-29 20:07:49 +00:00
|
|
|
|
$user->saveSettings();
|
|
|
|
|
|
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = User::newFromName( $user->getName() );
|
2016-11-17 00:38:09 +00:00
|
|
|
|
$user->load( User::READ_LATEST );
|
|
|
|
|
|
$this->assertEquals( 'test', $user->getOption( 'userjs-someoption' ) );
|
2017-01-09 10:56:41 +00:00
|
|
|
|
$this->assertEquals( 200, $user->getOption( 'rclimit' ) );
|
2016-11-17 00:38:09 +00:00
|
|
|
|
|
|
|
|
|
|
$user = User::newFromName( $user->getName() );
|
|
|
|
|
|
MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache();
|
2014-09-20 16:56:04 +00:00
|
|
|
|
$this->assertEquals( 'test', $user->getOption( 'userjs-someoption' ) );
|
2017-01-09 10:56:41 +00:00
|
|
|
|
$this->assertEquals( 200, $user->getOption( 'rclimit' ) );
|
2012-10-29 20:07:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-02-20 23:45:58 +00:00
|
|
|
|
* T39963
|
2012-10-29 20:07:49 +00:00
|
|
|
|
* Make sure defaults are loaded when setOption is called.
|
2013-10-21 21:09:13 +00:00
|
|
|
|
* @covers User::loadOptions
|
2012-10-29 20:07:49 +00:00
|
|
|
|
*/
|
|
|
|
|
|
public function testAnonOptions() {
|
|
|
|
|
|
global $wgDefaultUserOptions;
|
2014-09-20 16:56:04 +00:00
|
|
|
|
$this->user->setOption( 'userjs-someoption', 'test' );
|
2017-01-09 10:56:41 +00:00
|
|
|
|
$this->assertEquals( $wgDefaultUserOptions['rclimit'], $this->user->getOption( 'rclimit' ) );
|
2014-09-20 16:56:04 +00:00
|
|
|
|
$this->assertEquals( 'test', $this->user->getOption( 'userjs-someoption' ) );
|
2012-10-29 20:07:49 +00:00
|
|
|
|
}
|
Password Expiration
Add functionality to expire users' passwords:
* Adds column to the user table to keep a password expiration
* Adds $wgPasswordExpirationDays, which will force users to reset
their passwords after a set number of days. By default, this set
to false, so passwords never expire.
* Adds a default grace period of 7 days, where if the user's password
is expired, they can still login, but are encouraged to reset their
password.
* Adds hook 'LoginPasswordResetMessage' to update reset message, in
case an extension wants to vary the message on a particular reset
event.
* Adds hook 'ResetPasswordExpiration' to allow extensions to change
the expiration date when the user resets their password. E.g., if
an extension wants to vary the expiration based on the user's group.
If the user is in the grace period, they get a password reset form
added to the login successful page. If an extension prevents showing
the login successful page (like CentralAuth), it should be updated to
show a password change form during the grace period. After the grace
period, the user will not be able to login without changing their
password.
Also prevents a successful reset if the user is "changing" their
password to their existing password.
No passwords will expire by default. Sites will have to call
User->expirePassword() from their own maintenance script to trigger a
password reset for a user.
Bug: 54997
Change-Id: I92a9fc63b409b182b1d7b48781d73fc7216f8061
2013-10-09 18:09:28 +00:00
|
|
|
|
|
2014-03-12 01:47:29 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Test password validity checks. There are 3 checks in core,
|
|
|
|
|
|
* - ensure the password meets the minimal length
|
|
|
|
|
|
* - ensure the password is not the same as the username
|
|
|
|
|
|
* - ensure the username/password combo isn't forbidden
|
|
|
|
|
|
* @covers User::checkPasswordValidity()
|
|
|
|
|
|
* @covers User::getPasswordValidity()
|
|
|
|
|
|
* @covers User::isValidPassword()
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testCheckPasswordValidity() {
|
2016-02-17 09:09:32 +00:00
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgPasswordPolicy' => [
|
|
|
|
|
|
'policies' => [
|
|
|
|
|
|
'sysop' => [
|
2015-04-23 01:48:48 +00:00
|
|
|
|
'MinimalPasswordLength' => 8,
|
|
|
|
|
|
'MinimumPasswordLengthToLogin' => 1,
|
|
|
|
|
|
'PasswordCannotMatchUsername' => 1,
|
2016-02-17 09:09:32 +00:00
|
|
|
|
],
|
|
|
|
|
|
'default' => [
|
2015-04-23 01:48:48 +00:00
|
|
|
|
'MinimalPasswordLength' => 6,
|
|
|
|
|
|
'PasswordCannotMatchUsername' => true,
|
|
|
|
|
|
'PasswordCannotMatchBlacklist' => true,
|
2016-05-18 09:19:20 +00:00
|
|
|
|
'MaximalPasswordLength' => 40,
|
2016-02-17 09:09:32 +00:00
|
|
|
|
],
|
|
|
|
|
|
],
|
|
|
|
|
|
'checks' => [
|
2015-04-23 01:48:48 +00:00
|
|
|
|
'MinimalPasswordLength' => 'PasswordPolicyChecks::checkMinimalPasswordLength',
|
|
|
|
|
|
'MinimumPasswordLengthToLogin' => 'PasswordPolicyChecks::checkMinimumPasswordLengthToLogin',
|
|
|
|
|
|
'PasswordCannotMatchUsername' => 'PasswordPolicyChecks::checkPasswordCannotMatchUsername',
|
|
|
|
|
|
'PasswordCannotMatchBlacklist' => 'PasswordPolicyChecks::checkPasswordCannotMatchBlacklist',
|
|
|
|
|
|
'MaximalPasswordLength' => 'PasswordPolicyChecks::checkMaximalPasswordLength',
|
2016-02-17 09:09:32 +00:00
|
|
|
|
],
|
|
|
|
|
|
],
|
|
|
|
|
|
] );
|
2015-04-23 01:48:48 +00:00
|
|
|
|
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = static::getTestUser()->getUser();
|
|
|
|
|
|
|
2014-03-12 01:47:29 +00:00
|
|
|
|
// Sanity
|
|
|
|
|
|
$this->assertTrue( $user->isValidPassword( 'Password1234' ) );
|
|
|
|
|
|
|
|
|
|
|
|
// Minimum length
|
|
|
|
|
|
$this->assertFalse( $user->isValidPassword( 'a' ) );
|
|
|
|
|
|
$this->assertFalse( $user->checkPasswordValidity( 'a' )->isGood() );
|
2014-12-26 16:29:15 +00:00
|
|
|
|
$this->assertTrue( $user->checkPasswordValidity( 'a' )->isOK() );
|
2014-03-12 01:47:29 +00:00
|
|
|
|
$this->assertEquals( 'passwordtooshort', $user->getPasswordValidity( 'a' ) );
|
|
|
|
|
|
|
2014-12-26 16:29:15 +00:00
|
|
|
|
// Maximum length
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$longPass = str_repeat( 'a', 41 );
|
2014-12-26 16:29:15 +00:00
|
|
|
|
$this->assertFalse( $user->isValidPassword( $longPass ) );
|
|
|
|
|
|
$this->assertFalse( $user->checkPasswordValidity( $longPass )->isGood() );
|
|
|
|
|
|
$this->assertFalse( $user->checkPasswordValidity( $longPass )->isOK() );
|
|
|
|
|
|
$this->assertEquals( 'passwordtoolong', $user->getPasswordValidity( $longPass ) );
|
|
|
|
|
|
|
2014-03-12 01:47:29 +00:00
|
|
|
|
// Matches username
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$this->assertFalse( $user->checkPasswordValidity( $user->getName() )->isGood() );
|
|
|
|
|
|
$this->assertTrue( $user->checkPasswordValidity( $user->getName() )->isOK() );
|
|
|
|
|
|
$this->assertEquals( 'password-name-match', $user->getPasswordValidity( $user->getName() ) );
|
2014-03-12 01:47:29 +00:00
|
|
|
|
|
|
|
|
|
|
// On the forbidden list
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = User::newFromName( 'Useruser' );
|
2014-03-12 01:47:29 +00:00
|
|
|
|
$this->assertFalse( $user->checkPasswordValidity( 'Passpass' )->isGood() );
|
|
|
|
|
|
$this->assertEquals( 'password-login-forbidden', $user->getPasswordValidity( 'Passpass' ) );
|
|
|
|
|
|
}
|
2014-08-25 18:24:10 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::getCanonicalName()
|
|
|
|
|
|
* @dataProvider provideGetCanonicalName
|
|
|
|
|
|
*/
|
2016-04-16 17:36:33 +00:00
|
|
|
|
public function testGetCanonicalName( $name, $expectedArray ) {
|
|
|
|
|
|
// fake interwiki map for the 'Interwiki prefix' testcase
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
|
|
|
|
|
'InterwikiLoadPrefix' => [
|
|
|
|
|
|
function ( $prefix, &$iwdata ) {
|
|
|
|
|
|
if ( $prefix === 'interwiki' ) {
|
|
|
|
|
|
$iwdata = [
|
|
|
|
|
|
'iw_url' => 'http://example.com/',
|
|
|
|
|
|
'iw_local' => 0,
|
|
|
|
|
|
'iw_trans' => 0,
|
|
|
|
|
|
];
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
2014-08-25 18:24:10 +00:00
|
|
|
|
foreach ( $expectedArray as $validate => $expected ) {
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
|
$expected,
|
2016-04-16 17:36:33 +00:00
|
|
|
|
User::getCanonicalName( $name, $validate === 'false' ? false : $validate ), $validate );
|
2014-08-25 18:24:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2014-09-18 01:28:26 +00:00
|
|
|
|
public static function provideGetCanonicalName() {
|
2016-02-17 09:09:32 +00:00
|
|
|
|
return [
|
2016-04-16 17:36:33 +00:00
|
|
|
|
'Leading space' => [ ' Leading space', [ 'creatable' => 'Leading space' ] ],
|
|
|
|
|
|
'Trailing space ' => [ 'Trailing space ', [ 'creatable' => 'Trailing space' ] ],
|
|
|
|
|
|
'Namespace prefix' => [ 'Talk:Username', [ 'creatable' => false, 'usable' => false,
|
|
|
|
|
|
'valid' => false, 'false' => 'Talk:Username' ] ],
|
|
|
|
|
|
'Interwiki prefix' => [ 'interwiki:Username', [ 'creatable' => false, 'usable' => false,
|
|
|
|
|
|
'valid' => false, 'false' => 'Interwiki:Username' ] ],
|
|
|
|
|
|
'With hash' => [ 'name with # hash', [ 'creatable' => false, 'usable' => false ] ],
|
|
|
|
|
|
'Multi spaces' => [ 'Multi spaces', [ 'creatable' => 'Multi spaces',
|
|
|
|
|
|
'usable' => 'Multi spaces' ] ],
|
|
|
|
|
|
'Lowercase' => [ 'lowercase', [ 'creatable' => 'Lowercase' ] ],
|
|
|
|
|
|
'Invalid character' => [ 'in[]valid', [ 'creatable' => false, 'usable' => false,
|
|
|
|
|
|
'valid' => false, 'false' => 'In[]valid' ] ],
|
|
|
|
|
|
'With slash' => [ 'with / slash', [ 'creatable' => false, 'usable' => false, 'valid' => false,
|
|
|
|
|
|
'false' => 'With / slash' ] ],
|
2016-02-17 09:09:32 +00:00
|
|
|
|
];
|
2014-08-25 18:24:10 +00:00
|
|
|
|
}
|
2014-12-11 08:59:28 +00:00
|
|
|
|
|
2015-01-13 18:25:41 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::equals
|
|
|
|
|
|
*/
|
2014-12-11 08:59:28 +00:00
|
|
|
|
public function testEquals() {
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$first = $this->getMutableTestUser()->getUser();
|
|
|
|
|
|
$second = User::newFromName( $first->getName() );
|
2014-12-11 08:59:28 +00:00
|
|
|
|
|
|
|
|
|
|
$this->assertTrue( $first->equals( $first ) );
|
|
|
|
|
|
$this->assertTrue( $first->equals( $second ) );
|
|
|
|
|
|
$this->assertTrue( $second->equals( $first ) );
|
|
|
|
|
|
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$third = $this->getMutableTestUser()->getUser();
|
|
|
|
|
|
$fourth = $this->getMutableTestUser()->getUser();
|
2014-12-11 08:59:28 +00:00
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $third->equals( $fourth ) );
|
|
|
|
|
|
$this->assertFalse( $fourth->equals( $third ) );
|
|
|
|
|
|
|
|
|
|
|
|
// Test users loaded from db with id
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = $this->getMutableTestUser()->getUser();
|
|
|
|
|
|
$fifth = User::newFromId( $user->getId() );
|
|
|
|
|
|
$sixth = User::newFromName( $user->getName() );
|
2014-12-11 08:59:28 +00:00
|
|
|
|
$this->assertTrue( $fifth->equals( $sixth ) );
|
|
|
|
|
|
}
|
2015-04-02 01:15:50 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::getId
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testGetId() {
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = static::getTestUser()->getUser();
|
2015-04-02 01:15:50 +00:00
|
|
|
|
$this->assertTrue( $user->getId() > 0 );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::isLoggedIn
|
|
|
|
|
|
* @covers User::isAnon
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testLoggedIn() {
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = $this->getMutableTestUser()->getUser();
|
2015-04-02 01:15:50 +00:00
|
|
|
|
$this->assertTrue( $user->isLoggedIn() );
|
|
|
|
|
|
$this->assertFalse( $user->isAnon() );
|
|
|
|
|
|
|
|
|
|
|
|
// Non-existent users are perceived as anonymous
|
|
|
|
|
|
$user = User::newFromName( 'UTNonexistent' );
|
|
|
|
|
|
$this->assertFalse( $user->isLoggedIn() );
|
|
|
|
|
|
$this->assertTrue( $user->isAnon() );
|
|
|
|
|
|
|
|
|
|
|
|
$user = new User;
|
|
|
|
|
|
$this->assertFalse( $user->isLoggedIn() );
|
|
|
|
|
|
$this->assertTrue( $user->isAnon() );
|
|
|
|
|
|
}
|
2015-04-07 20:50:00 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::checkAndSetTouched
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testCheckAndSetTouched() {
|
2016-05-18 09:19:20 +00:00
|
|
|
|
$user = $this->getMutableTestUser()->getUser();
|
|
|
|
|
|
$user = TestingAccessWrapper::newFromObject( $user );
|
2015-04-07 20:50:00 +00:00
|
|
|
|
$this->assertTrue( $user->isLoggedIn() );
|
|
|
|
|
|
|
|
|
|
|
|
$touched = $user->getDBTouched();
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
|
$user->checkAndSetTouched(), "checkAndSetTouched() succeded" );
|
|
|
|
|
|
$this->assertGreaterThan(
|
|
|
|
|
|
$touched, $user->getDBTouched(), "user_touched increased with casOnTouched()" );
|
|
|
|
|
|
|
|
|
|
|
|
$touched = $user->getDBTouched();
|
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
|
$user->checkAndSetTouched(), "checkAndSetTouched() succeded #2" );
|
|
|
|
|
|
$this->assertGreaterThan(
|
|
|
|
|
|
$touched, $user->getDBTouched(), "user_touched increased with casOnTouched() #2" );
|
|
|
|
|
|
}
|
2016-07-27 01:44:53 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::findUsersByGroup
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testFindUsersByGroup() {
|
|
|
|
|
|
$users = User::findUsersByGroup( [] );
|
|
|
|
|
|
$this->assertEquals( 0, iterator_count( $users ) );
|
|
|
|
|
|
|
|
|
|
|
|
$users = User::findUsersByGroup( 'foo' );
|
|
|
|
|
|
$this->assertEquals( 0, iterator_count( $users ) );
|
|
|
|
|
|
|
|
|
|
|
|
$user = $this->getMutableTestUser( [ 'foo' ] )->getUser();
|
|
|
|
|
|
$users = User::findUsersByGroup( 'foo' );
|
|
|
|
|
|
$this->assertEquals( 1, iterator_count( $users ) );
|
|
|
|
|
|
$users->rewind();
|
|
|
|
|
|
$this->assertTrue( $user->equals( $users->current() ) );
|
|
|
|
|
|
|
|
|
|
|
|
// arguments have OR relationship
|
|
|
|
|
|
$user2 = $this->getMutableTestUser( [ 'bar' ] )->getUser();
|
|
|
|
|
|
$users = User::findUsersByGroup( [ 'foo', 'bar' ] );
|
|
|
|
|
|
$this->assertEquals( 2, iterator_count( $users ) );
|
|
|
|
|
|
$users->rewind();
|
|
|
|
|
|
$this->assertTrue( $user->equals( $users->current() ) );
|
|
|
|
|
|
$users->next();
|
|
|
|
|
|
$this->assertTrue( $user2->equals( $users->current() ) );
|
|
|
|
|
|
|
|
|
|
|
|
// users are not duplicated
|
|
|
|
|
|
$user = $this->getMutableTestUser( [ 'baz', 'boom' ] )->getUser();
|
|
|
|
|
|
$users = User::findUsersByGroup( [ 'baz', 'boom' ] );
|
|
|
|
|
|
$this->assertEquals( 1, iterator_count( $users ) );
|
|
|
|
|
|
$users->rewind();
|
|
|
|
|
|
$this->assertTrue( $user->equals( $users->current() ) );
|
|
|
|
|
|
}
|
2013-02-07 21:56:54 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* When a user is autoblocked a cookie is set with which to track them
|
|
|
|
|
|
* in case they log out and change IP addresses.
|
|
|
|
|
|
* @link https://phabricator.wikimedia.org/T5233
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testAutoblockCookies() {
|
|
|
|
|
|
// Set up the bits of global configuration that we use.
|
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgCookieSetOnAutoblock' => true,
|
|
|
|
|
|
'wgCookiePrefix' => 'wmsitetitle',
|
2017-01-04 03:38:27 +00:00
|
|
|
|
'wgSecretKey' => MWCryptRand::generateHex( 64, true ),
|
2013-02-07 21:56:54 +00:00
|
|
|
|
] );
|
|
|
|
|
|
|
2017-09-18 18:57:17 +00:00
|
|
|
|
// Unregister the hooks for proper unit testing
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
|
|
|
|
|
'PerformRetroactiveAutoblock' => []
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
2013-02-07 21:56:54 +00:00
|
|
|
|
// 1. Log in a test user, and block them.
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$userBlocker = $this->getTestSysop()->getUser();
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$user1tmp = $this->getTestUser()->getUser();
|
|
|
|
|
|
$request1 = new FauxRequest();
|
|
|
|
|
|
$request1->getSession()->setUser( $user1tmp );
|
2016-12-20 12:08:38 +00:00
|
|
|
|
$expiryFiveHours = wfTimestamp() + ( 5 * 60 * 60 );
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$block = new Block( [
|
|
|
|
|
|
'enableAutoblock' => true,
|
2016-12-20 12:08:38 +00:00
|
|
|
|
'expiry' => wfTimestamp( TS_MW, $expiryFiveHours ),
|
2013-02-07 21:56:54 +00:00
|
|
|
|
] );
|
|
|
|
|
|
$block->setTarget( $user1tmp );
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$block->setBlocker( $userBlocker );
|
2017-09-18 18:03:04 +00:00
|
|
|
|
$res = $block->insert();
|
|
|
|
|
|
$this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$user1 = User::newFromSession( $request1 );
|
|
|
|
|
|
$user1->mBlock = $block;
|
|
|
|
|
|
$user1->load();
|
|
|
|
|
|
|
|
|
|
|
|
// Confirm that the block has been applied as required.
|
|
|
|
|
|
$this->assertTrue( $user1->isLoggedIn() );
|
|
|
|
|
|
$this->assertTrue( $user1->isBlocked() );
|
|
|
|
|
|
$this->assertEquals( Block::TYPE_USER, $block->getType() );
|
|
|
|
|
|
$this->assertTrue( $block->isAutoblocking() );
|
|
|
|
|
|
$this->assertGreaterThanOrEqual( 1, $block->getId() );
|
|
|
|
|
|
|
|
|
|
|
|
// Test for the desired cookie name, value, and expiry.
|
|
|
|
|
|
$cookies = $request1->response()->getCookies();
|
|
|
|
|
|
$this->assertArrayHasKey( 'wmsitetitleBlockID', $cookies );
|
2016-12-20 12:08:38 +00:00
|
|
|
|
$this->assertEquals( $expiryFiveHours, $cookies['wmsitetitleBlockID']['expire'] );
|
2017-01-04 03:38:27 +00:00
|
|
|
|
$cookieValue = Block::getIdFromCookieValue( $cookies['wmsitetitleBlockID']['value'] );
|
|
|
|
|
|
$this->assertEquals( $block->getId(), $cookieValue );
|
2013-02-07 21:56:54 +00:00
|
|
|
|
|
|
|
|
|
|
// 2. Create a new request, set the cookies, and see if the (anon) user is blocked.
|
|
|
|
|
|
$request2 = new FauxRequest();
|
2017-01-04 03:38:27 +00:00
|
|
|
|
$request2->setCookie( 'BlockID', $block->getCookieValue() );
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$user2 = User::newFromSession( $request2 );
|
|
|
|
|
|
$user2->load();
|
|
|
|
|
|
$this->assertNotEquals( $user1->getId(), $user2->getId() );
|
|
|
|
|
|
$this->assertNotEquals( $user1->getToken(), $user2->getToken() );
|
|
|
|
|
|
$this->assertTrue( $user2->isAnon() );
|
|
|
|
|
|
$this->assertFalse( $user2->isLoggedIn() );
|
|
|
|
|
|
$this->assertTrue( $user2->isBlocked() );
|
2017-09-18 18:57:17 +00:00
|
|
|
|
// Non-strict type-check.
|
|
|
|
|
|
$this->assertEquals( true, $user2->getBlock()->isAutoblocking(), 'Autoblock does not work' );
|
2013-02-07 21:56:54 +00:00
|
|
|
|
// 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() );
|
|
|
|
|
|
$this->assertEquals( $block->getExpiry(), $user2->getBlock()->getExpiry() );
|
|
|
|
|
|
|
|
|
|
|
|
// 3. Finally, set up a request as a new user, and the block should still be applied.
|
|
|
|
|
|
$user3tmp = $this->getTestUser()->getUser();
|
|
|
|
|
|
$request3 = new FauxRequest();
|
|
|
|
|
|
$request3->getSession()->setUser( $user3tmp );
|
|
|
|
|
|
$request3->setCookie( 'BlockID', $block->getId() );
|
|
|
|
|
|
$user3 = User::newFromSession( $request3 );
|
|
|
|
|
|
$user3->load();
|
|
|
|
|
|
$this->assertTrue( $user3->isLoggedIn() );
|
|
|
|
|
|
$this->assertTrue( $user3->isBlocked() );
|
|
|
|
|
|
$this->assertEquals( true, $user3->getBlock()->isAutoblocking() ); // Non-strict type-check.
|
|
|
|
|
|
|
|
|
|
|
|
// Clean up.
|
|
|
|
|
|
$block->delete();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Make sure that no cookie is set to track autoblocked users
|
|
|
|
|
|
* when $wgCookieSetOnAutoblock is false.
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testAutoblockCookiesDisabled() {
|
|
|
|
|
|
// Set up the bits of global configuration that we use.
|
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgCookieSetOnAutoblock' => false,
|
|
|
|
|
|
'wgCookiePrefix' => 'wm_no_cookies',
|
2017-01-04 03:38:27 +00:00
|
|
|
|
'wgSecretKey' => MWCryptRand::generateHex( 64, true ),
|
2013-02-07 21:56:54 +00:00
|
|
|
|
] );
|
|
|
|
|
|
|
2017-09-18 18:57:17 +00:00
|
|
|
|
// Unregister the hooks for proper unit testing
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
|
|
|
|
|
'PerformRetroactiveAutoblock' => []
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
2013-02-07 21:56:54 +00:00
|
|
|
|
// 1. Log in a test user, and block them.
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$userBlocker = $this->getTestSysop()->getUser();
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$testUser = $this->getTestUser()->getUser();
|
|
|
|
|
|
$request1 = new FauxRequest();
|
|
|
|
|
|
$request1->getSession()->setUser( $testUser );
|
|
|
|
|
|
$block = new Block( [ 'enableAutoblock' => true ] );
|
|
|
|
|
|
$block->setTarget( $testUser );
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$block->setBlocker( $userBlocker );
|
2017-09-18 18:03:04 +00:00
|
|
|
|
$res = $block->insert();
|
|
|
|
|
|
$this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$user = User::newFromSession( $request1 );
|
|
|
|
|
|
$user->mBlock = $block;
|
|
|
|
|
|
$user->load();
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Test that the cookie IS NOT present.
|
|
|
|
|
|
$this->assertTrue( $user->isLoggedIn() );
|
|
|
|
|
|
$this->assertTrue( $user->isBlocked() );
|
|
|
|
|
|
$this->assertEquals( Block::TYPE_USER, $block->getType() );
|
|
|
|
|
|
$this->assertTrue( $block->isAutoblocking() );
|
|
|
|
|
|
$this->assertGreaterThanOrEqual( 1, $user->getBlockId() );
|
|
|
|
|
|
$this->assertGreaterThanOrEqual( $block->getId(), $user->getBlockId() );
|
|
|
|
|
|
$cookies = $request1->response()->getCookies();
|
|
|
|
|
|
$this->assertArrayNotHasKey( 'wm_no_cookiesBlockID', $cookies );
|
|
|
|
|
|
|
|
|
|
|
|
// Clean up.
|
|
|
|
|
|
$block->delete();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* When a user is autoblocked and a cookie is set to track them, the expiry time of the cookie
|
2016-12-20 12:08:38 +00:00
|
|
|
|
* should match the block's expiry, to a maximum of 24 hours. If the expiry time is changed,
|
|
|
|
|
|
* the cookie's should change with it.
|
2013-02-07 21:56:54 +00:00
|
|
|
|
*/
|
|
|
|
|
|
public function testAutoblockCookieInfiniteExpiry() {
|
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgCookieSetOnAutoblock' => true,
|
|
|
|
|
|
'wgCookiePrefix' => 'wm_infinite_block',
|
2017-01-04 03:38:27 +00:00
|
|
|
|
'wgSecretKey' => MWCryptRand::generateHex( 64, true ),
|
2013-02-07 21:56:54 +00:00
|
|
|
|
] );
|
2017-09-18 18:57:17 +00:00
|
|
|
|
|
|
|
|
|
|
// Unregister the hooks for proper unit testing
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
|
|
|
|
|
'PerformRetroactiveAutoblock' => []
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
2013-02-07 21:56:54 +00:00
|
|
|
|
// 1. Log in a test user, and block them indefinitely.
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$userBlocker = $this->getTestSysop()->getUser();
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$user1Tmp = $this->getTestUser()->getUser();
|
|
|
|
|
|
$request1 = new FauxRequest();
|
|
|
|
|
|
$request1->getSession()->setUser( $user1Tmp );
|
|
|
|
|
|
$block = new Block( [ 'enableAutoblock' => true, 'expiry' => 'infinity' ] );
|
|
|
|
|
|
$block->setTarget( $user1Tmp );
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$block->setBlocker( $userBlocker );
|
2017-09-18 18:03:04 +00:00
|
|
|
|
$res = $block->insert();
|
|
|
|
|
|
$this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$user1 = User::newFromSession( $request1 );
|
|
|
|
|
|
$user1->mBlock = $block;
|
|
|
|
|
|
$user1->load();
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Test the cookie's expiry timestamp.
|
|
|
|
|
|
$this->assertTrue( $user1->isLoggedIn() );
|
|
|
|
|
|
$this->assertTrue( $user1->isBlocked() );
|
|
|
|
|
|
$this->assertEquals( Block::TYPE_USER, $block->getType() );
|
|
|
|
|
|
$this->assertTrue( $block->isAutoblocking() );
|
|
|
|
|
|
$this->assertGreaterThanOrEqual( 1, $user1->getBlockId() );
|
|
|
|
|
|
$cookies = $request1->response()->getCookies();
|
2016-12-20 12:08:38 +00:00
|
|
|
|
// Test the cookie's expiry to the nearest minute.
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$this->assertArrayHasKey( 'wm_infinite_blockBlockID', $cookies );
|
2016-12-20 12:08:38 +00:00
|
|
|
|
$expOneDay = wfTimestamp() + ( 24 * 60 * 60 );
|
2016-12-20 12:13:56 +00:00
|
|
|
|
// Check for expiry dates in a 10-second window, to account for slow testing.
|
2017-01-04 03:29:35 +00:00
|
|
|
|
$this->assertEquals(
|
|
|
|
|
|
$expOneDay,
|
|
|
|
|
|
$cookies['wm_infinite_blockBlockID']['expire'],
|
|
|
|
|
|
'Expiry date',
|
|
|
|
|
|
5.0
|
2016-12-20 12:13:56 +00:00
|
|
|
|
);
|
2013-02-07 21:56:54 +00:00
|
|
|
|
|
2016-12-20 12:08:38 +00:00
|
|
|
|
// 3. Change the block's expiry (to 2 hours), and the cookie's should be changed also.
|
|
|
|
|
|
$newExpiry = wfTimestamp() + 2 * 60 * 60;
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$block->mExpiry = wfTimestamp( TS_MW, $newExpiry );
|
|
|
|
|
|
$block->update();
|
|
|
|
|
|
$user2tmp = $this->getTestUser()->getUser();
|
|
|
|
|
|
$request2 = new FauxRequest();
|
|
|
|
|
|
$request2->getSession()->setUser( $user2tmp );
|
|
|
|
|
|
$user2 = User::newFromSession( $request2 );
|
|
|
|
|
|
$user2->mBlock = $block;
|
|
|
|
|
|
$user2->load();
|
|
|
|
|
|
$cookies = $request2->response()->getCookies();
|
2016-12-20 12:08:38 +00:00
|
|
|
|
$this->assertEquals( wfTimestamp( TS_MW, $newExpiry ), $block->getExpiry() );
|
2013-02-07 21:56:54 +00:00
|
|
|
|
$this->assertEquals( $newExpiry, $cookies['wm_infinite_blockBlockID']['expire'] );
|
|
|
|
|
|
|
|
|
|
|
|
// Clean up.
|
|
|
|
|
|
$block->delete();
|
|
|
|
|
|
}
|
2016-11-23 19:51:30 +00:00
|
|
|
|
|
|
|
|
|
|
public function testSoftBlockRanges() {
|
|
|
|
|
|
global $wgUser;
|
|
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgSoftBlockRanges' => [ '10.0.0.0/8' ],
|
|
|
|
|
|
'wgUser' => null,
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
|
|
// IP isn't in $wgSoftBlockRanges
|
|
|
|
|
|
$request = new FauxRequest();
|
|
|
|
|
|
$request->setIP( '192.168.0.1' );
|
|
|
|
|
|
$wgUser = User::newFromSession( $request );
|
|
|
|
|
|
$this->assertNull( $wgUser->getBlock() );
|
|
|
|
|
|
|
|
|
|
|
|
// IP is in $wgSoftBlockRanges
|
|
|
|
|
|
$request = new FauxRequest();
|
|
|
|
|
|
$request->setIP( '10.20.30.40' );
|
|
|
|
|
|
$wgUser = User::newFromSession( $request );
|
|
|
|
|
|
$block = $wgUser->getBlock();
|
|
|
|
|
|
$this->assertInstanceOf( Block::class, $block );
|
|
|
|
|
|
$this->assertSame( 'wgSoftBlockRanges', $block->getSystemBlockType() );
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure the block is really soft
|
|
|
|
|
|
$request->getSession()->setUser( $this->getTestUser()->getUser() );
|
|
|
|
|
|
$wgUser = User::newFromSession( $request );
|
|
|
|
|
|
$this->assertFalse( $wgUser->isAnon(), 'sanity check' );
|
|
|
|
|
|
$this->assertNull( $wgUser->getBlock() );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-01-04 03:38:27 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Test that a modified BlockID cookie doesn't actually load the relevant block (T152951).
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testAutoblockCookieInauthentic() {
|
|
|
|
|
|
// Set up the bits of global configuration that we use.
|
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgCookieSetOnAutoblock' => true,
|
|
|
|
|
|
'wgCookiePrefix' => 'wmsitetitle',
|
|
|
|
|
|
'wgSecretKey' => MWCryptRand::generateHex( 64, true ),
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
2017-09-18 18:57:17 +00:00
|
|
|
|
// Unregister the hooks for proper unit testing
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
|
|
|
|
|
'PerformRetroactiveAutoblock' => []
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
2017-01-04 03:38:27 +00:00
|
|
|
|
// 1. Log in a blocked test user.
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$userBlocker = $this->getTestSysop()->getUser();
|
2017-01-04 03:38:27 +00:00
|
|
|
|
$user1tmp = $this->getTestUser()->getUser();
|
|
|
|
|
|
$request1 = new FauxRequest();
|
|
|
|
|
|
$request1->getSession()->setUser( $user1tmp );
|
|
|
|
|
|
$block = new Block( [ 'enableAutoblock' => true ] );
|
|
|
|
|
|
$block->setTarget( $user1tmp );
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$block->setBlocker( $userBlocker );
|
2017-09-18 18:03:04 +00:00
|
|
|
|
$res = $block->insert();
|
|
|
|
|
|
$this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
|
2017-01-04 03:38:27 +00:00
|
|
|
|
$user1 = User::newFromSession( $request1 );
|
|
|
|
|
|
$user1->mBlock = $block;
|
|
|
|
|
|
$user1->load();
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Create a new request, set the cookie to an invalid value, and make sure the (anon)
|
|
|
|
|
|
// user not blocked.
|
|
|
|
|
|
$request2 = new FauxRequest();
|
|
|
|
|
|
$request2->setCookie( 'BlockID', $block->getId() . '!zzzzzzz' );
|
|
|
|
|
|
$user2 = User::newFromSession( $request2 );
|
|
|
|
|
|
$user2->load();
|
|
|
|
|
|
$this->assertTrue( $user2->isAnon() );
|
|
|
|
|
|
$this->assertFalse( $user2->isLoggedIn() );
|
|
|
|
|
|
$this->assertFalse( $user2->isBlocked() );
|
|
|
|
|
|
|
|
|
|
|
|
// Clean up.
|
|
|
|
|
|
$block->delete();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* The BlockID cookie is normally verified with a HMAC, but not if wgSecretKey is not set.
|
|
|
|
|
|
* This checks that a non-authenticated cookie still works.
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testAutoblockCookieNoSecretKey() {
|
|
|
|
|
|
// Set up the bits of global configuration that we use.
|
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgCookieSetOnAutoblock' => true,
|
|
|
|
|
|
'wgCookiePrefix' => 'wmsitetitle',
|
|
|
|
|
|
'wgSecretKey' => null,
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
2017-09-18 18:57:17 +00:00
|
|
|
|
// Unregister the hooks for proper unit testing
|
|
|
|
|
|
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
|
|
|
|
|
'PerformRetroactiveAutoblock' => []
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
2017-01-04 03:38:27 +00:00
|
|
|
|
// 1. Log in a blocked test user.
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$userBlocker = $this->getTestSysop()->getUser();
|
2017-01-04 03:38:27 +00:00
|
|
|
|
$user1tmp = $this->getTestUser()->getUser();
|
|
|
|
|
|
$request1 = new FauxRequest();
|
|
|
|
|
|
$request1->getSession()->setUser( $user1tmp );
|
|
|
|
|
|
$block = new Block( [ 'enableAutoblock' => true ] );
|
|
|
|
|
|
$block->setTarget( $user1tmp );
|
2017-09-18 18:57:17 +00:00
|
|
|
|
$block->setBlocker( $userBlocker );
|
2017-09-18 18:03:04 +00:00
|
|
|
|
$res = $block->insert();
|
|
|
|
|
|
$this->assertTrue( (bool)$res['id'], 'Failed to insert block' );
|
2017-01-04 03:38:27 +00:00
|
|
|
|
$user1 = User::newFromSession( $request1 );
|
|
|
|
|
|
$user1->mBlock = $block;
|
|
|
|
|
|
$user1->load();
|
|
|
|
|
|
$this->assertTrue( $user1->isBlocked() );
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Create a new request, set the cookie to just the block ID, and the user should
|
|
|
|
|
|
// still get blocked when they log in again.
|
|
|
|
|
|
$request2 = new FauxRequest();
|
|
|
|
|
|
$request2->setCookie( 'BlockID', $block->getId() );
|
|
|
|
|
|
$user2 = User::newFromSession( $request2 );
|
|
|
|
|
|
$user2->load();
|
|
|
|
|
|
$this->assertNotEquals( $user1->getId(), $user2->getId() );
|
|
|
|
|
|
$this->assertNotEquals( $user1->getToken(), $user2->getToken() );
|
|
|
|
|
|
$this->assertTrue( $user2->isAnon() );
|
|
|
|
|
|
$this->assertFalse( $user2->isLoggedIn() );
|
|
|
|
|
|
$this->assertTrue( $user2->isBlocked() );
|
|
|
|
|
|
$this->assertEquals( true, $user2->getBlock()->isAutoblocking() ); // Non-strict type-check.
|
|
|
|
|
|
|
|
|
|
|
|
// Clean up.
|
|
|
|
|
|
$block->delete();
|
|
|
|
|
|
}
|
2017-02-02 01:23:01 +00:00
|
|
|
|
|
2017-12-25 07:27:12 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::isPingLimitable
|
|
|
|
|
|
*/
|
2017-02-02 01:23:01 +00:00
|
|
|
|
public function testIsPingLimitable() {
|
|
|
|
|
|
$request = new FauxRequest();
|
|
|
|
|
|
$request->setIP( '1.2.3.4' );
|
|
|
|
|
|
$user = User::newFromSession( $request );
|
|
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals( 'wgRateLimitsExcludedIPs', [] );
|
|
|
|
|
|
$this->assertTrue( $user->isPingLimitable() );
|
|
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals( 'wgRateLimitsExcludedIPs', [ '1.2.3.4' ] );
|
|
|
|
|
|
$this->assertFalse( $user->isPingLimitable() );
|
|
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals( 'wgRateLimitsExcludedIPs', [ '1.2.3.0/8' ] );
|
|
|
|
|
|
$this->assertFalse( $user->isPingLimitable() );
|
|
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals( 'wgRateLimitsExcludedIPs', [] );
|
|
|
|
|
|
$noRateLimitUser = $this->getMockBuilder( User::class )->disableOriginalConstructor()
|
|
|
|
|
|
->setMethods( [ 'getIP', 'getRights' ] )->getMock();
|
|
|
|
|
|
$noRateLimitUser->expects( $this->any() )->method( 'getIP' )->willReturn( '1.2.3.4' );
|
|
|
|
|
|
$noRateLimitUser->expects( $this->any() )->method( 'getRights' )->willReturn( [ 'noratelimit' ] );
|
|
|
|
|
|
$this->assertFalse( $noRateLimitUser->isPingLimitable() );
|
|
|
|
|
|
}
|
2017-02-10 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
|
public function provideExperienceLevel() {
|
|
|
|
|
|
return [
|
|
|
|
|
|
[ 2, 2, 'newcomer' ],
|
|
|
|
|
|
[ 12, 3, 'newcomer' ],
|
|
|
|
|
|
[ 8, 5, 'newcomer' ],
|
|
|
|
|
|
[ 15, 10, 'learner' ],
|
|
|
|
|
|
[ 450, 20, 'learner' ],
|
|
|
|
|
|
[ 460, 33, 'learner' ],
|
|
|
|
|
|
[ 525, 28, 'learner' ],
|
|
|
|
|
|
[ 538, 33, 'experienced' ],
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-25 07:27:12 +00:00
|
|
|
|
* @covers User::getExperienceLevel
|
2017-02-10 14:18:02 +00:00
|
|
|
|
* @dataProvider provideExperienceLevel
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testExperienceLevel( $editCount, $memberSince, $expLevel ) {
|
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
|
'wgLearnerEdits' => 10,
|
|
|
|
|
|
'wgLearnerMemberSince' => 4,
|
|
|
|
|
|
'wgExperiencedUserEdits' => 500,
|
|
|
|
|
|
'wgExperiencedUserMemberSince' => 30,
|
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
|
|
$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 );
|
|
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $expLevel, $user->getExperienceLevel() );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-25 07:27:12 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers User::getExperienceLevel
|
|
|
|
|
|
*/
|
2017-02-10 14:18:02 +00:00
|
|
|
|
public function testExperienceLevelAnon() {
|
|
|
|
|
|
$user = User::newFromName( '10.11.12.13', false );
|
|
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $user->getExperienceLevel() );
|
|
|
|
|
|
}
|
2017-04-15 23:52:23 +00:00
|
|
|
|
|
|
|
|
|
|
public static function provideIsLocallBlockedProxy() {
|
|
|
|
|
|
return [
|
|
|
|
|
|
[ '1.2.3.4', '1.2.3.4' ],
|
|
|
|
|
|
[ '1.2.3.4', '1.2.3.0/16' ],
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @dataProvider provideIsLocallBlockedProxy
|
|
|
|
|
|
* @covers User::isLocallyBlockedProxy
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testIsLocallyBlockedProxy( $ip, $blockListEntry ) {
|
|
|
|
|
|
$this->setMwGlobals(
|
|
|
|
|
|
'wgProxyList', []
|
|
|
|
|
|
);
|
|
|
|
|
|
$this->assertFalse( User::isLocallyBlockedProxy( $ip ) );
|
|
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals(
|
|
|
|
|
|
'wgProxyList',
|
|
|
|
|
|
[
|
|
|
|
|
|
$blockListEntry
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
$this->assertTrue( User::isLocallyBlockedProxy( $ip ) );
|
|
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals(
|
|
|
|
|
|
'wgProxyList',
|
|
|
|
|
|
[
|
|
|
|
|
|
'test' => $blockListEntry
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
$this->assertTrue( User::isLocallyBlockedProxy( $ip ) );
|
|
|
|
|
|
|
|
|
|
|
|
$this->hideDeprecated(
|
|
|
|
|
|
'IP addresses in the keys of $wgProxyList (found the following IP ' .
|
|
|
|
|
|
'addresses in keys: ' . $blockListEntry . ', please move them to values)'
|
|
|
|
|
|
);
|
|
|
|
|
|
$this->setMwGlobals(
|
|
|
|
|
|
'wgProxyList',
|
|
|
|
|
|
[
|
|
|
|
|
|
$blockListEntry => 'test'
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
$this->assertTrue( User::isLocallyBlockedProxy( $ip ) );
|
|
|
|
|
|
}
|
2011-07-19 21:41:25 +00:00
|
|
|
|
}
|