diff options
author | Tim Starling <tstarling@wikimedia.org> | 2024-12-11 12:29:29 +1100 |
---|---|---|
committer | Tim Starling <tstarling@wikimedia.org> | 2024-12-16 12:35:24 +1100 |
commit | cf1198155c27e1cb4b02ec9ab01d91c0820f0667 (patch) | |
tree | 1b141a4f45cf3aec7b9a4de696510326980261c7 /tests | |
parent | f69f8de8d2b561b8ff1e019eb94a09c62c3d3ad9 (diff) | |
download | mediawikicore-cf1198155c27e1cb4b02ec9ab01d91c0820f0667.tar.gz mediawikicore-cf1198155c27e1cb4b02ec9ab01d91c0820f0667.zip |
block: Multiblocks block API
In ApiBlock:
* Add an "id" parameter. If this is given, update the specified block.
* Add a "newblock" parameter. If this is given, always add a new block,
don't check if the target is already blocked.
* If "reblock" is given and the target has more than one block, fail
with an "ambiguous-block" error.
Supporting changes:
* Add BlockUserFactory::newUpdateBlock(), which takes a DatabaseBlock
instead of a target union to act on. The block is passed through to
the BlockUser constructor.
* Rename the first parameter to BlockUser::placeBlock() from $reblock to
$conflictMode, and style it like an enum. Add the CONFLICT_NEW value,
to support the "newblock" API option.
* In DatabaseBlockStore::newFromId(), add $fromPrimary, so that ApiBlock
can pass data to BlockUserFactory with equivalent freshness to the
LHS.
Also:
* In BlockUser, memoize prior blocks loaded from the DB
* Move T287798 autoblock check to the memoized accessor. Just don't
return autoblocks.
* Move "TODO handle failure" comment in BlockUser to the called method.
It really can't fail.
* In DatabaseBlockStore::newFromId(), add an $includeExpired parameter
and default to false although it was previously implicitly true.
Based on a brief review of callers, I think this is beneficial.
Bug: T378147
Change-Id: Iea5b77cb27006b33f3dde61660be5ad2c374a425
Diffstat (limited to 'tests')
-rw-r--r-- | tests/phpunit/includes/api/ApiBlockTest.php | 97 | ||||
-rw-r--r-- | tests/phpunit/integration/includes/block/BlockUserTest.php | 51 |
2 files changed, 144 insertions, 4 deletions
diff --git a/tests/phpunit/includes/api/ApiBlockTest.php b/tests/phpunit/includes/api/ApiBlockTest.php index adbeb4bdf796..aa5025b12f7c 100644 --- a/tests/phpunit/includes/api/ApiBlockTest.php +++ b/tests/phpunit/includes/api/ApiBlockTest.php @@ -3,6 +3,7 @@ namespace MediaWiki\Tests\Api; use MediaWiki\Block\DatabaseBlock; +use MediaWiki\Block\DatabaseBlockStore; use MediaWiki\Block\Restriction\ActionRestriction; use MediaWiki\Block\Restriction\NamespaceRestriction; use MediaWiki\Block\Restriction\PageRestriction; @@ -28,6 +29,8 @@ class ApiBlockTest extends ApiTestCase { protected $mUser = null; /** @var DatabaseBlockStore */ private $blockStore; + /** @var DatabaseBlock|null */ + private $block; protected function setUp(): void { parent::setUp(); @@ -40,6 +43,7 @@ class ApiBlockTest extends ApiTestCase { 'IPv6' => 19, ] ); + $this->overrideConfigValue( MainConfigNames::EnableMultiBlocks, true ); $this->blockStore = $this->getServiceContainer()->getDatabaseBlockStore(); } @@ -62,12 +66,12 @@ class ApiBlockTest extends ApiTestCase { } $ret = $this->doApiRequestWithToken( array_merge( $params, $extraParams ), null, $blocker ); - $block = $this->blockStore->newFromTarget( $this->mUser->getName() ); + $this->block = $this->blockStore->newFromId( $ret[0]['block']['id'] ); - $this->assertInstanceOf( DatabaseBlock::class, $block, 'Block is valid' ); + $this->assertInstanceOf( DatabaseBlock::class, $this->block, 'Block is valid' ); - $this->assertSame( $this->mUser->getName(), $block->getTargetName() ); - $this->assertSame( 'Some reason', $block->getReasonComment()->text ); + $this->assertSame( $this->mUser->getName(), $this->block->getTargetName() ); + $this->assertSame( 'Some reason', $this->block->getReasonComment()->text ); return $ret; } @@ -344,4 +348,89 @@ class ApiBlockTest extends ApiTestCase { $this->assertArrayHasKey( 'userID', $blockResult ); $this->assertSame( $userId, $blockResult['userID'] ); } + + public function testConflict() { + $this->doBlock(); + $this->expectApiErrorCode( 'alreadyblocked' ); + $this->doBlock( [ 'noemail' => '' ] ); + } + + public function testReblock() { + $this->doBlock(); + $this->assertFalse( $this->block->isEmailBlocked() ); + $this->doBlock( [ 'noemail' => '', 'reblock' => true ] ); + $this->assertTrue( $this->block->isEmailBlocked() ); + } + + public function testMultiBlocks() { + $this->doBlock(); + $this->doBlock( [ 'noemail' => '', 'newblock' => '' ] ); + $this->assertTrue( $this->block->isEmailBlocked() ); + $this->assertCount( 2, $this->blockStore->newListFromTarget( $this->mUser ) ); + } + + public function testMultiRedundant() { + $this->expectApiErrorCode( 'alreadyblocked' ); + $this->doBlock(); + $this->doBlock( [ 'newblock' => '' ] ); + } + + public function testReblockMulti() { + $this->doBlock(); + $this->doBlock( [ 'noemail' => '', 'newblock' => '' ] ); + $this->expectApiErrorCode( 'ambiguous-block' ); + $this->doBlock( [ 'reblock' => true ] ); + } + + public function testId() { + $this->doBlock(); + $this->assertFalse( $this->block->isEmailBlocked() ); + $this->doBlock( [ 'noemail' => '', 'id' => $this->block->getId(), 'user' => null ] ); + $this->assertTrue( $this->block->isEmailBlocked() ); + } + + public function testIdConflictsWithUser() { + $this->expectApiErrorCode( 'invalidparammix' ); + $this->doBlock( [ 'noemail' => '', 'id' => '1' ] ); + } + + public function testIdConflictsWithNewblock() { + $this->expectApiErrorCode( 'invalidparammix' ); + $this->doBlock( [ 'newblock' => '', 'id' => '1' ] ); + } + + public function testIdConflictsWithReblock() { + $this->expectApiErrorCode( 'invalidparammix' ); + $this->doBlock( [ 'reblock' => '', 'id' => '1' ] ); + } + + public function testIdMulti() { + $this->doBlock(); + $block1 = $this->block->getId(); + $this->doBlock( [ 'allowusertalk' => '', 'newblock' => '' ] ); + $block2 = $this->block->getId(); + $this->assertFalse( $this->blockStore->newFromId( $block2 )->isEmailBlocked() ); + + $this->doBlock( [ 'id' => $block2, 'user' => null, 'noemail' => '' ] ); + $this->assertFalse( $this->blockStore->newFromId( $block1 )->isEmailBlocked() ); + $this->assertTrue( $this->blockStore->newFromId( $block2 )->isEmailBlocked() ); + } + + public function testNoSuchBlockId() { + $this->expectApiErrorCode( 'nosuchblockid' ); + $this->doBlock( [ 'id' => '1', 'user' => null ] ); + } + + public function testModifyAutoblock() { + $this->doBlock( [ 'autoblock' => '' ] ); + $autoId = $this->blockStore->doAutoblock( $this->block, '127.0.0.1' ); + $this->expectApiErrorCode( 'modify-autoblock' ); + $this->doBlock( [ 'id' => $autoId, 'user' => null, 'noemail' => '' ] ); + } + + public function testNoOpBlockUpdate() { + $this->doBlock(); + $this->expectApiErrorCode( 'alreadyblocked' ); + $this->doBlock( [ 'id' => $this->block->getId(), 'user' => null ] ); + } } diff --git a/tests/phpunit/integration/includes/block/BlockUserTest.php b/tests/phpunit/integration/includes/block/BlockUserTest.php index 0957a9e0f52c..5b9f78c382a1 100644 --- a/tests/phpunit/integration/includes/block/BlockUserTest.php +++ b/tests/phpunit/integration/includes/block/BlockUserTest.php @@ -3,6 +3,7 @@ use MediaWiki\Block\BlockUserFactory; use MediaWiki\Block\DatabaseBlock; use MediaWiki\Block\Restriction\PageRestriction; +use MediaWiki\MainConfigNames; use MediaWiki\Tests\Unit\Permissions\MockAuthorityTrait; use MediaWiki\User\User; @@ -244,4 +245,54 @@ class BlockUserTest extends MediaWikiIntegrationTestCase { $this->assertContains( $IPBlock->getId(), $blockIds ); } + /** + * @covers \MediaWiki\Block\BlockUser::placeBlockUnsafe + */ + public function testTooManyContribs() { + // Set the contrib limit to zero so that it fails with one edit + $this->overrideConfigValue( MainConfigNames::HideUserContribLimit, 0 ); + // Reset the stored instance + $this->blockUserFactory = $this->getServiceContainer()->getBlockUserFactory(); + // Make the edit + $this->editPage( 'BlockUserTest', 'test', '', NS_MAIN, $this->user ); + // Try to block the user with the hideuser option + $blockStatus = $this->blockUserFactory->newBlockUser( + $this->user, + $this->getTestUser( [ 'sysop', 'suppress' ] )->getUser(), + 'infinity', + 'test block', + [ 'isHideUser' => true ] + )->placeBlockUnsafe(); + $this->assertStatusError( 'ipb_hide_invalid', $blockStatus ); + } + + /** + * @covers \MediaWiki\Block\BlockUser::placeBlockUnsafe + */ + public function testUpdateWithTooManyContribs() { + $this->overrideConfigValue( MainConfigNames::HideUserContribLimit, 0 ); + $this->blockUserFactory = $this->getServiceContainer()->getBlockUserFactory(); + $this->editPage( 'BlockUserTest', 'test', '', NS_MAIN, $this->user ); + $performer = $this->getTestUser( [ 'sysop', 'suppress' ] )->getUser(); + // Make a regular block, without the hideuser option + $blockStatus = $this->blockUserFactory->newBlockUser( + $this->user, + $performer, + 'infinity', + 'test block' + )->placeBlockUnsafe(); + $this->assertStatusGood( $blockStatus ); + + // Try to change the block to include the hideuser option, which should + // fail due to the edit + $blockStatus = $this->blockUserFactory->newUpdateBlock( + $blockStatus->value, + $performer, + 'infinity', + 'test block', + [ 'isHideUser' => true ] + )->placeBlockUnsafe(); + $this->assertStatusError( 'ipb_hide_invalid', $blockStatus ); + } + } |