2010-12-28 19:12:27 +00:00
|
|
|
<?php
|
|
|
|
|
|
2019-04-11 19:54:10 +00:00
|
|
|
use MediaWiki\Block\BlockRestrictionStore;
|
2022-01-20 18:38:30 +00:00
|
|
|
use MediaWiki\Block\BlockUtils;
|
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;
|
2021-09-26 19:51:13 +00:00
|
|
|
use MediaWiki\DAO\WikiAwareEntity;
|
2022-07-19 10:57:01 +00:00
|
|
|
use MediaWiki\MainConfigNames;
|
2023-09-19 12:13:45 +00:00
|
|
|
use MediaWiki\User\User;
|
2021-03-19 13:56:13 +00:00
|
|
|
use MediaWiki\User\UserIdentity;
|
|
|
|
|
use MediaWiki\User\UserIdentityValue;
|
2022-01-20 18:38:30 +00:00
|
|
|
use MediaWiki\User\UserNameUtils;
|
|
|
|
|
use Wikimedia\Rdbms\DBConnRef;
|
|
|
|
|
use Wikimedia\Rdbms\ILoadBalancer;
|
|
|
|
|
use Wikimedia\Rdbms\LBFactory;
|
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
|
|
|
|
2024-01-20 10:41:15 +00:00
|
|
|
public function addDBData() {
|
Fix tests not properly cleaning up the DB
- UserEditTrackerTest: determine whether to create the page based on
WikiPage::exists() instead of a method parameter. The current
implementation only works because the page is not deleted between test
runs, and the creation query is ignored. However, if the first call to
`editTrackerDoEdit` doesn't have $create=true, tests would fail. For
instance, testGetEditTimestamp would fail when run on its own because
the revision cannot be inserted if the page doesn't exist. Just use
WikiPage::exists instead of forcing callers to handle this correctly.
- DatabaseBlockTest: use addDBDataOnce instead of a DIY implementation.
This also makes the tests more deterministic, because the records
needed by the test class are created immediately. Also avoid redundant
User::addToDatabase and ::saveSettings, these are already done by
TestUser.
- PageRestrictionTest: avoid Title::newFromID which is not guaranteed to
succeed if all pages have been deleted by that point. The second part
of the test was effectively doing the same thing as the first part, so
just remove it.
- WikiPageDbTest: avoid expensive page deletions in tearDown. These are
all unnecessary because the DB is cleaned up after each test (and
'page' is explicitly included in $tablesUsed). In fact, deleting test
pages as done there can be even worse than not doing anything, because
it creates log entries etc. Add page_restrictions to tablesUsed as
that's not truncated automatically.
- DBSiteStoreTest: testReset would fail when run on its own because it
depends on test sites being inserted in testGetSites. Make the test
add the sites it needs, so that they can safely be cleared between
test runs.
Change-Id: I1065fb3e8507b4b1a3bf185181f2f3059a97fd04
2023-08-11 17:50:20 +00:00
|
|
|
$blockList = [
|
|
|
|
|
[ 'target' => '70.2.0.0/16',
|
|
|
|
|
'type' => DatabaseBlock::TYPE_RANGE,
|
|
|
|
|
'desc' => 'Range Hardblock',
|
|
|
|
|
'ACDisable' => false,
|
|
|
|
|
'isHardblock' => true,
|
|
|
|
|
'isAutoBlocking' => false,
|
|
|
|
|
],
|
2024-01-20 10:47:36 +00:00
|
|
|
[ 'target' => '2001:4860:4001:0:0:0:0:0/48',
|
Fix tests not properly cleaning up the DB
- UserEditTrackerTest: determine whether to create the page based on
WikiPage::exists() instead of a method parameter. The current
implementation only works because the page is not deleted between test
runs, and the creation query is ignored. However, if the first call to
`editTrackerDoEdit` doesn't have $create=true, tests would fail. For
instance, testGetEditTimestamp would fail when run on its own because
the revision cannot be inserted if the page doesn't exist. Just use
WikiPage::exists instead of forcing callers to handle this correctly.
- DatabaseBlockTest: use addDBDataOnce instead of a DIY implementation.
This also makes the tests more deterministic, because the records
needed by the test class are created immediately. Also avoid redundant
User::addToDatabase and ::saveSettings, these are already done by
TestUser.
- PageRestrictionTest: avoid Title::newFromID which is not guaranteed to
succeed if all pages have been deleted by that point. The second part
of the test was effectively doing the same thing as the first part, so
just remove it.
- WikiPageDbTest: avoid expensive page deletions in tearDown. These are
all unnecessary because the DB is cleaned up after each test (and
'page' is explicitly included in $tablesUsed). In fact, deleting test
pages as done there can be even worse than not doing anything, because
it creates log entries etc. Add page_restrictions to tablesUsed as
that's not truncated automatically.
- DBSiteStoreTest: testReset would fail when run on its own because it
depends on test sites being inserted in testGetSites. Make the test
add the sites it needs, so that they can safely be cleared between
test runs.
Change-Id: I1065fb3e8507b4b1a3bf185181f2f3059a97fd04
2023-08-11 17:50:20 +00:00
|
|
|
'type' => DatabaseBlock::TYPE_RANGE,
|
|
|
|
|
'desc' => 'Range6 Hardblock',
|
|
|
|
|
'ACDisable' => false,
|
|
|
|
|
'isHardblock' => true,
|
|
|
|
|
'isAutoBlocking' => false,
|
|
|
|
|
],
|
|
|
|
|
[ 'target' => '60.2.0.0/16',
|
|
|
|
|
'type' => DatabaseBlock::TYPE_RANGE,
|
|
|
|
|
'desc' => 'Range Softblock with AC Disabled',
|
|
|
|
|
'ACDisable' => true,
|
|
|
|
|
'isHardblock' => false,
|
|
|
|
|
'isAutoBlocking' => false,
|
|
|
|
|
],
|
|
|
|
|
[ 'target' => '50.2.0.0/16',
|
|
|
|
|
'type' => DatabaseBlock::TYPE_RANGE,
|
|
|
|
|
'desc' => 'Range Softblock',
|
|
|
|
|
'ACDisable' => false,
|
|
|
|
|
'isHardblock' => false,
|
|
|
|
|
'isAutoBlocking' => false,
|
|
|
|
|
],
|
|
|
|
|
[ 'target' => '50.1.1.1',
|
|
|
|
|
'type' => DatabaseBlock::TYPE_IP,
|
|
|
|
|
'desc' => 'Exact Softblock',
|
|
|
|
|
'ACDisable' => false,
|
|
|
|
|
'isHardblock' => false,
|
|
|
|
|
'isAutoBlocking' => false,
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
|
|
|
|
$blocker = $this->getTestUser()->getUser();
|
|
|
|
|
foreach ( $blockList as $insBlock ) {
|
|
|
|
|
$block = new DatabaseBlock();
|
2024-01-20 10:47:36 +00:00
|
|
|
$block->setTarget( $insBlock['target'] );
|
Fix tests not properly cleaning up the DB
- UserEditTrackerTest: determine whether to create the page based on
WikiPage::exists() instead of a method parameter. The current
implementation only works because the page is not deleted between test
runs, and the creation query is ignored. However, if the first call to
`editTrackerDoEdit` doesn't have $create=true, tests would fail. For
instance, testGetEditTimestamp would fail when run on its own because
the revision cannot be inserted if the page doesn't exist. Just use
WikiPage::exists instead of forcing callers to handle this correctly.
- DatabaseBlockTest: use addDBDataOnce instead of a DIY implementation.
This also makes the tests more deterministic, because the records
needed by the test class are created immediately. Also avoid redundant
User::addToDatabase and ::saveSettings, these are already done by
TestUser.
- PageRestrictionTest: avoid Title::newFromID which is not guaranteed to
succeed if all pages have been deleted by that point. The second part
of the test was effectively doing the same thing as the first part, so
just remove it.
- WikiPageDbTest: avoid expensive page deletions in tearDown. These are
all unnecessary because the DB is cleaned up after each test (and
'page' is explicitly included in $tablesUsed). In fact, deleting test
pages as done there can be even worse than not doing anything, because
it creates log entries etc. Add page_restrictions to tablesUsed as
that's not truncated automatically.
- DBSiteStoreTest: testReset would fail when run on its own because it
depends on test sites being inserted in testGetSites. Make the test
add the sites it needs, so that they can safely be cleared between
test runs.
Change-Id: I1065fb3e8507b4b1a3bf185181f2f3059a97fd04
2023-08-11 17:50:20 +00:00
|
|
|
$block->setBlocker( $blocker );
|
|
|
|
|
$block->setReason( $insBlock['desc'] );
|
|
|
|
|
$block->setExpiry( 'infinity' );
|
|
|
|
|
$block->isCreateAccountBlocked( $insBlock['ACDisable'] );
|
|
|
|
|
$block->isHardblock( $insBlock['isHardblock'] );
|
|
|
|
|
$block->isAutoblocking( $insBlock['isAutoBlocking'] );
|
|
|
|
|
$blockStore->insertBlock( $block );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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() {
|
Fix tests not properly cleaning up the DB
- UserEditTrackerTest: determine whether to create the page based on
WikiPage::exists() instead of a method parameter. The current
implementation only works because the page is not deleted between test
runs, and the creation query is ignored. However, if the first call to
`editTrackerDoEdit` doesn't have $create=true, tests would fail. For
instance, testGetEditTimestamp would fail when run on its own because
the revision cannot be inserted if the page doesn't exist. Just use
WikiPage::exists instead of forcing callers to handle this correctly.
- DatabaseBlockTest: use addDBDataOnce instead of a DIY implementation.
This also makes the tests more deterministic, because the records
needed by the test class are created immediately. Also avoid redundant
User::addToDatabase and ::saveSettings, these are already done by
TestUser.
- PageRestrictionTest: avoid Title::newFromID which is not guaranteed to
succeed if all pages have been deleted by that point. The second part
of the test was effectively doing the same thing as the first part, so
just remove it.
- WikiPageDbTest: avoid expensive page deletions in tearDown. These are
all unnecessary because the DB is cleaned up after each test (and
'page' is explicitly included in $tablesUsed). In fact, deleting test
pages as done there can be even worse than not doing anything, because
it creates log entries etc. Add page_restrictions to tablesUsed as
that's not truncated automatically.
- DBSiteStoreTest: testReset would fail when run on its own because it
depends on test sites being inserted in testGetSites. Make the test
add the sites it needs, so that they can safely be cleared between
test runs.
Change-Id: I1065fb3e8507b4b1a3bf185181f2f3059a97fd04
2023-08-11 17:50:20 +00:00
|
|
|
return $this->getTestUser()->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
|
|
|
*/
|
2021-03-19 13:56:13 +00:00
|
|
|
private function addBlockForUser( UserIdentity $user ) {
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
2011-06-15 20:43:24 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$blockOptions = [
|
2023-11-05 23:53:56 +00:00
|
|
|
'address' => $user,
|
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() ) {
|
2023-06-03 15:25:27 +00:00
|
|
|
throw new RuntimeException( "Failed to insert block for BlockTest; old leftover block remaining?" );
|
2011-06-15 20:43:24 +00:00
|
|
|
}
|
2013-03-30 17:05:15 +00:00
|
|
|
|
2017-10-25 17:22:32 +00:00
|
|
|
return $block;
|
2011-05-28 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-08 17:07:45 +00:00
|
|
|
/**
|
|
|
|
|
* @covers ::newFromTarget
|
|
|
|
|
*/
|
|
|
|
|
public function testHardBlocks() {
|
|
|
|
|
// Set up temp user config
|
|
|
|
|
$this->overrideConfigValue(
|
|
|
|
|
MainConfigNames::AutoCreateTempUser,
|
|
|
|
|
[
|
|
|
|
|
'enabled' => true,
|
2023-08-23 12:06:00 +00:00
|
|
|
'expireAfterDays' => null,
|
2023-08-08 17:07:45 +00:00
|
|
|
'actions' => [ 'edit' ],
|
|
|
|
|
'genPattern' => '*Unregistered $1',
|
|
|
|
|
'matchPattern' => '*$1',
|
|
|
|
|
'serialProvider' => [ 'type' => 'local' ],
|
|
|
|
|
'serialMapping' => [ 'type' => 'plain-numeric' ],
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
|
|
|
|
$blocker = $this->getTestUser()->getUser();
|
|
|
|
|
|
|
|
|
|
$block = new DatabaseBlock();
|
|
|
|
|
$block->setTarget( '1.2.3.4' );
|
|
|
|
|
$block->setBlocker( $blocker );
|
|
|
|
|
$block->setReason( 'test' );
|
|
|
|
|
$block->setExpiry( 'infinity' );
|
|
|
|
|
$block->isHardblock( false );
|
|
|
|
|
$blockStore->insertBlock( $block );
|
|
|
|
|
|
|
|
|
|
$this->assertFalse(
|
|
|
|
|
(bool)DatabaseBlock::newFromTarget( '*Unregistered 1' ),
|
|
|
|
|
'Temporary user is not blocked directly'
|
|
|
|
|
);
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
(bool)DatabaseBlock::newFromTarget( '*Unregistered 1', '1.2.3.4' ),
|
|
|
|
|
'Temporary user is blocked by soft block'
|
|
|
|
|
);
|
|
|
|
|
$this->assertFalse(
|
|
|
|
|
(bool)DatabaseBlock::newFromTarget( $blocker, '1.2.3.4' ),
|
|
|
|
|
'Logged-in user is not blocked by soft block'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
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() {
|
2023-10-31 07:57:33 +00:00
|
|
|
$this->hideDeprecated( DatabaseBlock::class . '::newFromID' );
|
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 ) {
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->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-06-03 10:25:17 +00:00
|
|
|
$block = DatabaseBlock::newFromTarget( $this->getTestUser()->getUserIdentity(), $ip );
|
2019-03-08 23:08:09 +00:00
|
|
|
$this->assertSame(
|
2022-10-07 17:35:34 +00:00
|
|
|
$expectedTarget,
|
|
|
|
|
$block->getTargetName()
|
2019-03-08 23:08:09 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static 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();
|
2021-11-21 16:23:11 +00:00
|
|
|
$this->assertNotEquals( 0, $userId, 'Check user id is not 0' );
|
2015-09-04 16:17:42 +00:00
|
|
|
TestUser::setPasswordForUser( $u, 'NotRandomPass' );
|
2012-07-13 09:43:17 +00:00
|
|
|
unset( $u );
|
|
|
|
|
|
|
|
|
|
$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 );
|
2023-10-11 22:18:26 +00:00
|
|
|
$this->assertTrue(
|
|
|
|
|
$u->isDefinitelyAllowed( 'createaccount' ),
|
2012-07-13 09:43:17 +00:00
|
|
|
"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,
|
|
|
|
|
'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 );
|
2022-01-12 20:13:39 +00:00
|
|
|
$this->getServiceContainer()->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 );
|
2023-10-11 22:18:26 +00:00
|
|
|
$this->assertFalse(
|
|
|
|
|
$u->isDefinitelyAllowed( 'createaccount' ),
|
2012-07-13 09:43:17 +00:00
|
|
|
"Our sandbox user '$username' should NOT be able to create account"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
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( [
|
2023-11-05 23:53:56 +00:00
|
|
|
'address' => $badActor,
|
2021-06-02 09:44:38 +00:00
|
|
|
'by' => $sysop,
|
2018-08-16 04:55:55 +00:00
|
|
|
'expiry' => 'infinity',
|
|
|
|
|
] );
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
2020-08-27 09:27:10 +00:00
|
|
|
$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() );
|
2021-06-03 10:25:17 +00:00
|
|
|
$this->assertEquals( $block->getTargetName(), $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() );
|
2018-08-16 04:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
2021-09-26 19:51:13 +00:00
|
|
|
/**
|
2022-01-20 18:38:30 +00:00
|
|
|
* @covers ::getTargetName()
|
|
|
|
|
* @covers ::getTargetUserIdentity()
|
|
|
|
|
* @covers ::isBlocking()
|
|
|
|
|
* @covers ::getBlocker()
|
|
|
|
|
* @covers ::getByName()
|
2021-09-26 19:51:13 +00:00
|
|
|
*/
|
|
|
|
|
public function testCrossWikiBlocking() {
|
2022-07-19 10:57:01 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::LocalDatabases, [ 'm' ] );
|
2022-01-20 18:38:30 +00:00
|
|
|
$dbMock = $this->createMock( DBConnRef::class );
|
|
|
|
|
$dbMock->method( 'decodeExpiry' )->willReturn( 'infinity' );
|
|
|
|
|
$lbMock = $this->createMock( ILoadBalancer::class );
|
|
|
|
|
$lbMock->method( 'getConnectionRef' )
|
|
|
|
|
->with( DB_REPLICA, [], 'm' )
|
|
|
|
|
->willReturn( $dbMock );
|
|
|
|
|
$lbFactoryMock = $this->createMock( LBFactory::class );
|
|
|
|
|
$lbFactoryMock
|
|
|
|
|
->method( 'getMainLB' )
|
|
|
|
|
->with( 'm' )
|
|
|
|
|
->willReturn( $lbMock );
|
|
|
|
|
$this->setService( 'DBLoadBalancerFactory', $lbFactoryMock );
|
|
|
|
|
|
|
|
|
|
$target = UserIdentityValue::newExternal( 'm', 'UserOnForeignWiki', 'm' );
|
|
|
|
|
|
|
|
|
|
$blockUtilsMock = $this->createMock( BlockUtils::class );
|
|
|
|
|
$blockUtilsMock
|
|
|
|
|
->method( 'parseBlockTarget' )
|
|
|
|
|
->with( $target )
|
|
|
|
|
->willReturn( [ $target, DatabaseBlock::TYPE_USER ] );
|
|
|
|
|
$this->setService( 'BlockUtils', $blockUtilsMock );
|
|
|
|
|
|
|
|
|
|
$blocker = UserIdentityValue::newExternal( 'm', 'MetaWikiUser', 'm' );
|
|
|
|
|
|
|
|
|
|
$userNameUtilsMock = $this->createMock( UserNameUtils::class );
|
|
|
|
|
$userNameUtilsMock
|
|
|
|
|
->method( 'isUsable' )
|
|
|
|
|
->with( $blocker->getName() )
|
|
|
|
|
->willReturn( false );
|
|
|
|
|
$this->setService( 'UserNameUtils', $userNameUtilsMock );
|
2021-09-26 19:51:13 +00:00
|
|
|
|
|
|
|
|
$blockOptions = [
|
2022-01-20 18:38:30 +00:00
|
|
|
'address' => $target,
|
2021-09-26 19:51:13 +00:00
|
|
|
'wiki' => 'm',
|
|
|
|
|
'reason' => 'testing crosswiki blocking',
|
|
|
|
|
'timestamp' => wfTimestampNow(),
|
|
|
|
|
'createAccount' => true,
|
|
|
|
|
'enableAutoblock' => true,
|
|
|
|
|
'hideName' => true,
|
|
|
|
|
'blockEmail' => true,
|
2022-01-20 18:38:30 +00:00
|
|
|
'by' => $blocker,
|
2021-09-26 19:51:13 +00:00
|
|
|
];
|
|
|
|
|
$block = new DatabaseBlock( $blockOptions );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
'm>UserOnForeignWiki',
|
|
|
|
|
$block->getTargetName(),
|
|
|
|
|
'Correct blockee name'
|
|
|
|
|
);
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
'm>UserOnForeignWiki',
|
|
|
|
|
$block->getTargetUserIdentity()->getName(),
|
|
|
|
|
'Correct blockee name'
|
|
|
|
|
);
|
|
|
|
|
$this->assertTrue( $block->isBlocking( 'm>UserOnForeignWiki' ), 'Is blocking blockee' );
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
'm>MetaWikiUser',
|
|
|
|
|
$block->getBlocker()->getName(),
|
|
|
|
|
'Correct blocker name'
|
|
|
|
|
);
|
|
|
|
|
$this->assertEquals( 'm>MetaWikiUser', $block->getByName(), 'Correct blocker name' );
|
|
|
|
|
}
|
|
|
|
|
|
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 ) );
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-26 19:51:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers ::getWikiId
|
|
|
|
|
*/
|
|
|
|
|
public function testGetWikiId() {
|
2022-07-19 10:57:01 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::LocalDatabases, [ 'foo' ] );
|
2022-01-20 18:38:30 +00:00
|
|
|
$dbMock = $this->createMock( DBConnRef::class );
|
|
|
|
|
$dbMock->method( 'decodeExpiry' )->willReturn( 'infinity' );
|
|
|
|
|
$lbMock = $this->createMock( ILoadBalancer::class );
|
|
|
|
|
$lbMock->method( 'getConnectionRef' )->willReturn( $dbMock );
|
|
|
|
|
$lbFactoryMock = $this->createMock( LBFactory::class );
|
|
|
|
|
$lbFactoryMock->method( 'getMainLB' )->willReturn( $lbMock );
|
|
|
|
|
$this->setService( 'DBLoadBalancerFactory', $lbFactoryMock );
|
|
|
|
|
|
2021-09-26 19:51:13 +00:00
|
|
|
$block = new DatabaseBlock( [ 'wiki' => 'foo' ] );
|
|
|
|
|
$this->assertSame( 'foo', $block->getWikiId() );
|
2022-01-20 18:38:30 +00:00
|
|
|
|
|
|
|
|
$this->resetServices();
|
|
|
|
|
|
2021-09-26 19:51:13 +00:00
|
|
|
$localBlock = new DatabaseBlock();
|
|
|
|
|
$this->assertSame( WikiAwareEntity::LOCAL, $localBlock->getWikiId() );
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 04:55:55 +00:00
|
|
|
/**
|
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() {
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->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( [
|
2023-11-05 23:53:56 +00:00
|
|
|
'address' => $badActor,
|
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.
|
2023-10-31 07:57:33 +00:00
|
|
|
$block = $blockStore->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
|
|
|
* 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() {
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->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( [
|
2023-11-05 23:53:56 +00:00
|
|
|
'address' => $badActor,
|
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.
|
2023-09-21 16:37:37 +00:00
|
|
|
$count = $this->db->newSelectQueryBuilder()
|
|
|
|
|
->select( '*' )
|
|
|
|
|
->from( 'ipblocks_restrictions' )
|
|
|
|
|
->where( [ 'ir_ipb_id' => 0 ] )
|
|
|
|
|
->caller( __METHOD__ )->fetchRowCount();
|
2018-08-16 04:55:55 +00:00
|
|
|
$this->assertSame( 0, $count );
|
|
|
|
|
}
|
|
|
|
|
|
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() {
|
2022-07-19 10:57:01 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::BlockDisablesLogin, 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
|
|
|
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
2020-08-27 09:27:10 +00:00
|
|
|
$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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
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() {
|
2022-07-19 10:57:01 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::BlockDisablesLogin, 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
|
|
|
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
2020-08-27 09:27:10 +00:00
|
|
|
$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() ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToNamespace
|
|
|
|
|
* @covers ::appliesToPage
|
2018-10-30 18:19:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testAppliesToReturnsTrueOnSitewideBlock() {
|
2022-07-19 10:57:01 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::BlockDisablesLogin, 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
|
|
|
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
2020-08-27 09:27:10 +00:00
|
|
|
$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 ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToPage
|
2018-10-30 18:19:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testAppliesToPageOnPartialPageBlock() {
|
2022-07-19 10:57:01 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::BlockDisablesLogin, 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
|
|
|
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
2020-08-27 09:27:10 +00:00
|
|
|
$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() ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-05-13 14:18:07 +00:00
|
|
|
* @covers ::appliesToNamespace
|
2018-10-30 18:19:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testAppliesToNamespaceOnPartialNamespaceBlock() {
|
2022-07-19 10:57:01 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::BlockDisablesLogin, 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
|
|
|
|
2022-01-12 20:13:39 +00:00
|
|
|
$blockStore = $this->getServiceContainer()->getDatabaseBlockStore();
|
2020-08-27 09:27:10 +00:00
|
|
|
$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
|
|
|
}
|
|
|
|
|
|
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
|
|
|
*/
|
2023-11-01 20:42:01 +00:00
|
|
|
public function testBlockAllowsRead() {
|
2022-07-19 10:57:01 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::BlockDisablesLogin, false );
|
2019-05-13 14:18:07 +00:00
|
|
|
$block = new DatabaseBlock();
|
2023-11-01 20:42:01 +00:00
|
|
|
$this->assertFalse( $block->appliesToRight( 'read' ) );
|
2019-01-08 21:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
2019-04-11 19:54:10 +00:00
|
|
|
/**
|
|
|
|
|
* Get an instance of BlockRestrictionStore
|
|
|
|
|
*
|
|
|
|
|
* @return BlockRestrictionStore
|
|
|
|
|
*/
|
2021-07-22 03:11:47 +00:00
|
|
|
protected function getBlockRestrictionStore(): BlockRestrictionStore {
|
2022-01-12 20:13:39 +00:00
|
|
|
return $this->getServiceContainer()->getBlockRestrictionStore();
|
2019-04-11 19:54:10 +00:00
|
|
|
}
|
2010-12-28 19:12:27 +00:00
|
|
|
}
|