aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--autoload.php5
-rw-r--r--includes/ServiceWiring.php5
-rw-r--r--includes/editpage/Constraint/AuthorizationConstraint.php88
-rw-r--r--includes/editpage/Constraint/ContentModelChangeConstraint.php35
-rw-r--r--includes/editpage/Constraint/EditConstraintFactory.php63
-rw-r--r--includes/editpage/Constraint/EditRightConstraint.php105
-rw-r--r--includes/editpage/Constraint/LinkPurgeRateLimitConstraint.php (renamed from includes/editpage/Constraint/UserRateLimitConstraint.php)23
-rw-r--r--includes/editpage/Constraint/UserBlockConstraint.php79
-rw-r--r--includes/editpage/EditPage.php44
-rw-r--r--tests/phpunit/includes/editpage/EditPageConstraintsTest.php59
-rw-r--r--tests/phpunit/mocks/permissions/MockAuthorityTrait.php1
-rw-r--r--tests/phpunit/unit/includes/editpage/Constraint/AuthorizationConstraintTest.php111
-rw-r--r--tests/phpunit/unit/includes/editpage/Constraint/EditConstraintFactoryTest.php7
-rw-r--r--tests/phpunit/unit/includes/editpage/Constraint/EditRightConstraintTest.php170
-rw-r--r--tests/phpunit/unit/includes/editpage/Constraint/LinkPurgeRateLimitConstraintTest.php (renamed from tests/phpunit/unit/includes/editpage/Constraint/UserRateLimitConstraintTest.php)27
-rw-r--r--tests/phpunit/unit/includes/editpage/Constraint/UserBlockConstraintTest.php72
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
- );
- }
-
-}