diff options
Diffstat (limited to 'includes')
-rw-r--r-- | includes/ServiceWiring.php | 5 | ||||
-rw-r--r-- | includes/editpage/Constraint/EditConstraintFactory.php | 30 | ||||
-rw-r--r-- | includes/editpage/Constraint/UserRateLimitConstraint.php | 46 | ||||
-rw-r--r-- | includes/editpage/EditPage.php | 12 |
4 files changed, 62 insertions, 31 deletions
diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 1825c28513c4..e2717561b990 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -2546,7 +2546,10 @@ return [ $services->getReadOnlyMode(), // SpamRegexConstraint - $services->getSpamChecker() + $services->getSpamChecker(), + + // UserRateLimitConstraint + $services->getRateLimiter() ); }, diff --git a/includes/editpage/Constraint/EditConstraintFactory.php b/includes/editpage/Constraint/EditConstraintFactory.php index 665b0b6ad5ed..023155eed5ff 100644 --- a/includes/editpage/Constraint/EditConstraintFactory.php +++ b/includes/editpage/Constraint/EditConstraintFactory.php @@ -30,6 +30,8 @@ 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; use MediaWiki\User\User; use MediaWiki\User\UserIdentity; @@ -67,6 +69,7 @@ class EditConstraintFactory { /** @var SpamChecker */ private $spamRegexChecker; + private RateLimiter $rateLimiter; /** * Some constraints have dependencies that need to be injected, @@ -86,6 +89,7 @@ class EditConstraintFactory { * @param HookContainer $hookContainer * @param ReadOnlyMode $readOnlyMode * @param SpamChecker $spamRegexChecker + * @param RateLimiter $rateLimiter */ public function __construct( ServiceOptions $options, @@ -93,7 +97,8 @@ class EditConstraintFactory { PermissionManager $permissionManager, HookContainer $hookContainer, ReadOnlyMode $readOnlyMode, - SpamChecker $spamRegexChecker + SpamChecker $spamRegexChecker, + RateLimiter $rateLimiter ) { $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS ); @@ -112,6 +117,9 @@ class EditConstraintFactory { // SpamRegexConstraint $this->spamRegexChecker = $spamRegexChecker; + + // UserRateLimitConstraint + $this->rateLimiter = $rateLimiter; } /** @@ -168,6 +176,26 @@ class EditConstraintFactory { } /** + * @param RateLimitSubject $subject + * @param string $oldModel + * @param string $newModel + * + * @return UserRateLimitConstraint + */ + public function newUserRateLimitConstraint( + RateLimitSubject $subject, + string $oldModel, + string $newModel + ): UserRateLimitConstraint { + return new UserRateLimitConstraint( + $this->rateLimiter, + $subject, + $oldModel, + $newModel + ); + } + + /** * @param string $input * @param UserIdentity $user * @param Title $title diff --git a/includes/editpage/Constraint/UserRateLimitConstraint.php b/includes/editpage/Constraint/UserRateLimitConstraint.php index db064f067920..d21409a95a84 100644 --- a/includes/editpage/Constraint/UserRateLimitConstraint.php +++ b/includes/editpage/Constraint/UserRateLimitConstraint.php @@ -20,8 +20,8 @@ namespace MediaWiki\EditPage\Constraint; -use MediaWiki\Title\Title; -use MediaWiki\User\User; +use MediaWiki\Permissions\RateLimiter; +use MediaWiki\Permissions\RateLimitSubject; use StatusValue; /** @@ -33,43 +33,39 @@ use StatusValue; */ class UserRateLimitConstraint implements IEditConstraint { - /** @var User */ - private $user; + private RateLimitSubject $subject; + private string $oldContentModel; + private string $newContentModel; + private RateLimiter $limiter; - /** @var Title */ - private $title; + private string $result; - /** @var string */ - private $newContentModel; - - /** @var string|null */ - private $result; - - /** - * @param User $user - * @param Title $title - * @param string $newContentModel - */ public function __construct( - User $user, - Title $title, + RateLimiter $limiter, + RateLimitSubject $subject, + string $oldContentModel, string $newContentModel ) { - $this->user = $user; - $this->title = $title; + $this->limiter = $limiter; + $this->subject = $subject; + $this->oldContentModel = $oldContentModel; $this->newContentModel = $newContentModel; } + private function limit( string $action, int $inc = 1 ) { + return $this->limiter->limit( $this->subject, $action, $inc ); + } + public function checkConstraint(): string { // Need to check for rate limits on `editcontentmodel` if it is changing - $contentModelChange = ( $this->newContentModel !== $this->title->getContentModel() ); + $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->user->pingLimiter() - || $this->user->pingLimiter( 'linkpurge', 0 ) // only counted after the fact - || ( $contentModelChange && $this->user->pingLimiter( 'editcontentmodel' ) ) + if ( $this->limit( 'edit' ) + || $this->limit( 'linkpurge', 0 ) // only counted after the fact + || ( $contentModelChange && $this->limit( 'editcontentmodel' ) ) ) { $this->result = self::CONSTRAINT_FAILED; } else { diff --git a/includes/editpage/EditPage.php b/includes/editpage/EditPage.php index d366898dbb34..f5c951e5ca71 100644 --- a/includes/editpage/EditPage.php +++ b/includes/editpage/EditPage.php @@ -53,7 +53,6 @@ use MediaWiki\EditPage\Constraint\SelfRedirectConstraint; use MediaWiki\EditPage\Constraint\SpamRegexConstraint; use MediaWiki\EditPage\Constraint\UnicodeConstraint; use MediaWiki\EditPage\Constraint\UserBlockConstraint; -use MediaWiki\EditPage\Constraint\UserRateLimitConstraint; use MediaWiki\HookContainer\HookRunner; use MediaWiki\HookContainer\ProtectedHookAccessorTrait; use MediaWiki\Html\Html; @@ -2119,7 +2118,11 @@ class EditPage implements IEditObject { $constraintFactory->newReadOnlyConstraint() ); $constraintRunner->addConstraint( - new UserRateLimitConstraint( $requestUser, $this->mTitle, $this->contentModel ) + $constraintFactory->newUserRateLimitConstraint( + $requestUser->toRateLimitSubject(), + $this->mTitle->getContentModel(), + $this->contentModel + ) ); $constraintRunner->addConstraint( // Same constraint is used to check size before and after merging the @@ -2503,8 +2506,9 @@ class EditPage implements IEditObject { $result['nullEdit'] = !$doEditStatus->wasRevisionCreated(); if ( $result['nullEdit'] ) { - // We don't know if it was a null edit until now, so increment here - $requestUser->pingLimiter( 'linkpurge' ); + // We didn't know if it was a null edit until now, so bump the rate limit now + $limitSubject = $requestUser->toRateLimitSubject(); + MediaWikiServices::getInstance()->getRateLimiter()->limit( $limitSubject, 'linkpurge' ); } $result['redirect'] = $content->isRedirect(); |