diff options
16 files changed, 292 insertions, 602 deletions
diff --git a/autoload.php b/autoload.php index ffcec57a34b9..42d2dfac6e1a 100644 --- a/autoload.php +++ b/autoload.php @@ -1294,6 +1294,7 @@ $wgAutoloadLocalClasses = [ 'MediaWiki\\DomainEvent\\EventSubscriberBase' => __DIR__ . '/includes/DomainEvent/DomainEventIngress.php', 'MediaWiki\\DomainEvent\\InitializableDomainEventSubscriber' => __DIR__ . '/includes/DomainEvent/InitializableDomainEventSubscriber.php', 'MediaWiki\\EditPage\\Constraint\\AccidentalRecreationConstraint' => __DIR__ . '/includes/editpage/Constraint/AccidentalRecreationConstraint.php', + 'MediaWiki\\EditPage\\Constraint\\AuthorizationConstraint' => __DIR__ . '/includes/editpage/Constraint/AuthorizationConstraint.php', 'MediaWiki\\EditPage\\Constraint\\BrokenRedirectConstraint' => __DIR__ . '/includes/editpage/Constraint/BrokenRedirectConstraint.php', 'MediaWiki\\EditPage\\Constraint\\ChangeTagsConstraint' => __DIR__ . '/includes/editpage/Constraint/ChangeTagsConstraint.php', 'MediaWiki\\EditPage\\Constraint\\ContentModelChangeConstraint' => __DIR__ . '/includes/editpage/Constraint/ContentModelChangeConstraint.php', @@ -1302,10 +1303,10 @@ $wgAutoloadLocalClasses = [ 'MediaWiki\\EditPage\\Constraint\\EditConstraintFactory' => __DIR__ . '/includes/editpage/Constraint/EditConstraintFactory.php', 'MediaWiki\\EditPage\\Constraint\\EditConstraintRunner' => __DIR__ . '/includes/editpage/Constraint/EditConstraintRunner.php', 'MediaWiki\\EditPage\\Constraint\\EditFilterMergedContentHookConstraint' => __DIR__ . '/includes/editpage/Constraint/EditFilterMergedContentHookConstraint.php', - 'MediaWiki\\EditPage\\Constraint\\EditRightConstraint' => __DIR__ . '/includes/editpage/Constraint/EditRightConstraint.php', 'MediaWiki\\EditPage\\Constraint\\ExistingSectionEditConstraint' => __DIR__ . '/includes/editpage/Constraint/ExistingSectionEditConstraint.php', 'MediaWiki\\EditPage\\Constraint\\IEditConstraint' => __DIR__ . '/includes/editpage/Constraint/IEditConstraint.php', 'MediaWiki\\EditPage\\Constraint\\ImageRedirectConstraint' => __DIR__ . '/includes/editpage/Constraint/ImageRedirectConstraint.php', + 'MediaWiki\\EditPage\\Constraint\\LinkPurgeRateLimitConstraint' => __DIR__ . '/includes/editpage/Constraint/LinkPurgeRateLimitConstraint.php', 'MediaWiki\\EditPage\\Constraint\\MissingCommentConstraint' => __DIR__ . '/includes/editpage/Constraint/MissingCommentConstraint.php', 'MediaWiki\\EditPage\\Constraint\\NewSectionMissingSubjectConstraint' => __DIR__ . '/includes/editpage/Constraint/NewSectionMissingSubjectConstraint.php', 'MediaWiki\\EditPage\\Constraint\\PageSizeConstraint' => __DIR__ . '/includes/editpage/Constraint/PageSizeConstraint.php', @@ -1314,8 +1315,6 @@ $wgAutoloadLocalClasses = [ 'MediaWiki\\EditPage\\Constraint\\SimpleAntiSpamConstraint' => __DIR__ . '/includes/editpage/Constraint/SimpleAntiSpamConstraint.php', 'MediaWiki\\EditPage\\Constraint\\SpamRegexConstraint' => __DIR__ . '/includes/editpage/Constraint/SpamRegexConstraint.php', 'MediaWiki\\EditPage\\Constraint\\UnicodeConstraint' => __DIR__ . '/includes/editpage/Constraint/UnicodeConstraint.php', - 'MediaWiki\\EditPage\\Constraint\\UserBlockConstraint' => __DIR__ . '/includes/editpage/Constraint/UserBlockConstraint.php', - 'MediaWiki\\EditPage\\Constraint\\UserRateLimitConstraint' => __DIR__ . '/includes/editpage/Constraint/UserRateLimitConstraint.php', 'MediaWiki\\EditPage\\EditPage' => __DIR__ . '/includes/editpage/EditPage.php', 'MediaWiki\\EditPage\\IEditObject' => __DIR__ . '/includes/editpage/IEditObject.php', 'MediaWiki\\EditPage\\IntroMessageBuilder' => __DIR__ . '/includes/editpage/IntroMessageBuilder.php', diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index f82bb3598935..68ec604820dd 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -2793,9 +2793,6 @@ return [ ), LoggerFactory::getProvider(), - // UserBlockConstraint - $services->getPermissionManager(), - // EditFilterMergedContentHookConstraint $services->getHookContainer(), @@ -2805,7 +2802,7 @@ return [ // SpamRegexConstraint $services->getSpamChecker(), - // UserRateLimitConstraint + // LinkPurgeRateLimitConstraint $services->getRateLimiter() ); }, diff --git a/includes/editpage/Constraint/AuthorizationConstraint.php b/includes/editpage/Constraint/AuthorizationConstraint.php new file mode 100644 index 000000000000..73247160fa7b --- /dev/null +++ b/includes/editpage/Constraint/AuthorizationConstraint.php @@ -0,0 +1,88 @@ +<?php +/** + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + */ + +namespace MediaWiki\EditPage\Constraint; + +use MediaWiki\Page\PageIdentity; +use MediaWiki\Permissions\Authority; +use MediaWiki\Permissions\PermissionStatus; +use StatusValue; + +/** + * Verify authorization to edit the page (user rights, rate limits, blocks). + * + * @since 1.44 + * @internal + */ +class AuthorizationConstraint implements IEditConstraint { + + private PermissionStatus $status; + + private Authority $performer; + private PageIdentity $target; + private bool $new; + + public function __construct( + Authority $performer, + PageIdentity $target, + bool $new + ) { + $this->performer = $performer; + $this->target = $target; + $this->new = $new; + } + + public function checkConstraint(): string { + $this->status = PermissionStatus::newEmpty(); + + if ( $this->new && !$this->performer->authorizeWrite( 'create', $this->target, $this->status ) ) { + return self::CONSTRAINT_FAILED; + } + + if ( !$this->performer->authorizeWrite( 'edit', $this->target, $this->status ) ) { + return self::CONSTRAINT_FAILED; + } + + return self::CONSTRAINT_PASSED; + } + + public function getLegacyStatus(): StatusValue { + $statusValue = StatusValue::newGood(); + + if ( !$this->status->isGood() ) { + // Report the most specific errors first + if ( $this->status->isBlocked() ) { + $statusValue->setResult( false, self::AS_BLOCKED_PAGE_FOR_USER ); + } elseif ( $this->status->isRateLimitExceeded() ) { + $statusValue->setResult( false, self::AS_RATE_LIMITED ); + } elseif ( $this->status->getPermission() === 'create' ) { + $statusValue->setResult( false, self::AS_NO_CREATE_PERMISSION ); + } elseif ( !$this->performer->isRegistered() ) { + $statusValue->setResult( false, self::AS_READ_ONLY_PAGE_ANON ); + } else { + $statusValue->setResult( false, self::AS_READ_ONLY_PAGE_LOGGED ); + } + } + + // TODO: Use error messages from the PermissionStatus ($this->status) here - T384399 + return $statusValue; + } + +} diff --git a/includes/editpage/Constraint/ContentModelChangeConstraint.php b/includes/editpage/Constraint/ContentModelChangeConstraint.php index 8ed2e56debde..2581ebab3c14 100644 --- a/includes/editpage/Constraint/ContentModelChangeConstraint.php +++ b/includes/editpage/Constraint/ContentModelChangeConstraint.php @@ -21,6 +21,7 @@ namespace MediaWiki\EditPage\Constraint; use MediaWiki\Permissions\Authority; +use MediaWiki\Permissions\PermissionStatus; use MediaWiki\Title\Title; use StatusValue; @@ -28,6 +29,7 @@ use StatusValue; * Verify user permissions if changing content model: * Must have editcontentmodel rights * Must be able to edit under the new content model + * Must not have exceeded the rate limit * * @since 1.36 * @internal @@ -35,10 +37,11 @@ use StatusValue; */ class ContentModelChangeConstraint implements IEditConstraint { + private PermissionStatus $status; + private Authority $performer; private Title $title; private string $newContentModel; - private string $result; /** * @param Authority $performer @@ -56,45 +59,43 @@ class ContentModelChangeConstraint implements IEditConstraint { } public function checkConstraint(): string { + $this->status = PermissionStatus::newEmpty(); + if ( $this->newContentModel === $this->title->getContentModel() ) { // No change - $this->result = self::CONSTRAINT_PASSED; return self::CONSTRAINT_PASSED; } - if ( !$this->performer->isAllowed( 'editcontentmodel' ) ) { - $this->result = self::CONSTRAINT_FAILED; + if ( !$this->performer->authorizeWrite( 'editcontentmodel', $this->title, $this->status ) ) { return self::CONSTRAINT_FAILED; } - // Make sure the user can edit the page under the new content model too + // Make sure the user can edit the page under the new content model too. + // We rely on caching in UserAuthority to avoid bumping the rate limit counter twice. $titleWithNewContentModel = clone $this->title; $titleWithNewContentModel->setContentModel( $this->newContentModel ); - - $canEditModel = $this->performer->authorizeWrite( - 'editcontentmodel', - $titleWithNewContentModel - ); - if ( - !$canEditModel - || !$this->performer->authorizeWrite( 'edit', $titleWithNewContentModel ) + !$this->performer->authorizeWrite( 'editcontentmodel', $titleWithNewContentModel, $this->status ) + || !$this->performer->authorizeWrite( 'edit', $titleWithNewContentModel, $this->status ) ) { - $this->result = self::CONSTRAINT_FAILED; return self::CONSTRAINT_FAILED; } - $this->result = self::CONSTRAINT_PASSED; return self::CONSTRAINT_PASSED; } public function getLegacyStatus(): StatusValue { $statusValue = StatusValue::newGood(); - if ( $this->result === self::CONSTRAINT_FAILED ) { - $statusValue->setResult( false, self::AS_NO_CHANGE_CONTENT_MODEL ); + if ( !$this->status->isGood() ) { + if ( $this->status->isRateLimitExceeded() ) { + $statusValue->setResult( false, self::AS_RATE_LIMITED ); + } else { + $statusValue->setResult( false, self::AS_NO_CHANGE_CONTENT_MODEL ); + } } + // TODO: Use error messages from the PermissionStatus ($this->status) here - T384399 return $statusValue; } diff --git a/includes/editpage/Constraint/EditConstraintFactory.php b/includes/editpage/Constraint/EditConstraintFactory.php index 750c977d2312..e9fede9f256c 100644 --- a/includes/editpage/Constraint/EditConstraintFactory.php +++ b/includes/editpage/Constraint/EditConstraintFactory.php @@ -26,10 +26,8 @@ use MediaWiki\Context\IContextSource; use MediaWiki\EditPage\SpamChecker; use MediaWiki\HookContainer\HookContainer; use MediaWiki\Language\Language; -use MediaWiki\Linker\LinkTarget; use MediaWiki\Logger\Spi; use MediaWiki\MainConfigNames; -use MediaWiki\Permissions\PermissionManager; use MediaWiki\Permissions\RateLimiter; use MediaWiki\Permissions\RateLimitSubject; use MediaWiki\Title\Title; @@ -54,7 +52,6 @@ class EditConstraintFactory { private ServiceOptions $options; private Spi $loggerFactory; - private PermissionManager $permissionManager; private HookContainer $hookContainer; private ReadOnlyMode $readOnlyMode; private SpamChecker $spamRegexChecker; @@ -74,7 +71,6 @@ class EditConstraintFactory { * * @param ServiceOptions $options * @param Spi $loggerFactory - * @param PermissionManager $permissionManager * @param HookContainer $hookContainer * @param ReadOnlyMode $readOnlyMode * @param SpamChecker $spamRegexChecker @@ -83,7 +79,6 @@ class EditConstraintFactory { public function __construct( ServiceOptions $options, Spi $loggerFactory, - PermissionManager $permissionManager, HookContainer $hookContainer, ReadOnlyMode $readOnlyMode, SpamChecker $spamRegexChecker, @@ -95,9 +90,6 @@ class EditConstraintFactory { $this->options = $options; $this->loggerFactory = $loggerFactory; - // UserBlockConstraint - $this->permissionManager = $permissionManager; - // EditFilterMergedContentHookConstraint $this->hookContainer = $hookContainer; @@ -107,7 +99,7 @@ class EditConstraintFactory { // SpamRegexConstraint $this->spamRegexChecker = $spamRegexChecker; - // UserRateLimitConstraint + // LinkPurgeRateLimitConstraint $this->rateLimiter = $rateLimiter; } @@ -163,21 +155,15 @@ class EditConstraintFactory { /** * @param RateLimitSubject $subject - * @param string $oldModel - * @param string $newModel * - * @return UserRateLimitConstraint + * @return LinkPurgeRateLimitConstraint */ - public function newUserRateLimitConstraint( - RateLimitSubject $subject, - string $oldModel, - string $newModel - ): UserRateLimitConstraint { - return new UserRateLimitConstraint( + public function newLinkPurgeRateLimitConstraint( + RateLimitSubject $subject + ): LinkPurgeRateLimitConstraint { + return new LinkPurgeRateLimitConstraint( $this->rateLimiter, - $subject, - $oldModel, - $newModel + $subject ); } @@ -226,39 +212,4 @@ class EditConstraintFactory { ); } - /** - * @param LinkTarget $title - * @param User $user - * @return UserBlockConstraint - */ - public function newUserBlockConstraint( - LinkTarget $title, - User $user - ): UserBlockConstraint { - return new UserBlockConstraint( - $this->permissionManager, - $title, - $user - ); - } - - /** - * @param User $performer - * @param Title $title - * @param bool $new - * @return EditRightConstraint - */ - public function newEditRightConstraint( - User $performer, - Title $title, - bool $new - ): EditRightConstraint { - return new EditRightConstraint( - $performer, - $this->permissionManager, - $title, - $new - ); - } - } diff --git a/includes/editpage/Constraint/EditRightConstraint.php b/includes/editpage/Constraint/EditRightConstraint.php deleted file mode 100644 index 47be037e4dad..000000000000 --- a/includes/editpage/Constraint/EditRightConstraint.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * http://www.gnu.org/copyleft/gpl.html - * - * @file - */ - -namespace MediaWiki\EditPage\Constraint; - -use MediaWiki\Permissions\PermissionManager; -use MediaWiki\Title\Title; -use MediaWiki\User\User; -use StatusValue; - -/** - * Verify user permissions: - * Must have edit rights - * - * @since 1.36 - * @internal - * @author DannyS712 - */ -class EditRightConstraint implements IEditConstraint { - - private User $performer; - private PermissionManager $permManager; - private Title $title; - private string $result; - private bool $new; - - /** - * @param User $performer - * @param PermissionManager $permManager - * @param Title $title - * @param bool $new - */ - public function __construct( - User $performer, - PermissionManager $permManager, - Title $title, - bool $new - ) { - $this->performer = $performer; - $this->permManager = $permManager; - $this->title = $title; - $this->new = $new; - } - - public function checkConstraint(): string { - if ( $this->new ) { - // Check isn't simple enough to just repeat when getting the status - if ( !$this->performer->authorizeWrite( 'create', $this->title ) ) { - $this->result = (string)self::AS_NO_CREATE_PERMISSION; - return self::CONSTRAINT_FAILED; - } - } - - // Check isn't simple enough to just repeat when getting the status - // Prior to 1.41 this checked if the user had edit rights in general - // instead of for the specific page in question. - if ( !$this->permManager->userCan( - 'edit', - $this->performer, - $this->title - ) ) { - $this->result = self::CONSTRAINT_FAILED; - return self::CONSTRAINT_FAILED; - } - - $this->result = self::CONSTRAINT_PASSED; - return self::CONSTRAINT_PASSED; - } - - public function getLegacyStatus(): StatusValue { - $statusValue = StatusValue::newGood(); - - if ( $this->result === self::CONSTRAINT_FAILED ) { - if ( !$this->performer->isRegistered() ) { - $statusValue->setResult( false, self::AS_READ_ONLY_PAGE_ANON ); - } else { - $statusValue->fatal( 'readonlytext' ); - $statusValue->value = self::AS_READ_ONLY_PAGE_LOGGED; - } - } elseif ( $this->result === (string)self::AS_NO_CREATE_PERMISSION ) { - $statusValue->fatal( 'nocreatetext' ); - $statusValue->value = self::AS_NO_CREATE_PERMISSION; - } - - return $statusValue; - } - -} diff --git a/includes/editpage/Constraint/UserRateLimitConstraint.php b/includes/editpage/Constraint/LinkPurgeRateLimitConstraint.php index 8f35dd5879d0..d25cf9336d88 100644 --- a/includes/editpage/Constraint/UserRateLimitConstraint.php +++ b/includes/editpage/Constraint/LinkPurgeRateLimitConstraint.php @@ -25,31 +25,26 @@ use MediaWiki\Permissions\RateLimitSubject; use StatusValue; /** - * Verify user doesn't exceed rate limits + * Verify that the user doesn't exceed 'linkpurge' limits, which are weird and special. + * Other rate limits have been integrated into their respective permission checks. * - * @since 1.36 + * @since 1.44 * @internal * @author DannyS712 */ -class UserRateLimitConstraint implements IEditConstraint { +class LinkPurgeRateLimitConstraint implements IEditConstraint { private RateLimitSubject $subject; - private string $oldContentModel; - private string $newContentModel; private RateLimiter $limiter; private string $result; public function __construct( RateLimiter $limiter, - RateLimitSubject $subject, - string $oldContentModel, - string $newContentModel + RateLimitSubject $subject ) { $this->limiter = $limiter; $this->subject = $subject; - $this->oldContentModel = $oldContentModel; - $this->newContentModel = $newContentModel; } private function limit( string $action, int $inc = 1 ): bool { @@ -57,16 +52,10 @@ class UserRateLimitConstraint implements IEditConstraint { } public function checkConstraint(): string { - // Need to check for rate limits on `editcontentmodel` if it is changing - $contentModelChange = ( $this->newContentModel !== $this->oldContentModel ); - // TODO inject and use a ThrottleStore once available, see T261744 // Checking if the user is rate limited increments the counts, so we cannot perform // the check again when getting the status; thus, store the result - if ( $this->limit( 'edit' ) - || $this->limit( 'linkpurge', 0 ) // only counted after the fact - || ( $contentModelChange && $this->limit( 'editcontentmodel' ) ) - ) { + if ( $this->limit( 'linkpurge', /* only counted after the fact */ 0 ) ) { $this->result = self::CONSTRAINT_FAILED; } else { $this->result = self::CONSTRAINT_PASSED; diff --git a/includes/editpage/Constraint/UserBlockConstraint.php b/includes/editpage/Constraint/UserBlockConstraint.php deleted file mode 100644 index bdd33262d434..000000000000 --- a/includes/editpage/Constraint/UserBlockConstraint.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php -/** - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * http://www.gnu.org/copyleft/gpl.html - * - * @file - */ - -namespace MediaWiki\EditPage\Constraint; - -use MediaWiki\Linker\LinkTarget; -use MediaWiki\Permissions\PermissionManager; -use MediaWiki\User\User; -use StatusValue; - -/** - * Verify user permissions: - * Must not be blocked from the page - * - * @since 1.36 - * @internal - * @author DannyS712 - */ -class UserBlockConstraint implements IEditConstraint { - - private PermissionManager $permissionManager; - private LinkTarget $title; - private User $user; - private string $result; - - /** - * @param PermissionManager $permissionManager - * @param LinkTarget $title - * @param User $user - */ - public function __construct( - PermissionManager $permissionManager, - LinkTarget $title, - User $user - ) { - $this->permissionManager = $permissionManager; - $this->title = $title; - $this->user = $user; - } - - public function checkConstraint(): string { - // Check isn't simple enough to just repeat when getting the status - if ( $this->permissionManager->isBlockedFrom( $this->user, $this->title ) ) { - $this->result = self::CONSTRAINT_FAILED; - return self::CONSTRAINT_FAILED; - } - - $this->result = self::CONSTRAINT_PASSED; - return self::CONSTRAINT_PASSED; - } - - public function getLegacyStatus(): StatusValue { - $statusValue = StatusValue::newGood(); - - if ( $this->result === self::CONSTRAINT_FAILED ) { - $statusValue->setResult( false, self::AS_BLOCKED_PAGE_FOR_USER ); - } - - return $statusValue; - } - -} diff --git a/includes/editpage/EditPage.php b/includes/editpage/EditPage.php index 93a3ad5a28e8..f08196894d88 100644 --- a/includes/editpage/EditPage.php +++ b/includes/editpage/EditPage.php @@ -37,6 +37,7 @@ use MediaWiki\Context\IContextSource; use MediaWiki\Debug\DeprecationHelper; use MediaWiki\Deferred\DeferredUpdates; use MediaWiki\EditPage\Constraint\AccidentalRecreationConstraint; +use MediaWiki\EditPage\Constraint\AuthorizationConstraint; use MediaWiki\EditPage\Constraint\BrokenRedirectConstraint; use MediaWiki\EditPage\Constraint\ChangeTagsConstraint; use MediaWiki\EditPage\Constraint\ContentModelChangeConstraint; @@ -54,7 +55,6 @@ use MediaWiki\EditPage\Constraint\PageSizeConstraint; use MediaWiki\EditPage\Constraint\SelfRedirectConstraint; use MediaWiki\EditPage\Constraint\SpamRegexConstraint; use MediaWiki\EditPage\Constraint\UnicodeConstraint; -use MediaWiki\EditPage\Constraint\UserBlockConstraint; use MediaWiki\Exception\ErrorPageError; use MediaWiki\Exception\MWContentSerializationException; use MediaWiki\Exception\MWException; @@ -2189,24 +2189,31 @@ class EditPage implements IEditObject { ) ); $constraintRunner->addConstraint( - $constraintFactory->newUserBlockConstraint( $this->mTitle, $requestUser ) + $constraintFactory->newReadOnlyConstraint() ); + + // Load the page data from the primary DB. If anything changes in the meantime, + // we detect it by using page_latest like a token in a 1 try compare-and-swap. + $this->page->loadPageData( IDBAccessObject::READ_LATEST ); + $new = !$this->page->exists(); + $constraintRunner->addConstraint( - new ContentModelChangeConstraint( + new AuthorizationConstraint( $authority, $this->mTitle, - $this->contentModel + $new ) ); - $constraintRunner->addConstraint( - $constraintFactory->newReadOnlyConstraint() + new ContentModelChangeConstraint( + $authority, + $this->mTitle, + $this->contentModel + ) ); $constraintRunner->addConstraint( - $constraintFactory->newUserRateLimitConstraint( - $requestUser->toRateLimitSubject(), - $this->mTitle->getContentModel(), - $this->contentModel + $constraintFactory->newLinkPurgeRateLimitConstraint( + $requestUser->toRateLimitSubject() ) ); $constraintRunner->addConstraint( @@ -2230,16 +2237,6 @@ class EditPage implements IEditObject { ) ); - // Load the page data from the primary DB. If anything changes in the meantime, - // we detect it by using page_latest like a token in a 1 try compare-and-swap. - $this->page->loadPageData( IDBAccessObject::READ_LATEST ); - $new = !$this->page->exists(); - - // We do this last, as some of the other constraints are more specific - $constraintRunner->addConstraint( - $constraintFactory->newEditRightConstraint( $this->getUserForPermissions(), $this->mTitle, $new ) - ); - // Check the constraints if ( !$constraintRunner->checkConstraints() ) { $failed = $constraintRunner->getFailedConstraint(); @@ -2625,9 +2622,12 @@ class EditPage implements IEditObject { * result from the backend. */ private function handleFailedConstraint( IEditConstraint $failed ): void { - if ( $failed instanceof UserBlockConstraint ) { + if ( $failed instanceof AuthorizationConstraint ) { // Auto-block user's IP if the account was "hard" blocked - if ( !MediaWikiServices::getInstance()->getReadOnlyMode()->isReadOnly() ) { + if ( + !MediaWikiServices::getInstance()->getReadOnlyMode()->isReadOnly() + && $failed->getLegacyStatus()->value === self::AS_BLOCKED_PAGE_FOR_USER + ) { $this->context->getUser()->spreadAnyEditBlock(); } } elseif ( $failed instanceof DefaultTextConstraint ) { diff --git a/tests/phpunit/includes/editpage/EditPageConstraintsTest.php b/tests/phpunit/includes/editpage/EditPageConstraintsTest.php index 2ca607066035..84dbbc7c7723 100644 --- a/tests/phpunit/includes/editpage/EditPageConstraintsTest.php +++ b/tests/phpunit/includes/editpage/EditPageConstraintsTest.php @@ -7,7 +7,9 @@ use MediaWiki\EditPage\EditPage; use MediaWiki\EditPage\SpamChecker; use MediaWiki\MainConfigNames; use MediaWiki\Permissions\PermissionManager; +use MediaWiki\Permissions\PermissionStatus; use MediaWiki\Request\FauxRequest; +use MediaWiki\Tests\Unit\MockBlockTrait; use MediaWiki\Tests\User\TempUser\TempUserTestTrait; use MediaWiki\Title\Title; use MediaWiki\User\User; @@ -27,6 +29,7 @@ use Wikimedia\Rdbms\ReadOnlyMode; class EditPageConstraintsTest extends MediaWikiLangTestCase { use TempUserTestTrait; + use MockBlockTrait; protected function setUp(): void { parent::setUp(); @@ -183,8 +186,8 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { $user = $this->getTestUser()->getUser(); $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit rights to pass EditRightConstraint and reach AccidentalRecreationConstraint - $permissionManager->overrideUserRightsForTesting( $user, [ 'edit' ] ); + // Needs these rights to pass AuthorizationConstraint and reach AccidentalRecreationConstraint + $permissionManager->overrideUserRightsForTesting( $user, [ 'edit', 'createpage' ] ); // Started the edit on 1 January 2019, page was deleted on 1 January 2020 $edit = [ @@ -215,7 +218,7 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { $user = $this->getTestUser()->getUser(); $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit rights to pass EditRightConstraint and reach NewSectionMissingSubjectConstraint + // Needs these rights to pass AuthorizationConstraint and reach NewSectionMissingSubjectConstraint $permissionManager->overrideUserRightsForTesting( $user, [ 'edit' ] ); $edit = [ @@ -258,7 +261,7 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { public function testContentModelChangeConstraint() { $user = $this->getTestUser()->getUser(); $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit rights to pass EditRightConstraint and reach ContentModelChangeConstraint + // Needs these rights to pass AuthorizationConstraint and reach ContentModelChangeConstraint $permissionManager->overrideUserRightsForTesting( $user, [ 'edit' ] ); $edit = [ @@ -285,14 +288,13 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { ); } - /** CreationPermissionConstraint integration */ - public function testCreationPermissionConstraint() { - $page = $this->getNonexistingTestPage( 'CreationPermissionConstraint page does not exist' ); + /** AuthorizationConstraint integration - 'create' rights */ + public function testAuthorizationConstraint_create() { + $page = $this->getNonexistingTestPage( 'AuthorizationConstraint_create page does not exist' ); $title = $page->getTitle(); $user = $this->getTestUser()->getUser(); $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit rights to pass EditRightConstraint and reach CreationPermissionConstraint $permissionManager->overrideUserRightsForTesting( $user, [ 'edit' ] ); $edit = [ @@ -316,7 +318,7 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { $user = $this->getTestUser()->getUser(); $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit and createpage rights to pass EditRightConstraint and CreationPermissionConstraint + // Needs these rights to pass AuthorizationConstraint $permissionManager->overrideUserRightsForTesting( $user, [ 'edit', 'createpage' ] ); $edit = [ @@ -366,7 +368,7 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { $user = $this->getTestUser()->getUser(); $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit and createpage rights to pass EditRightConstraint and CreationPermissionConstraint + // Needs these rights to pass AuthorizationConstraint $permissionManager->overrideUserRightsForTesting( $user, [ 'edit', 'createpage' ] ); $edit = [ @@ -399,12 +401,12 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { } /** - * EditRightConstraint integration - * @dataProvider provideTestEditRightConstraint + * AuthorizationConstraint integration - 'edit' rights + * @dataProvider provideTestAuthorizationConstraint_edit * @param bool $anon * @param int $expectedErrorCode */ - public function testEditRightConstraint( $anon, $expectedErrorCode ) { + public function testAuthorizationConstraint_edit( $anon, $expectedErrorCode ) { if ( $anon ) { $this->disableAutoCreateTempUser(); $user = $this->getServiceContainer()->getUserFactory()->newAnonymous( '127.0.0.1' ); @@ -428,7 +430,7 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { ); } - public static function provideTestEditRightConstraint() { + public static function provideTestAuthorizationConstraint_edit() { yield 'Anonymous user' => [ true, EditPage::AS_READ_ONLY_PAGE_ANON ]; yield 'Registered user' => [ false, EditPage::AS_READ_ONLY_PAGE_LOGGED ]; } @@ -448,7 +450,7 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { } $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit rights to pass EditRightConstraint and reach ImageRedirectConstraint + // Needs these rights to pass AuthorizationConstraint and reach ImageRedirectConstraint $permissionManager->overrideUserRightsForTesting( $user, [ 'edit' ] ); $edit = [ @@ -480,7 +482,7 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { $user = $this->getTestUser()->getUser(); $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit rights to pass EditRightConstraint and reach MissingCommentConstraint + // Needs these rights to pass AuthorizationConstraint and reach MissingCommentConstraint $permissionManager->overrideUserRightsForTesting( $user, [ 'edit' ] ); $edit = [ @@ -512,7 +514,7 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { $user = $this->getTestUser()->getUser(); $permissionManager = $this->getServiceContainer()->getPermissionManager(); - // Needs edit rights to pass EditRightConstraint and reach NewSectionMissingSubjectConstraint + // Needs these rights to pass AuthorizationConstraint and reach NewSectionMissingSubjectConstraint $permissionManager->overrideUserRightsForTesting( $user, [ 'edit' ] ); $edit = [ @@ -646,21 +648,14 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { ); } - /** UserBlockConstraint integration */ - public function testUserBlockConstraint() { - $user = $this->createMock( User::class ); - $user->method( 'getName' )->willReturn( 'NameGoesHere' ); - $user->method( 'getId' )->willReturn( 12345 ); - + /** AuthorizationConstraint integration - user blocks */ + public function testAuthorizationConstraint_block() { $permissionManager = $this->createMock( PermissionManager::class ); - // Needs edit rights to pass EditRightConstraint and reach UserBlockConstraint - $permissionManager->method( 'userHasRight' )->willReturn( true ); - $permissionManager->method( 'userCan' )->willReturn( true ); - + $permissionStatus = PermissionStatus::newEmpty(); + $permissionStatus->setBlock( $this->makeMockBlock() ); // Not worried about the specifics of the method call, those are tested in - // the UserBlockConstraintTest - $permissionManager->method( 'isBlockedFrom' )->willReturn( true ); - + // the AuthorizationConstraintTest + $permissionManager->method( 'getPermissionStatus' )->willReturn( $permissionStatus ); $this->setService( 'PermissionManager', $permissionManager ); $edit = [ @@ -677,8 +672,8 @@ class EditPageConstraintsTest extends MediaWikiLangTestCase { ); } - /** UserRateLimitConstraint integration */ - public function testUserRateLimitConstraint() { + /** LinkPurgeRateLimitConstraint integration */ + public function testLinkPurgeRateLimitConstraint() { $this->setTemporaryHook( 'PingLimiter', static function ( $user, $action, &$result, $incrBy ) { diff --git a/tests/phpunit/mocks/permissions/MockAuthorityTrait.php b/tests/phpunit/mocks/permissions/MockAuthorityTrait.php index b9b0c9350cbd..eedb4e3d7c70 100644 --- a/tests/phpunit/mocks/permissions/MockAuthorityTrait.php +++ b/tests/phpunit/mocks/permissions/MockAuthorityTrait.php @@ -334,6 +334,7 @@ trait MockAuthorityTrait { return true; } ); $mock->method( 'getBlock' )->willReturn( $block ); + $mock->method( 'isRegistered' )->willReturn( $user->isRegistered() ); $mock->method( 'isTemp' )->willReturn( $isTemp ); $mock->method( 'isNamed' )->willReturn( $user->isRegistered() && !$isTemp ); return $mock; diff --git a/tests/phpunit/unit/includes/editpage/Constraint/AuthorizationConstraintTest.php b/tests/phpunit/unit/includes/editpage/Constraint/AuthorizationConstraintTest.php new file mode 100644 index 000000000000..68d8c6541858 --- /dev/null +++ b/tests/phpunit/unit/includes/editpage/Constraint/AuthorizationConstraintTest.php @@ -0,0 +1,111 @@ +<?php +/** + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + */ + +use MediaWiki\EditPage\Constraint\AuthorizationConstraint; +use MediaWiki\EditPage\Constraint\IEditConstraint; +use MediaWiki\Page\PageIdentity; +use MediaWiki\Page\PageIdentityValue; +use MediaWiki\Permissions\Authority; +use MediaWiki\Tests\Unit\MockBlockTrait; +use MediaWiki\Tests\Unit\Permissions\MockAuthorityTrait; +use MediaWiki\User\UserIdentityValue; + +/** + * @covers \MediaWiki\EditPage\Constraint\AuthorizationConstraint + */ +class AuthorizationConstraintTest extends MediaWikiUnitTestCase { + use EditConstraintTestTrait; + use MockAuthorityTrait; + use MockTitleTrait; + use MockBlockTrait; + + /** + * @dataProvider provideTestPass + */ + public function testPass( Authority $performer, PageIdentity $page, bool $new ): void { + $constraint = new AuthorizationConstraint( + $performer, + $page, + $new + ); + $this->assertConstraintPassed( $constraint ); + } + + public function provideTestPass(): iterable { + yield 'Edit existing page' => [ + 'performer' => $this->mockAnonAuthorityWithPermissions( [ 'edit' ] ), + 'page' => PageIdentityValue::localIdentity( 123, NS_MAIN, 'AuthorizationConstraintTest' ), + 'new' => false, + ]; + yield 'Create a new page' => [ + 'performer' => $this->mockAnonAuthorityWithPermissions( [ 'edit', 'create' ] ), + 'page' => PageIdentityValue::localIdentity( 0, NS_MAIN, 'AuthorizationConstraintTest' ), + 'new' => true, + ]; + } + + /** + * @dataProvider provideTestFailure + */ + public function testFailure( + Authority $performer, PageIdentity $page, bool $new, int $expectedValue + ): void { + $constraint = new AuthorizationConstraint( + $performer, + $page, + $new + ); + $this->assertConstraintFailed( $constraint, $expectedValue ); + } + + public function provideTestFailure(): iterable { + yield 'Anonymous user' => [ + 'performer' => $this->mockAnonAuthorityWithoutPermissions( [ 'edit' ] ), + 'page' => PageIdentityValue::localIdentity( 123, NS_MAIN, 'AuthorizationConstraintTest' ), + 'new' => false, + 'expectedValue' => IEditConstraint::AS_READ_ONLY_PAGE_ANON, + ]; + yield 'Registered user' => [ + 'performer' => $this->mockRegisteredAuthorityWithoutPermissions( [ 'edit' ] ), + 'page' => PageIdentityValue::localIdentity( 123, NS_MAIN, 'AuthorizationConstraintTest' ), + 'new' => false, + 'expectedValue' => IEditConstraint::AS_READ_ONLY_PAGE_LOGGED, + ]; + yield 'User without create permission creates a page' => [ + 'performer' => $this->mockAnonAuthorityWithoutPermissions( [ 'create' ] ), + 'page' => PageIdentityValue::localIdentity( 0, NS_MAIN, 'AuthorizationConstraintTest' ), + 'new' => true, + 'expectedValue' => IEditConstraint::AS_NO_CREATE_PERMISSION, + ]; + yield 'Blocked user' => [ + 'performer' => $this->mockUserAuthorityWithBlock( + UserIdentityValue::newRegistered( 42, 'AuthorizationConstraintTest User' ), + $this->makeMockBlock( [ + 'decodedExpiry' => 'infinity', + ] ), + [ 'edit' ] + ), + 'page' => PageIdentityValue::localIdentity( 123, NS_MAIN, 'AuthorizationConstraintTest' ), + 'new' => false, + 'expectedValue' => IEditConstraint::AS_BLOCKED_PAGE_FOR_USER, + ]; + } + +} diff --git a/tests/phpunit/unit/includes/editpage/Constraint/EditConstraintFactoryTest.php b/tests/phpunit/unit/includes/editpage/Constraint/EditConstraintFactoryTest.php index dabb27a15ff1..76ce13cb71d5 100644 --- a/tests/phpunit/unit/includes/editpage/Constraint/EditConstraintFactoryTest.php +++ b/tests/phpunit/unit/includes/editpage/Constraint/EditConstraintFactoryTest.php @@ -27,13 +27,11 @@ use MediaWiki\EditPage\Constraint\PageSizeConstraint; use MediaWiki\EditPage\Constraint\ReadOnlyConstraint; use MediaWiki\EditPage\Constraint\SimpleAntiSpamConstraint; use MediaWiki\EditPage\Constraint\SpamRegexConstraint; -use MediaWiki\EditPage\Constraint\UserBlockConstraint; use MediaWiki\EditPage\SpamChecker; use MediaWiki\HookContainer\HookContainer; use MediaWiki\Language\Language; use MediaWiki\Logger\Spi; use MediaWiki\MainConfigNames; -use MediaWiki\Permissions\PermissionManager; use MediaWiki\Permissions\RateLimiter; use MediaWiki\Title\Title; use MediaWiki\User\User; @@ -61,7 +59,6 @@ class EditConstraintFactoryTest extends MediaWikiUnitTestCase { $factory = new EditConstraintFactory( $options, $loggerFactory, - $this->createMock( PermissionManager::class ), $this->createMock( HookContainer::class ), $this->createMock( ReadOnlyMode::class ), $this->createMock( SpamChecker::class ), @@ -107,9 +104,5 @@ class EditConstraintFactoryTest extends MediaWikiUnitTestCase { $title ) ); - $this->assertInstanceOf( - UserBlockConstraint::class, - $factory->newUserBlockConstraint( $title, $user ) - ); } } diff --git a/tests/phpunit/unit/includes/editpage/Constraint/EditRightConstraintTest.php b/tests/phpunit/unit/includes/editpage/Constraint/EditRightConstraintTest.php deleted file mode 100644 index 9d3346e87d01..000000000000 --- a/tests/phpunit/unit/includes/editpage/Constraint/EditRightConstraintTest.php +++ /dev/null @@ -1,170 +0,0 @@ -<?php -/** - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * http://www.gnu.org/copyleft/gpl.html - * - * @file - */ - -use MediaWiki\EditPage\Constraint\EditRightConstraint; -use MediaWiki\EditPage\Constraint\IEditConstraint; -use MediaWiki\Permissions\PermissionManager; -use MediaWiki\Tests\Unit\Permissions\MockAuthorityTrait; -use MediaWiki\Title\Title; -use MediaWiki\User\User; - -/** - * Tests the EditRightConstraint - * - * @author DannyS712 - * - * @covers \MediaWiki\EditPage\Constraint\EditRightConstraint - */ -class EditRightConstraintTest extends MediaWikiUnitTestCase { - use EditConstraintTestTrait; - use MockAuthorityTrait; - use MockTitleTrait; - - /** - * @dataProvider provideTestPass - * @param User $performer - * @param bool $new - * @param PermissionManager $permissionManager - * @return void - */ - public function testPass( User $performer, bool $new, PermissionManager $permissionManager ) { - $constraint = new EditRightConstraint( - $performer, - $permissionManager, - $this->createMock( Title::class ), - $new - ); - $this->assertConstraintPassed( $constraint ); - } - - public function provideTestPass() { - $title = $this->createMock( Title::class ); - $userEdit = $this->createMock( User::class ); - $permissionManagerEdit = $this->createMock( PermissionManager::class ); - $permissionManagerEdit->expects( $this->once() ) - ->method( 'userCan' ) - ->with( - 'edit', - $userEdit, - $title - ) - ->willReturn( true ); - $userCreateAndEdit = $this->createMock( User::class ); - $userCreateAndEdit->expects( $this->once() ) - ->method( 'authorizeWrite' ) - ->with( - 'create', - $title - ) - ->willReturn( true ); - $permissionManagerCreateAndEdit = $this->createMock( PermissionManager::class ); - $permissionManagerCreateAndEdit->expects( $this->once() ) - ->method( 'userCan' ) - ->with( - 'edit', - $userCreateAndEdit, - $title - ) - ->willReturn( true ); - yield 'Edit existing page' => [ - 'performer' => $userEdit, - 'new' => false, - 'permissionManager' => $permissionManagerEdit - ]; - yield 'Create a new page' => [ - 'performer' => $userCreateAndEdit, - 'new' => true, - 'permissionManager' => $permissionManagerCreateAndEdit - ]; - } - - /** - * @dataProvider provideTestFailure - * @param User $performer - * @param bool $new - * @param PermissionManager $permissionManager - * @param int $expectedValue - */ - public function testFailure( - User $performer, bool $new, PermissionManager $permissionManager, int $expectedValue - ) { - $title = $this->createMock( Title::class ); - $constraint = new EditRightConstraint( - $performer, - $permissionManager, - $title, - $new - ); - $this->assertConstraintFailed( $constraint, $expectedValue ); - } - - public function provideTestFailure() { - $title = $this->createMock( Title::class ); - $anon = $this->createMock( User::class ); - $anon->expects( $this->once() )->method( 'isRegistered' )->willReturn( false ); - $permissionManagerAnon = $this->createMock( PermissionManager::class ); - $permissionManagerAnon->expects( $this->once() ) - ->method( 'userCan' ) - ->with( - 'edit', - $anon, - $title - ) - ->willReturn( false ); - $reg = $this->createMock( User::class ); - $reg->expects( $this->once() )->method( 'isRegistered' )->willReturn( true ); - $permissionManagerReg = $this->createMock( PermissionManager::class ); - $permissionManagerReg->expects( $this->once() ) - ->method( 'userCan' ) - ->with( - 'edit', - $reg, - $title - ) - ->willReturn( false ); - $userWithoutCreatePerm = $this->createMock( User::class ); - $userWithoutCreatePerm->expects( $this->once() ) - ->method( 'authorizeWrite' ) - ->with( - 'create', - $title - ) - ->willReturn( false ); - yield 'Anonymous user' => [ - 'performer' => $anon, - 'new' => false, - 'permissionManager' => $permissionManagerAnon, - 'expectedValue' => IEditConstraint::AS_READ_ONLY_PAGE_ANON, - ]; - yield 'Registered user' => [ - 'performer' => $reg, - 'new' => false, - 'permissionManager' => $permissionManagerReg, - 'expectedValue' => IEditConstraint::AS_READ_ONLY_PAGE_LOGGED, - ]; - yield 'User without create permission creates a page' => [ - 'performer' => $userWithoutCreatePerm, - 'new' => true, - 'permissionManager' => $this->createMock( PermissionManager::class ), - 'expectedValue' => IEditConstraint::AS_NO_CREATE_PERMISSION, - ]; - } - -} diff --git a/tests/phpunit/unit/includes/editpage/Constraint/UserRateLimitConstraintTest.php b/tests/phpunit/unit/includes/editpage/Constraint/LinkPurgeRateLimitConstraintTest.php index b832aa7ee5e5..7363601e0f72 100644 --- a/tests/phpunit/unit/includes/editpage/Constraint/UserRateLimitConstraintTest.php +++ b/tests/phpunit/unit/includes/editpage/Constraint/LinkPurgeRateLimitConstraintTest.php @@ -19,20 +19,20 @@ */ use MediaWiki\EditPage\Constraint\IEditConstraint; -use MediaWiki\EditPage\Constraint\UserRateLimitConstraint; +use MediaWiki\EditPage\Constraint\LinkPurgeRateLimitConstraint; use MediaWiki\Permissions\RateLimiter; use MediaWiki\Permissions\RateLimitSubject; use MediaWiki\User\UserIdentityValue; use PHPUnit\Framework\MockObject\MockObject; /** - * Tests the UserRateLimitConstraint + * Tests the LinkPurgeRateLimitConstraint * * @author DannyS712 * - * @covers \MediaWiki\EditPage\Constraint\UserRateLimitConstraint + * @covers \MediaWiki\EditPage\Constraint\LinkPurgeRateLimitConstraint */ -class UserRateLimitConstraintTest extends MediaWikiUnitTestCase { +class LinkPurgeRateLimitConstraintTest extends MediaWikiUnitTestCase { use EditConstraintTestTrait; /** @@ -42,19 +42,10 @@ class UserRateLimitConstraintTest extends MediaWikiUnitTestCase { */ private function getRateLimiter( $fail ) { $mock = $this->createNoOpMock( RateLimiter::class, [ 'limit' ] ); - $expectedArgs = [ - [ 'edit', 1, false ], - [ 'linkpurge', 0, false ], - [ 'editcontentmodel', 1, $fail ] - ]; - $mock->expects( $this->exactly( 3 ) ) + $mock->expects( $this->once() ) ->method( 'limit' ) - ->willReturnCallback( function ( $_, $action, $incrBy ) use ( &$expectedArgs ) { - $curExpectedArgs = array_shift( $expectedArgs ); - $this->assertSame( $curExpectedArgs[0], $action ); - $this->assertSame( $curExpectedArgs[1], $incrBy ); - return $curExpectedArgs[2]; - } ); + ->with( self::anything(), 'linkpurge', 0 ) + ->willReturn( $fail ); return $mock; } @@ -63,7 +54,7 @@ class UserRateLimitConstraintTest extends MediaWikiUnitTestCase { $subject = new RateLimitSubject( new UserIdentityValue( 1, 'test' ), null, [] ); - $constraint = new UserRateLimitConstraint( $limiter, $subject, 'OldContentModel', 'NewContentModel' ); + $constraint = new LinkPurgeRateLimitConstraint( $limiter, $subject ); $this->assertConstraintPassed( $constraint ); } @@ -72,7 +63,7 @@ class UserRateLimitConstraintTest extends MediaWikiUnitTestCase { $subject = new RateLimitSubject( new UserIdentityValue( 1, 'test' ), null, [] ); - $constraint = new UserRateLimitConstraint( $limiter, $subject, 'OldContentModel', 'NewContentModel' ); + $constraint = new LinkPurgeRateLimitConstraint( $limiter, $subject ); $this->assertConstraintFailed( $constraint, IEditConstraint::AS_RATE_LIMITED ); } diff --git a/tests/phpunit/unit/includes/editpage/Constraint/UserBlockConstraintTest.php b/tests/phpunit/unit/includes/editpage/Constraint/UserBlockConstraintTest.php deleted file mode 100644 index e231e4a50c66..000000000000 --- a/tests/phpunit/unit/includes/editpage/Constraint/UserBlockConstraintTest.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php -/** - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * http://www.gnu.org/copyleft/gpl.html - * - * @file - */ - -use MediaWiki\EditPage\Constraint\IEditConstraint; -use MediaWiki\EditPage\Constraint\UserBlockConstraint; -use MediaWiki\Permissions\PermissionManager; -use MediaWiki\Title\Title; -use MediaWiki\User\User; - -/** - * Tests the UserBlockConstraint - * - * @author DannyS712 - * - * @covers \MediaWiki\EditPage\Constraint\UserBlockConstraint - */ -class UserBlockConstraintTest extends MediaWikiUnitTestCase { - use EditConstraintTestTrait; - - public function testPass() { - $title = $this->createMock( Title::class ); - $user = $this->createMock( User::class ); - $permissionManager = $this->createMock( PermissionManager::class ); - $permissionManager->expects( $this->once() ) - ->method( 'isBlockedFrom' ) - ->with( - $user, - $title - ) - ->willReturn( false ); - - $constraint = new UserBlockConstraint( $permissionManager, $title, $user ); - $this->assertConstraintPassed( $constraint ); - } - - public function testFailure() { - $title = $this->createMock( Title::class ); - $user = $this->createMock( User::class ); - $permissionManager = $this->createMock( PermissionManager::class ); - $permissionManager->expects( $this->once() ) - ->method( 'isBlockedFrom' ) - ->with( - $user, - $title - ) - ->willReturn( true ); - - $constraint = new UserBlockConstraint( $permissionManager, $title, $user ); - $this->assertConstraintFailed( - $constraint, - IEditConstraint::AS_BLOCKED_PAGE_FOR_USER - ); - } - -} |