2010-12-28 19:12:27 +00:00
|
|
|
<?php
|
|
|
|
|
|
2019-04-11 19:54:10 +00:00
|
|
|
use MediaWiki\Block\BlockRestrictionStore;
|
2019-05-13 14:18:07 +00:00
|
|
|
use MediaWiki\Block\DatabaseBlock;
|
2018-10-30 18:19:22 +00:00
|
|
|
use MediaWiki\Block\Restriction\NamespaceRestriction;
|
2020-01-10 00:00:51 +00:00
|
|
|
use MediaWiki\Block\Restriction\PageRestriction;
|
2019-04-11 19:54:10 +00:00
|
|
|
use MediaWiki\MediaWikiServices;
|
2021-03-19 13:56:13 +00:00
|
|
|
use MediaWiki\User\UserIdentity;
|
|
|
|
|
use MediaWiki\User\UserIdentityValue;
|
2019-06-25 18:53:15 +00:00
|
|
|
use Wikimedia\IPUtils;
|
2018-08-16 04:55:55 +00:00
|
|
|
|
2010-12-29 15:01:47 +00:00
|
|
|
/**
|
|
|
|
|
* @group Database
|
2011-10-31 17:00:29 +00:00
|
|
|
* @group Blocking
|
2019-05-13 14:18:07 +00:00
|
|
|
* @coversDefaultClass \MediaWiki\Block\DatabaseBlock
|
2010-12-29 15:01:47 +00:00
|
|
|
*/
|
2019-05-13 14:18:07 +00:00
|
|
|
class DatabaseBlockTest extends MediaWikiLangTestCase {
|
2011-06-03 06:22:18 +00:00
|
|
|
|
2017-10-25 17:22:32 +00:00
|
|
|
/**
|
2021-03-19 13:56:13 +00:00
|
|
|
* @return UserIdentity
|
2017-10-25 17:22:32 +00:00
|
|
|
*/
|
|
|
|
|
private function getUserForBlocking() {
|
|
|
|
|
$testUser = $this->getMutableTestUser();
|
|
|
|
|
$user = $testUser->getUser();
|
|
|
|
|
$user->addToDatabase();
|
|
|
|
|
TestUser::setPasswordForUser( $user, 'UTBlockeePassword' );
|
|
|
|
|
$user->saveSettings();
|
2021-03-19 13:56:13 +00:00
|
|
|
return $testUser->getUserIdentity();
|
2017-10-25 17:22:32 +00:00
|
|
|
}
|
2011-06-15 20:43:24 +00:00
|
|
|
|
2017-10-25 17:22:32 +00:00
|
|
|
/**
|
2021-03-19 13:56:13 +00:00
|
|
|
* @param UserIdentity $user
|
2017-10-25 17:22:32 +00:00
|
|
|
*
|
2019-05-13 14:18:07 +00:00
|
|
|
* @return DatabaseBlock
|
2017-10-25 17:22:32 +00:00
|
|
|
* @throws MWException
|
|
|
|
|
*/
|
2021-03-19 13:56:13 +00:00
|
|
|
private function addBlockForUser( UserIdentity $user ) {
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
2011-06-15 20:43:24 +00:00
|
|
|
// Delete the last round's block if it's still there
|
2021-03-19 13:56:13 +00:00
|
|
|
$oldBlock = DatabaseBlock::newFromTarget( $user );
|
2011-06-15 20:43:24 +00:00
|
|
|
if ( $oldBlock ) {
|
|
|
|
|
// An old block will prevent our new one from saving.
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $oldBlock );
|
2011-06-15 20:43:24 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$blockOptions = [
|
2017-10-25 17:22:32 +00:00
|
|
|
'address' => $user->getName(),
|
2016-03-18 13:55:54 +00:00
|
|
|
'user' => $user->getId(),
|
2021-06-02 09:44:38 +00:00
|
|
|
'by' => $this->getTestSysop()->getUser(),
|
2014-05-22 14:45:46 +00:00
|
|
|
'reason' => 'Parce que',
|
|
|
|
|
'expiry' => time() + 100500,
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( $blockOptions );
|
2010-12-28 19:12:27 +00:00
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->insertBlock( $block );
|
2011-05-28 21:25:29 +00:00
|
|
|
// save up ID for use in assertion. Since ID is an autoincrement,
|
|
|
|
|
// its value might change depending on the order the tests are run.
|
|
|
|
|
// ApiBlockTest insert its own blocks!
|
2017-10-25 17:22:32 +00:00
|
|
|
if ( !$block->getId() ) {
|
2011-06-15 20:43:24 +00:00
|
|
|
throw new MWException( "Failed to insert block for BlockTest; old leftover block remaining?" );
|
|
|
|
|
}
|
2013-03-30 17:05:15 +00:00
|
|
|
|
|
|
|
|
$this->addXffBlocks();
|
2011-05-28 21:25:29 +00:00
|
|
|
|
2017-10-25 17:22:32 +00:00
|
|
|
return $block;
|
2011-05-28 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-24 10:54:02 +00:00
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::newFromTarget
|
2013-10-24 10:54:02 +00:00
|
|
|
*/
|
|
|
|
|
public function testINewFromTargetReturnsCorrectBlock() {
|
2017-10-25 17:22:32 +00:00
|
|
|
$user = $this->getUserForBlocking();
|
|
|
|
|
$block = $this->addBlockForUser( $user );
|
|
|
|
|
|
2014-04-24 09:57:41 +00:00
|
|
|
$this->assertTrue(
|
2019-05-13 14:18:07 +00:00
|
|
|
$block->equals( DatabaseBlock::newFromTarget( $user->getName() ) ),
|
2014-04-24 09:57:41 +00:00
|
|
|
"newFromTarget() returns the same block as the one that was made"
|
|
|
|
|
);
|
2013-10-24 10:54:02 +00:00
|
|
|
}
|
2012-04-10 00:12:06 +00:00
|
|
|
|
2013-10-24 10:54:02 +00:00
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::newFromID
|
2013-10-24 10:54:02 +00:00
|
|
|
*/
|
|
|
|
|
public function testINewFromIDReturnsCorrectBlock() {
|
2017-10-25 17:22:32 +00:00
|
|
|
$user = $this->getUserForBlocking();
|
|
|
|
|
$block = $this->addBlockForUser( $user );
|
|
|
|
|
|
2014-04-24 09:57:41 +00:00
|
|
|
$this->assertTrue(
|
2019-05-13 14:18:07 +00:00
|
|
|
$block->equals( DatabaseBlock::newFromID( $block->getId() ) ),
|
2014-04-24 09:57:41 +00:00
|
|
|
"newFromID() returns the same block as the one that was made"
|
|
|
|
|
);
|
2010-12-28 19:12:27 +00:00
|
|
|
}
|
2011-06-26 20:04:38 +00:00
|
|
|
|
2010-12-28 19:27:34 +00:00
|
|
|
/**
|
2017-02-20 23:45:58 +00:00
|
|
|
* per T28425
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::__construct
|
2010-12-28 19:27:34 +00:00
|
|
|
*/
|
2018-08-18 13:51:29 +00:00
|
|
|
public function testT28425BlockTimestampDefaultsToTime() {
|
2017-10-25 17:22:32 +00:00
|
|
|
$user = $this->getUserForBlocking();
|
|
|
|
|
$block = $this->addBlockForUser( $user );
|
|
|
|
|
$madeAt = wfTimestamp( TS_MW );
|
|
|
|
|
|
2011-08-18 06:23:44 +00:00
|
|
|
// delta to stop one-off errors when things happen to go over a second mark.
|
2019-03-22 15:16:40 +00:00
|
|
|
$delta = abs( $madeAt - $block->getTimestamp() );
|
2014-04-24 09:57:41 +00:00
|
|
|
$this->assertLessThan(
|
|
|
|
|
2,
|
|
|
|
|
$delta,
|
|
|
|
|
"If no timestamp is specified, the block is recorded as time()"
|
|
|
|
|
);
|
2010-12-28 19:27:34 +00:00
|
|
|
}
|
2010-12-28 19:12:27 +00:00
|
|
|
|
2011-05-24 21:04:50 +00:00
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* CheckUser since being changed to use DatabaseBlock::newFromTarget started failing
|
|
|
|
|
* because the new function didn't accept empty strings like DatabaseBlock::load()
|
2017-02-20 23:45:58 +00:00
|
|
|
* had. Regression T31116.
|
2011-05-24 21:04:50 +00:00
|
|
|
*
|
2018-08-18 13:51:29 +00:00
|
|
|
* @dataProvider provideT31116Data
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::newFromTarget
|
2011-05-24 21:04:50 +00:00
|
|
|
*/
|
2018-08-18 13:51:29 +00:00
|
|
|
public function testT31116NewFromTargetWithEmptyIp( $vagueTarget ) {
|
2017-10-25 17:22:32 +00:00
|
|
|
$user = $this->getUserForBlocking();
|
|
|
|
|
$initialBlock = $this->addBlockForUser( $user );
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = DatabaseBlock::newFromTarget( $user->getName(), $vagueTarget );
|
2017-10-25 17:22:32 +00:00
|
|
|
|
2014-04-24 09:57:41 +00:00
|
|
|
$this->assertTrue(
|
2017-10-25 17:22:32 +00:00
|
|
|
$initialBlock->equals( $block ),
|
2014-04-24 09:57:41 +00:00
|
|
|
"newFromTarget() returns the same block as the one that was made when "
|
|
|
|
|
. "given empty vagueTarget param " . var_export( $vagueTarget, true )
|
|
|
|
|
);
|
2011-05-24 21:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
2018-08-18 13:51:29 +00:00
|
|
|
public static function provideT31116Data() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ null ],
|
|
|
|
|
[ '' ],
|
|
|
|
|
[ false ]
|
|
|
|
|
];
|
2011-05-24 21:04:50 +00:00
|
|
|
}
|
2012-04-10 00:12:06 +00:00
|
|
|
|
2019-03-08 23:08:09 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideNewFromTargetRangeBlocks
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::newFromTarget
|
2019-03-08 23:08:09 +00:00
|
|
|
*/
|
|
|
|
|
public function testNewFromTargetRangeBlocks( $targets, $ip, $expectedTarget ) {
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
2019-03-08 23:08:09 +00:00
|
|
|
$blocker = $this->getTestSysop()->getUser();
|
|
|
|
|
|
|
|
|
|
foreach ( $targets as $target ) {
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock();
|
2019-03-08 23:08:09 +00:00
|
|
|
$block->setTarget( $target );
|
|
|
|
|
$block->setBlocker( $blocker );
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->insertBlock( $block );
|
2019-03-08 23:08:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Should find the block with the narrowest range
|
2021-03-19 13:56:13 +00:00
|
|
|
$blockTarget = DatabaseBlock::newFromTarget( $this->getTestUser()->getUserIdentity(), $ip )->getTarget();
|
2019-03-08 23:08:09 +00:00
|
|
|
$this->assertSame(
|
|
|
|
|
$blockTarget instanceof User ? $blockTarget->getName() : $blockTarget,
|
|
|
|
|
$expectedTarget
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
foreach ( $targets as $target ) {
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = DatabaseBlock::newFromTarget( $target );
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2019-03-08 23:08:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-09 18:24:07 +00:00
|
|
|
public function provideNewFromTargetRangeBlocks() {
|
2019-03-08 23:08:09 +00:00
|
|
|
return [
|
|
|
|
|
'Blocks to IPv4 ranges' => [
|
|
|
|
|
[ '0.0.0.0/20', '0.0.0.0/30', '0.0.0.0/25' ],
|
|
|
|
|
'0.0.0.0',
|
|
|
|
|
'0.0.0.0/30'
|
|
|
|
|
],
|
|
|
|
|
'Blocks to IPv6 ranges' => [
|
|
|
|
|
[ '0:0:0:0:0:0:0:0/20', '0:0:0:0:0:0:0:0/30', '0:0:0:0:0:0:0:0/25' ],
|
|
|
|
|
'0:0:0:0:0:0:0:0',
|
|
|
|
|
'0:0:0:0:0:0:0:0/30'
|
|
|
|
|
],
|
|
|
|
|
'Blocks to wide IPv4 range and IP' => [
|
|
|
|
|
[ '0.0.0.0/16', '0.0.0.0' ],
|
|
|
|
|
'0.0.0.0',
|
|
|
|
|
'0.0.0.0'
|
|
|
|
|
],
|
|
|
|
|
'Blocks to narrow IPv4 range and IP' => [
|
|
|
|
|
[ '0.0.0.0/31', '0.0.0.0' ],
|
|
|
|
|
'0.0.0.0',
|
|
|
|
|
'0.0.0.0'
|
|
|
|
|
],
|
2019-05-08 17:49:18 +00:00
|
|
|
'Blocks to wide IPv6 range and IP' => [
|
|
|
|
|
[ '0:0:0:0:0:0:0:0/19', '0:0:0:0:0:0:0:0' ],
|
|
|
|
|
'0:0:0:0:0:0:0:0',
|
|
|
|
|
'0:0:0:0:0:0:0:0'
|
|
|
|
|
],
|
2019-03-08 23:08:09 +00:00
|
|
|
'Blocks to narrow IPv6 range and IP' => [
|
|
|
|
|
[ '0:0:0:0:0:0:0:0/127', '0:0:0:0:0:0:0:0' ],
|
|
|
|
|
'0:0:0:0:0:0:0:0',
|
|
|
|
|
'0:0:0:0:0:0:0:0'
|
|
|
|
|
],
|
2019-05-08 17:49:18 +00:00
|
|
|
'Blocks to wide IPv6 range and IP, large numbers' => [
|
|
|
|
|
[ '2000:DEAD:BEEF:A:0:0:0:0/19', '2000:DEAD:BEEF:A:0:0:0:0' ],
|
|
|
|
|
'2000:DEAD:BEEF:A:0:0:0:0',
|
|
|
|
|
'2000:DEAD:BEEF:A:0:0:0:0'
|
|
|
|
|
],
|
|
|
|
|
'Blocks to narrow IPv6 range and IP, large numbers' => [
|
|
|
|
|
[ '2000:DEAD:BEEF:A:0:0:0:0/127', '2000:DEAD:BEEF:A:0:0:0:0' ],
|
|
|
|
|
'2000:DEAD:BEEF:A:0:0:0:0',
|
|
|
|
|
'2000:DEAD:BEEF:A:0:0:0:0'
|
|
|
|
|
],
|
2019-03-08 23:08:09 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-24 10:54:02 +00:00
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToRight
|
2013-10-24 10:54:02 +00:00
|
|
|
*/
|
2013-10-23 22:51:31 +00:00
|
|
|
public function testBlockedUserCanNotCreateAccount() {
|
2012-07-13 09:43:17 +00:00
|
|
|
$username = 'BlockedUserToCreateAccountWith';
|
|
|
|
|
$u = User::newFromName( $username );
|
|
|
|
|
$u->addToDatabase();
|
2015-11-19 22:09:29 +00:00
|
|
|
$userId = $u->getId();
|
|
|
|
|
$this->assertNotEquals( 0, $userId, 'sanity' );
|
2015-09-04 16:17:42 +00:00
|
|
|
TestUser::setPasswordForUser( $u, 'NotRandomPass' );
|
2012-07-13 09:43:17 +00:00
|
|
|
unset( $u );
|
|
|
|
|
|
|
|
|
|
// Sanity check
|
|
|
|
|
$this->assertNull(
|
2019-05-13 14:18:07 +00:00
|
|
|
DatabaseBlock::newFromTarget( $username ),
|
2012-07-13 09:43:17 +00:00
|
|
|
"$username should not be blocked"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Reload user
|
|
|
|
|
$u = User::newFromName( $username );
|
|
|
|
|
$this->assertFalse(
|
|
|
|
|
$u->isBlockedFromCreateAccount(),
|
|
|
|
|
"Our sandbox user should be able to create account before being blocked"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Foreign perspective (blockee not on current wiki)...
|
2016-02-17 09:09:32 +00:00
|
|
|
$blockOptions = [
|
2014-05-22 14:45:46 +00:00
|
|
|
'address' => $username,
|
2015-11-19 22:09:29 +00:00
|
|
|
'user' => $userId,
|
2014-05-22 14:45:46 +00:00
|
|
|
'reason' => 'crosswiki block...',
|
|
|
|
|
'timestamp' => wfTimestampNow(),
|
|
|
|
|
'expiry' => $this->db->getInfinity(),
|
|
|
|
|
'createAccount' => true,
|
|
|
|
|
'enableAutoblock' => true,
|
|
|
|
|
'hideName' => true,
|
|
|
|
|
'blockEmail' => true,
|
2021-06-02 09:44:38 +00:00
|
|
|
'by' => UserIdentityValue::newExternal( 'm', 'MetaWikiUser' ),
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( $blockOptions );
|
2020-08-27 09:27:10 +00:00
|
|
|
MediaWikiServices::getInstance()->getDatabaseBlockStore()->insertBlock( $block );
|
2012-07-13 09:43:17 +00:00
|
|
|
|
|
|
|
|
// Reload block from DB
|
2019-05-13 14:18:07 +00:00
|
|
|
$userBlock = DatabaseBlock::newFromTarget( $username );
|
2012-07-13 09:43:17 +00:00
|
|
|
$this->assertTrue(
|
Separate out different functionalities of Block::prevents
Block::prevents plays several different roles:
* acts as get/setter for Boolean properties that correspond to
ipb_create_account, ipb_block_email and ipb_allow_usertalk
* calculates whether a block blocks a given right, based on Block
properties, global configs, white/blacklists and anonymous user
rights
* decides whether a block prevents editing of the target's own
user talk page (listed separately because 'editownusertalk' is
not a right)
This patch:
* renames mDisableUsertalk to allowEditUsertalk (and reverses the
value), to match the field ipb_allow_usertalk and make this logic
easier to follow
* renames mCreateAccount to blockCreateAccount, to make it clear
that the flag blocks account creation when true, and make this
logic easier to follow
* decouples the block that is stored in the database (which now
reflects the form that the admin submitted) and the behaviour of
the block on enforcement (since the properties set by the admin
can be overridden by global configs) - so if the global configs
change, the block behaviour could too
* creates get/setters for blockCreateAccount, mBlockEmail and
allowEditUsertalk properties
* creates appliesToRight, exclusively for checking whether the
block blocks a given right, taking into account the block
properties, global configs and anonymous user rights
* creates appliesToUsertalk, for checking whether the block
blocks a user from editing their own talk page. The block is
unaware of the user trying to make the edit, and this user is not
always the same as the block target, e.g. if the block target is
an IP range. Therefore the user's talk page is passed in to this
method. appliesToUsertalk can be called from anywhere where the
user is known
* uses the get/setters wherever Block::prevents was being used as
such
* uses appliesToRight whenever Block::prevents was being used to
determine if the block blocks a given right
* uses appliesToUsertalk in User::isBlockedFrom
Bug: T211578
Bug: T214508
Change-Id: I0e131696419211319082cb454f4f05297e55d22e
2019-02-09 12:17:54 +00:00
|
|
|
(bool)$block->appliesToRight( 'createaccount' ),
|
|
|
|
|
"Block object in DB should block right 'createaccount'"
|
2012-07-13 09:43:17 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->assertInstanceOf(
|
2019-05-13 14:18:07 +00:00
|
|
|
DatabaseBlock::class,
|
2012-07-13 09:43:17 +00:00
|
|
|
$userBlock,
|
|
|
|
|
"'$username' block block object should be existent"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Reload user
|
|
|
|
|
$u = User::newFromName( $username );
|
|
|
|
|
$this->assertTrue(
|
2013-01-28 10:27:15 +00:00
|
|
|
(bool)$u->isBlockedFromCreateAccount(),
|
2012-07-13 09:43:17 +00:00
|
|
|
"Our sandbox user '$username' should NOT be able to create account"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-24 10:54:02 +00:00
|
|
|
/**
|
2020-08-27 09:27:10 +00:00
|
|
|
* TODO: Move to DatabaseBlockStoreTest
|
|
|
|
|
*
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::insert
|
2013-10-24 10:54:02 +00:00
|
|
|
*/
|
2013-10-23 22:51:31 +00:00
|
|
|
public function testCrappyCrossWikiBlocks() {
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
2012-04-10 00:12:06 +00:00
|
|
|
// Delete the last round's block if it's still there
|
2019-05-13 14:18:07 +00:00
|
|
|
$oldBlock = DatabaseBlock::newFromTarget( 'UserOnForeignWiki' );
|
2012-04-10 00:12:06 +00:00
|
|
|
if ( $oldBlock ) {
|
|
|
|
|
// An old block will prevent our new one from saving.
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $oldBlock );
|
2012-04-10 00:12:06 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-08 22:18:20 +00:00
|
|
|
// Local perspective (blockee on current wiki)...
|
|
|
|
|
$user = User::newFromName( 'UserOnForeignWiki' );
|
|
|
|
|
$user->addToDatabase();
|
2015-11-19 22:09:29 +00:00
|
|
|
$userId = $user->getId();
|
|
|
|
|
$this->assertNotEquals( 0, $userId, 'sanity' );
|
2013-12-08 22:18:20 +00:00
|
|
|
|
2012-04-10 00:12:06 +00:00
|
|
|
// Foreign perspective (blockee not on current wiki)...
|
2016-02-17 09:09:32 +00:00
|
|
|
$blockOptions = [
|
2014-05-22 14:45:46 +00:00
|
|
|
'address' => 'UserOnForeignWiki',
|
2015-11-19 22:09:29 +00:00
|
|
|
'user' => $user->getId(),
|
2014-05-22 14:45:46 +00:00
|
|
|
'reason' => 'crosswiki block...',
|
|
|
|
|
'timestamp' => wfTimestampNow(),
|
|
|
|
|
'expiry' => $this->db->getInfinity(),
|
|
|
|
|
'createAccount' => true,
|
|
|
|
|
'enableAutoblock' => true,
|
|
|
|
|
'hideName' => true,
|
|
|
|
|
'blockEmail' => true,
|
2021-06-02 09:44:38 +00:00
|
|
|
'by' => UserIdentityValue::newExternal( 'm', 'MetaWikiUser' ),
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( $blockOptions );
|
2012-04-10 00:12:06 +00:00
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$res = $blockStore->insertBlock( $block, $this->db );
|
2012-04-10 00:12:06 +00:00
|
|
|
$this->assertTrue( (bool)$res['id'], 'Block succeeded' );
|
|
|
|
|
|
|
|
|
|
$user = null; // clear
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = DatabaseBlock::newFromID( $res['id'] );
|
2014-04-24 09:57:41 +00:00
|
|
|
$this->assertEquals(
|
|
|
|
|
'UserOnForeignWiki',
|
|
|
|
|
$block->getTarget()->getName(),
|
|
|
|
|
'Correct blockee name'
|
|
|
|
|
);
|
2021-04-16 12:55:24 +00:00
|
|
|
$this->assertEquals(
|
|
|
|
|
'UserOnForeignWiki',
|
|
|
|
|
$block->getTargetUserIdentity()->getName(),
|
|
|
|
|
'Correct blockee name'
|
|
|
|
|
);
|
2015-11-19 22:09:29 +00:00
|
|
|
$this->assertEquals( $userId, $block->getTarget()->getId(), 'Correct blockee id' );
|
2021-04-16 12:55:24 +00:00
|
|
|
$this->assertEquals( $userId, $block->getTargetUserIdentity()->getId(), 'Correct blockee id' );
|
|
|
|
|
$this->assertEquals( 'UserOnForeignWiki', $block->getTargetName(), 'Correct blockee name' );
|
|
|
|
|
$this->assertTrue( $block->isBlocking( 'UserOnForeignWiki' ), 'Is blocking blockee' );
|
2021-06-02 09:44:38 +00:00
|
|
|
$this->assertEquals( 'm>MetaWikiUser', $block->getBlocker()->getName(),
|
2017-10-25 19:26:53 +00:00
|
|
|
'Correct blocker name' );
|
2021-06-02 09:44:38 +00:00
|
|
|
$this->assertEquals( 'm>MetaWikiUser', $block->getByName(), 'Correct blocker name' );
|
2019-09-17 14:31:49 +00:00
|
|
|
$this->assertSame( 0, $block->getBy(), 'Correct blocker id' );
|
2012-04-10 00:12:06 +00:00
|
|
|
}
|
2012-11-17 23:23:09 +00:00
|
|
|
|
2013-03-30 17:05:15 +00:00
|
|
|
protected function addXffBlocks() {
|
|
|
|
|
static $inited = false;
|
|
|
|
|
|
|
|
|
|
if ( $inited ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$inited = true;
|
2012-11-17 23:23:09 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$blockList = [
|
|
|
|
|
[ 'target' => '70.2.0.0/16',
|
2019-05-13 14:18:07 +00:00
|
|
|
'type' => DatabaseBlock::TYPE_RANGE,
|
2012-11-17 23:23:09 +00:00
|
|
|
'desc' => 'Range Hardblock',
|
|
|
|
|
'ACDisable' => false,
|
|
|
|
|
'isHardblock' => true,
|
|
|
|
|
'isAutoBlocking' => false,
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'target' => '2001:4860:4001::/48',
|
2019-05-13 14:18:07 +00:00
|
|
|
'type' => DatabaseBlock::TYPE_RANGE,
|
2012-11-17 23:23:09 +00:00
|
|
|
'desc' => 'Range6 Hardblock',
|
|
|
|
|
'ACDisable' => false,
|
|
|
|
|
'isHardblock' => true,
|
|
|
|
|
'isAutoBlocking' => false,
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'target' => '60.2.0.0/16',
|
2019-05-13 14:18:07 +00:00
|
|
|
'type' => DatabaseBlock::TYPE_RANGE,
|
2012-11-17 23:23:09 +00:00
|
|
|
'desc' => 'Range Softblock with AC Disabled',
|
|
|
|
|
'ACDisable' => true,
|
|
|
|
|
'isHardblock' => false,
|
|
|
|
|
'isAutoBlocking' => false,
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'target' => '50.2.0.0/16',
|
2019-05-13 14:18:07 +00:00
|
|
|
'type' => DatabaseBlock::TYPE_RANGE,
|
2012-11-17 23:23:09 +00:00
|
|
|
'desc' => 'Range Softblock',
|
|
|
|
|
'ACDisable' => false,
|
|
|
|
|
'isHardblock' => false,
|
|
|
|
|
'isAutoBlocking' => false,
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'target' => '50.1.1.1',
|
2019-05-13 14:18:07 +00:00
|
|
|
'type' => DatabaseBlock::TYPE_IP,
|
2012-11-17 23:23:09 +00:00
|
|
|
'desc' => 'Exact Softblock',
|
|
|
|
|
'ACDisable' => false,
|
|
|
|
|
'isHardblock' => false,
|
|
|
|
|
'isAutoBlocking' => false,
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
];
|
2012-11-17 23:23:09 +00:00
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
2017-10-25 19:26:53 +00:00
|
|
|
$blocker = $this->getTestUser()->getUser();
|
2012-11-17 23:23:09 +00:00
|
|
|
foreach ( $blockList as $insBlock ) {
|
|
|
|
|
$target = $insBlock['target'];
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
if ( $insBlock['type'] === DatabaseBlock::TYPE_IP ) {
|
2019-06-25 18:53:15 +00:00
|
|
|
$target = User::newFromName( IPUtils::sanitizeIP( $target ), false )->getName();
|
2019-05-13 14:18:07 +00:00
|
|
|
} elseif ( $insBlock['type'] === DatabaseBlock::TYPE_RANGE ) {
|
2019-06-25 18:53:15 +00:00
|
|
|
$target = IPUtils::sanitizeRange( $target );
|
2012-11-17 23:23:09 +00:00
|
|
|
}
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock();
|
2012-11-17 23:23:09 +00:00
|
|
|
$block->setTarget( $target );
|
2017-10-25 19:26:53 +00:00
|
|
|
$block->setBlocker( $blocker );
|
2019-03-22 15:16:40 +00:00
|
|
|
$block->setReason( $insBlock['desc'] );
|
|
|
|
|
$block->setExpiry( 'infinity' );
|
Separate out different functionalities of Block::prevents
Block::prevents plays several different roles:
* acts as get/setter for Boolean properties that correspond to
ipb_create_account, ipb_block_email and ipb_allow_usertalk
* calculates whether a block blocks a given right, based on Block
properties, global configs, white/blacklists and anonymous user
rights
* decides whether a block prevents editing of the target's own
user talk page (listed separately because 'editownusertalk' is
not a right)
This patch:
* renames mDisableUsertalk to allowEditUsertalk (and reverses the
value), to match the field ipb_allow_usertalk and make this logic
easier to follow
* renames mCreateAccount to blockCreateAccount, to make it clear
that the flag blocks account creation when true, and make this
logic easier to follow
* decouples the block that is stored in the database (which now
reflects the form that the admin submitted) and the behaviour of
the block on enforcement (since the properties set by the admin
can be overridden by global configs) - so if the global configs
change, the block behaviour could too
* creates get/setters for blockCreateAccount, mBlockEmail and
allowEditUsertalk properties
* creates appliesToRight, exclusively for checking whether the
block blocks a given right, taking into account the block
properties, global configs and anonymous user rights
* creates appliesToUsertalk, for checking whether the block
blocks a user from editing their own talk page. The block is
unaware of the user trying to make the edit, and this user is not
always the same as the block target, e.g. if the block target is
an IP range. Therefore the user's talk page is passed in to this
method. appliesToUsertalk can be called from anywhere where the
user is known
* uses the get/setters wherever Block::prevents was being used as
such
* uses appliesToRight whenever Block::prevents was being used to
determine if the block blocks a given right
* uses appliesToUsertalk in User::isBlockedFrom
Bug: T211578
Bug: T214508
Change-Id: I0e131696419211319082cb454f4f05297e55d22e
2019-02-09 12:17:54 +00:00
|
|
|
$block->isCreateAccountBlocked( $insBlock['ACDisable'] );
|
2012-11-17 23:23:09 +00:00
|
|
|
$block->isHardblock( $insBlock['isHardblock'] );
|
|
|
|
|
$block->isAutoblocking( $insBlock['isAutoBlocking'] );
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->insertBlock( $block );
|
2012-11-17 23:23:09 +00:00
|
|
|
}
|
2013-03-30 17:05:15 +00:00
|
|
|
}
|
2012-11-17 23:23:09 +00:00
|
|
|
|
2013-03-30 17:05:15 +00:00
|
|
|
public static function providerXff() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'xff' => '1.2.3.4, 70.2.1.1, 60.2.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 2,
|
|
|
|
|
'result' => 'Range Hardblock'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '1.2.3.4, 50.2.1.1, 60.2.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 2,
|
|
|
|
|
'result' => 'Range Softblock with AC Disabled'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '1.2.3.4, 70.2.1.1, 50.1.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 2,
|
|
|
|
|
'result' => 'Exact Softblock'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '1.2.3.4, 70.2.1.1, 50.2.1.1, 50.1.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 3,
|
|
|
|
|
'result' => 'Exact Softblock'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '1.2.3.4, 70.2.1.1, 50.2.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 2,
|
|
|
|
|
'result' => 'Range Hardblock'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '1.2.3.4, 70.2.1.1, 60.2.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 2,
|
|
|
|
|
'result' => 'Range Hardblock'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '50.2.1.1, 60.2.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 2,
|
|
|
|
|
'result' => 'Range Softblock with AC Disabled'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '1.2.3.4, 50.1.1.1, 60.2.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 2,
|
|
|
|
|
'result' => 'Exact Softblock'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '1.2.3.4, <$A_BUNCH-OF{INVALID}TEXT\>, 60.2.1.1, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 1,
|
|
|
|
|
'result' => 'Range Softblock with AC Disabled'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[ 'xff' => '1.2.3.4, 50.2.1.1, 2001:4860:4001:802::1003, 2.3.4.5',
|
2012-11-17 23:23:09 +00:00
|
|
|
'count' => 2,
|
|
|
|
|
'result' => 'Range6 Hardblock'
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
];
|
2013-03-30 17:05:15 +00:00
|
|
|
}
|
2012-11-17 23:23:09 +00:00
|
|
|
|
2013-03-30 17:05:15 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider providerXff
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::getBlocksForIPList
|
2013-03-30 17:05:15 +00:00
|
|
|
*/
|
2013-10-23 22:51:31 +00:00
|
|
|
public function testBlocksOnXff( $xff, $exCount, $exResult ) {
|
2017-10-25 17:22:32 +00:00
|
|
|
$user = $this->getUserForBlocking();
|
|
|
|
|
$this->addBlockForUser( $user );
|
|
|
|
|
|
2013-03-30 17:05:15 +00:00
|
|
|
$list = array_map( 'trim', explode( ',', $xff ) );
|
2019-05-13 14:18:07 +00:00
|
|
|
$xffblocks = DatabaseBlock::getBlocksForIPList( $list, true );
|
2020-02-28 15:45:22 +00:00
|
|
|
$this->assertCount( $exCount, $xffblocks, 'Number of blocks for ' . $xff );
|
2012-11-17 23:23:09 +00:00
|
|
|
}
|
2014-05-22 14:45:46 +00:00
|
|
|
|
2018-08-16 04:55:55 +00:00
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::newFromRow
|
2018-08-16 04:55:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testNewFromRow() {
|
|
|
|
|
$badActor = $this->getTestUser()->getUser();
|
|
|
|
|
$sysop = $this->getTestSysop()->getUser();
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-08-16 04:55:55 +00:00
|
|
|
'address' => $badActor->getName(),
|
|
|
|
|
'user' => $badActor->getId(),
|
2021-06-02 09:44:38 +00:00
|
|
|
'by' => $sysop,
|
2018-08-16 04:55:55 +00:00
|
|
|
'expiry' => 'infinity',
|
|
|
|
|
] );
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
|
|
|
|
$blockStore->insertBlock( $block );
|
2018-08-16 04:55:55 +00:00
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$blockQuery = DatabaseBlock::getQueryInfo();
|
2018-08-16 04:55:55 +00:00
|
|
|
$row = $this->db->select(
|
|
|
|
|
$blockQuery['tables'],
|
|
|
|
|
$blockQuery['fields'],
|
|
|
|
|
[
|
|
|
|
|
'ipb_id' => $block->getId(),
|
|
|
|
|
],
|
|
|
|
|
__METHOD__,
|
|
|
|
|
[],
|
|
|
|
|
$blockQuery['joins']
|
|
|
|
|
)->fetchObject();
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = DatabaseBlock::newFromRow( $row );
|
|
|
|
|
$this->assertInstanceOf( DatabaseBlock::class, $block );
|
2018-08-16 04:55:55 +00:00
|
|
|
$this->assertEquals( $block->getBy(), $sysop->getId() );
|
|
|
|
|
$this->assertEquals( $block->getTarget()->getName(), $badActor->getName() );
|
2021-04-16 12:55:24 +00:00
|
|
|
$this->assertEquals( $block->getTargetName(), $badActor->getName() );
|
|
|
|
|
$this->assertTrue( $block->isBlocking( $badActor ), 'Is blocking expected user' );
|
|
|
|
|
$this->assertEquals( $block->getTargetUserIdentity()->getId(), $badActor->getId() );
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2018-08-16 04:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::equals
|
2018-08-16 04:55:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testEquals() {
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock();
|
2018-08-16 04:55:55 +00:00
|
|
|
|
|
|
|
|
$this->assertTrue( $block->equals( $block ) );
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$partial = new DatabaseBlock( [
|
2018-08-16 04:55:55 +00:00
|
|
|
'sitewide' => false,
|
|
|
|
|
] );
|
|
|
|
|
$this->assertFalse( $block->equals( $partial ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::isSitewide
|
2018-08-16 04:55:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsSitewide() {
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock();
|
2018-08-16 04:55:55 +00:00
|
|
|
$this->assertTrue( $block->isSitewide() );
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-08-16 04:55:55 +00:00
|
|
|
'sitewide' => true,
|
|
|
|
|
] );
|
|
|
|
|
$this->assertTrue( $block->isSitewide() );
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-08-16 04:55:55 +00:00
|
|
|
'sitewide' => false,
|
|
|
|
|
] );
|
|
|
|
|
$this->assertFalse( $block->isSitewide() );
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-08-16 04:55:55 +00:00
|
|
|
'sitewide' => false,
|
|
|
|
|
] );
|
|
|
|
|
$block->isSitewide( true );
|
|
|
|
|
$this->assertTrue( $block->isSitewide() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::getRestrictions
|
|
|
|
|
* @covers ::setRestrictions
|
2018-08-16 04:55:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testRestrictions() {
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock();
|
2018-08-16 04:55:55 +00:00
|
|
|
$restrictions = [
|
|
|
|
|
new PageRestriction( 0, 1 )
|
|
|
|
|
];
|
|
|
|
|
$block->setRestrictions( $restrictions );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $restrictions, $block->getRestrictions() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::getRestrictions
|
|
|
|
|
* @covers ::insert
|
2018-08-16 04:55:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testRestrictionsFromDatabase() {
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
2018-08-16 04:55:55 +00:00
|
|
|
$badActor = $this->getTestUser()->getUser();
|
|
|
|
|
$sysop = $this->getTestSysop()->getUser();
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-08-16 04:55:55 +00:00
|
|
|
'address' => $badActor->getName(),
|
|
|
|
|
'user' => $badActor->getId(),
|
2021-06-02 09:44:38 +00:00
|
|
|
'by' => $sysop,
|
2018-08-16 04:55:55 +00:00
|
|
|
'expiry' => 'infinity',
|
|
|
|
|
] );
|
|
|
|
|
$page = $this->getExistingTestPage( 'Foo' );
|
|
|
|
|
$restriction = new PageRestriction( 0, $page->getId() );
|
|
|
|
|
$block->setRestrictions( [ $restriction ] );
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->insertBlock( $block );
|
2018-08-16 04:55:55 +00:00
|
|
|
|
|
|
|
|
// Refresh the block from the database.
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = DatabaseBlock::newFromID( $block->getId() );
|
2018-08-16 04:55:55 +00:00
|
|
|
$restrictions = $block->getRestrictions();
|
|
|
|
|
$this->assertCount( 1, $restrictions );
|
|
|
|
|
$this->assertTrue( $restriction->equals( $restrictions[0] ) );
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2018-08-16 04:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-08-27 09:27:10 +00:00
|
|
|
* TODO: Move to DatabaseBlockStoreTest
|
|
|
|
|
*
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::insert
|
2018-08-16 04:55:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testInsertExistingBlock() {
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
2018-08-16 04:55:55 +00:00
|
|
|
$badActor = $this->getTestUser()->getUser();
|
|
|
|
|
$sysop = $this->getTestSysop()->getUser();
|
|
|
|
|
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-08-16 04:55:55 +00:00
|
|
|
'address' => $badActor->getName(),
|
|
|
|
|
'user' => $badActor->getId(),
|
2021-06-02 09:44:38 +00:00
|
|
|
'by' => $sysop,
|
2018-08-16 04:55:55 +00:00
|
|
|
'expiry' => 'infinity',
|
|
|
|
|
] );
|
|
|
|
|
$page = $this->getExistingTestPage( 'Foo' );
|
|
|
|
|
$restriction = new PageRestriction( 0, $page->getId() );
|
|
|
|
|
$block->setRestrictions( [ $restriction ] );
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->insertBlock( $block );
|
2018-08-16 04:55:55 +00:00
|
|
|
|
2020-08-30 17:05:36 +00:00
|
|
|
// Insert the block again, which should result in a failure
|
2018-08-16 04:55:55 +00:00
|
|
|
$result = $block->insert();
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $result );
|
|
|
|
|
|
|
|
|
|
// Ensure that there are no restrictions where the blockId is 0.
|
|
|
|
|
$count = $this->db->selectRowCount(
|
|
|
|
|
'ipblocks_restrictions',
|
|
|
|
|
'*',
|
|
|
|
|
[ 'ir_ipb_id' => 0 ],
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame( 0, $count );
|
|
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2018-08-16 04:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
2018-08-27 01:45:18 +00:00
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToTitle
|
2018-08-27 01:45:18 +00:00
|
|
|
*/
|
2018-11-01 14:11:03 +00:00
|
|
|
public function testAppliesToTitleReturnsTrueOnSitewideBlock() {
|
2019-02-19 20:16:21 +00:00
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgBlockDisablesLogin' => false,
|
|
|
|
|
] );
|
2018-08-27 01:45:18 +00:00
|
|
|
$user = $this->getTestUser()->getUser();
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-08-27 01:45:18 +00:00
|
|
|
'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
|
|
|
|
|
'allowUsertalk' => true,
|
|
|
|
|
'sitewide' => true
|
|
|
|
|
] );
|
|
|
|
|
|
2021-03-19 13:56:13 +00:00
|
|
|
$block->setTarget( new UserIdentityValue( $user->getId(), $user->getName() ) );
|
2018-08-27 01:45:18 +00:00
|
|
|
$block->setBlocker( $this->getTestSysop()->getUser() );
|
2020-08-27 09:27:10 +00:00
|
|
|
|
|
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
|
|
|
|
$blockStore->insertBlock( $block );
|
2018-08-27 01:45:18 +00:00
|
|
|
|
|
|
|
|
$title = $this->getExistingTestPage( 'Foo' )->getTitle();
|
|
|
|
|
|
2018-11-01 14:11:03 +00:00
|
|
|
$this->assertTrue( $block->appliesToTitle( $title ) );
|
|
|
|
|
|
|
|
|
|
// appliesToTitle() ignores allowUsertalk
|
|
|
|
|
$title = $user->getTalkPage();
|
|
|
|
|
$this->assertTrue( $block->appliesToTitle( $title ) );
|
2018-08-27 01:45:18 +00:00
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2018-08-27 01:45:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToTitle
|
2018-08-27 01:45:18 +00:00
|
|
|
*/
|
2018-11-01 14:11:03 +00:00
|
|
|
public function testAppliesToTitleOnPartialBlock() {
|
2019-02-19 20:16:21 +00:00
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgBlockDisablesLogin' => false,
|
|
|
|
|
] );
|
2018-08-27 01:45:18 +00:00
|
|
|
$user = $this->getTestUser()->getUser();
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-08-27 01:45:18 +00:00
|
|
|
'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
|
|
|
|
|
'allowUsertalk' => true,
|
|
|
|
|
'sitewide' => false
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$block->setTarget( $user );
|
|
|
|
|
$block->setBlocker( $this->getTestSysop()->getUser() );
|
2020-08-27 09:27:10 +00:00
|
|
|
|
|
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
|
|
|
|
$blockStore->insertBlock( $block );
|
2018-08-27 01:45:18 +00:00
|
|
|
|
|
|
|
|
$pageFoo = $this->getExistingTestPage( 'Foo' );
|
|
|
|
|
$pageBar = $this->getExistingTestPage( 'Bar' );
|
2018-10-30 18:19:22 +00:00
|
|
|
$pageJohn = $this->getExistingTestPage( 'User:John' );
|
2018-08-27 01:45:18 +00:00
|
|
|
|
|
|
|
|
$pageRestriction = new PageRestriction( $block->getId(), $pageFoo->getId() );
|
2018-10-30 18:19:22 +00:00
|
|
|
$namespaceRestriction = new NamespaceRestriction( $block->getId(), NS_USER );
|
2019-04-11 19:54:10 +00:00
|
|
|
$this->getBlockRestrictionStore()->insert( [ $pageRestriction, $namespaceRestriction ] );
|
2018-08-27 01:45:18 +00:00
|
|
|
|
2018-11-01 14:11:03 +00:00
|
|
|
$this->assertTrue( $block->appliesToTitle( $pageFoo->getTitle() ) );
|
|
|
|
|
$this->assertFalse( $block->appliesToTitle( $pageBar->getTitle() ) );
|
2018-10-30 18:19:22 +00:00
|
|
|
$this->assertTrue( $block->appliesToTitle( $pageJohn->getTitle() ) );
|
|
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2018-10-30 18:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToNamespace
|
|
|
|
|
* @covers ::appliesToPage
|
2018-10-30 18:19:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testAppliesToReturnsTrueOnSitewideBlock() {
|
2019-02-19 20:16:21 +00:00
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgBlockDisablesLogin' => false,
|
|
|
|
|
] );
|
2018-10-30 18:19:22 +00:00
|
|
|
$user = $this->getTestUser()->getUser();
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-10-30 18:19:22 +00:00
|
|
|
'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
|
|
|
|
|
'allowUsertalk' => true,
|
|
|
|
|
'sitewide' => true
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$block->setTarget( $user );
|
|
|
|
|
$block->setBlocker( $this->getTestSysop()->getUser() );
|
2020-08-27 09:27:10 +00:00
|
|
|
|
|
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
|
|
|
|
$blockStore->insertBlock( $block );
|
2018-10-30 18:19:22 +00:00
|
|
|
|
|
|
|
|
$title = $this->getExistingTestPage()->getTitle();
|
|
|
|
|
|
|
|
|
|
$this->assertTrue( $block->appliesToPage( $title->getArticleID() ) );
|
|
|
|
|
$this->assertTrue( $block->appliesToNamespace( NS_MAIN ) );
|
|
|
|
|
$this->assertTrue( $block->appliesToNamespace( NS_USER_TALK ) );
|
|
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2018-10-30 18:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToPage
|
2018-10-30 18:19:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testAppliesToPageOnPartialPageBlock() {
|
2019-02-19 20:16:21 +00:00
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgBlockDisablesLogin' => false,
|
|
|
|
|
] );
|
2018-10-30 18:19:22 +00:00
|
|
|
$user = $this->getTestUser()->getUser();
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-10-30 18:19:22 +00:00
|
|
|
'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
|
|
|
|
|
'allowUsertalk' => true,
|
|
|
|
|
'sitewide' => false
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$block->setTarget( $user );
|
|
|
|
|
$block->setBlocker( $this->getTestSysop()->getUser() );
|
2020-08-27 09:27:10 +00:00
|
|
|
|
|
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
|
|
|
|
$blockStore->insertBlock( $block );
|
2018-10-30 18:19:22 +00:00
|
|
|
|
|
|
|
|
$title = $this->getExistingTestPage()->getTitle();
|
|
|
|
|
|
|
|
|
|
$pageRestriction = new PageRestriction(
|
|
|
|
|
$block->getId(),
|
|
|
|
|
$title->getArticleID()
|
|
|
|
|
);
|
2019-04-11 19:54:10 +00:00
|
|
|
$this->getBlockRestrictionStore()->insert( [ $pageRestriction ] );
|
2018-10-30 18:19:22 +00:00
|
|
|
|
|
|
|
|
$this->assertTrue( $block->appliesToPage( $title->getArticleID() ) );
|
|
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2018-10-30 18:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToNamespace
|
2018-10-30 18:19:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testAppliesToNamespaceOnPartialNamespaceBlock() {
|
2019-02-19 20:16:21 +00:00
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgBlockDisablesLogin' => false,
|
|
|
|
|
] );
|
2018-10-30 18:19:22 +00:00
|
|
|
$user = $this->getTestUser()->getUser();
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock( [
|
2018-10-30 18:19:22 +00:00
|
|
|
'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
|
|
|
|
|
'allowUsertalk' => true,
|
|
|
|
|
'sitewide' => false
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$block->setTarget( $user );
|
|
|
|
|
$block->setBlocker( $this->getTestSysop()->getUser() );
|
2020-08-27 09:27:10 +00:00
|
|
|
|
|
|
|
|
$blockStore = MediaWikiServices::getInstance()->getDatabaseBlockStore();
|
|
|
|
|
$blockStore->insertBlock( $block );
|
2018-10-30 18:19:22 +00:00
|
|
|
|
|
|
|
|
$namespaceRestriction = new NamespaceRestriction( $block->getId(), NS_MAIN );
|
2019-04-11 19:54:10 +00:00
|
|
|
$this->getBlockRestrictionStore()->insert( [ $namespaceRestriction ] );
|
2018-10-30 18:19:22 +00:00
|
|
|
|
|
|
|
|
$this->assertTrue( $block->appliesToNamespace( NS_MAIN ) );
|
|
|
|
|
$this->assertFalse( $block->appliesToNamespace( NS_USER ) );
|
2018-08-27 01:45:18 +00:00
|
|
|
|
2020-08-27 09:27:10 +00:00
|
|
|
$blockStore->deleteBlock( $block );
|
2018-08-27 01:45:18 +00:00
|
|
|
}
|
|
|
|
|
|
2019-01-08 21:14:48 +00:00
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToRight
|
2019-01-08 21:14:48 +00:00
|
|
|
*/
|
|
|
|
|
public function testBlockAllowsPurge() {
|
2019-02-19 20:16:21 +00:00
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgBlockDisablesLogin' => false,
|
|
|
|
|
] );
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock();
|
Separate out different functionalities of Block::prevents
Block::prevents plays several different roles:
* acts as get/setter for Boolean properties that correspond to
ipb_create_account, ipb_block_email and ipb_allow_usertalk
* calculates whether a block blocks a given right, based on Block
properties, global configs, white/blacklists and anonymous user
rights
* decides whether a block prevents editing of the target's own
user talk page (listed separately because 'editownusertalk' is
not a right)
This patch:
* renames mDisableUsertalk to allowEditUsertalk (and reverses the
value), to match the field ipb_allow_usertalk and make this logic
easier to follow
* renames mCreateAccount to blockCreateAccount, to make it clear
that the flag blocks account creation when true, and make this
logic easier to follow
* decouples the block that is stored in the database (which now
reflects the form that the admin submitted) and the behaviour of
the block on enforcement (since the properties set by the admin
can be overridden by global configs) - so if the global configs
change, the block behaviour could too
* creates get/setters for blockCreateAccount, mBlockEmail and
allowEditUsertalk properties
* creates appliesToRight, exclusively for checking whether the
block blocks a given right, taking into account the block
properties, global configs and anonymous user rights
* creates appliesToUsertalk, for checking whether the block
blocks a user from editing their own talk page. The block is
unaware of the user trying to make the edit, and this user is not
always the same as the block target, e.g. if the block target is
an IP range. Therefore the user's talk page is passed in to this
method. appliesToUsertalk can be called from anywhere where the
user is known
* uses the get/setters wherever Block::prevents was being used as
such
* uses appliesToRight whenever Block::prevents was being used to
determine if the block blocks a given right
* uses appliesToUsertalk in User::isBlockedFrom
Bug: T211578
Bug: T214508
Change-Id: I0e131696419211319082cb454f4f05297e55d22e
2019-02-09 12:17:54 +00:00
|
|
|
$this->assertFalse( $block->appliesToRight( 'purge' ) );
|
2019-01-08 21:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
2019-04-11 19:54:10 +00:00
|
|
|
/**
|
|
|
|
|
* Get an instance of BlockRestrictionStore
|
|
|
|
|
*
|
|
|
|
|
* @return BlockRestrictionStore
|
|
|
|
|
*/
|
|
|
|
|
protected function getBlockRestrictionStore() : BlockRestrictionStore {
|
|
|
|
|
return MediaWikiServices::getInstance()->getBlockRestrictionStore();
|
|
|
|
|
}
|
2010-12-28 19:12:27 +00:00
|
|
|
}
|