Cenarium has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/312017

Change subject: Enable Throttler to relax limits for users in some groups
......................................................................

Enable Throttler to relax limits for users in some groups

This adds a config variable $wgThrottleGroupMultipliers that allows to
relax limits for users in some groups by multiplying the limits by some
specified number. If the multiplier is zero, the throttle is bypassed.
This allows to make some usergroups imune to the account creation limit
without having to possess noratelimit.

Bug: T146287
Change-Id: Ifb8425aa753731cb2dd441c8092ce39b9028b563
---
M includes/DefaultSettings.php
M includes/auth/ThrottlePreAuthenticationProvider.php
M includes/auth/Throttler.php
M tests/phpunit/includes/auth/ThrottlerTest.php
4 files changed, 87 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/17/312017/1

diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index f0e9e83..6caab69 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -5600,6 +5600,23 @@
 $wgRateLimitsExcludedIPs = [];
 
 /**
+ * Array of strings mapped to arrays of strings mapped to nonnegative integers
+ *
+ * @par Example:
+ * You could have a group of account creators with 10 times the normal limit.
+ * @code
+ *     $wgThrottleGroupMultipliers = [
+ *         'createaccount' => [
+ *              'accountcreator' => 10
+ *         ]
+ *     ]
+ * @endcode
+ */
+$wgThrottleGroupMultipliers = [
+       'createaccount' => [],
+];
+
+/**
  * Log IP addresses in the recentchanges table; can be accessed only by
  * extensions (e.g. CheckUser) or a DB admin
  * Used for retroactive autoblocks
diff --git a/includes/auth/ThrottlePreAuthenticationProvider.php 
b/includes/auth/ThrottlePreAuthenticationProvider.php
index e2123ef..35a759d 100644
--- a/includes/auth/ThrottlePreAuthenticationProvider.php
+++ b/includes/auth/ThrottlePreAuthenticationProvider.php
@@ -76,10 +76,12 @@
                ];
 
                if ( !empty( $this->throttleSettings['accountCreationThrottle'] 
) ) {
+                       $allMultipliers = $this->config->get( 
'ThrottleGroupMultipliers' );
                        $this->accountCreationThrottle = new Throttler(
                                
$this->throttleSettings['accountCreationThrottle'], [
                                        'type' => 'acctcreate',
                                        'cache' => $this->cache,
+                                       'multipliers' => 
$allMultipliers['createaccount']
                                ]
                        );
                }
@@ -105,6 +107,7 @@
                        return \StatusValue::newGood();
                }
 
+               $this->accountCreationThrottle->setGroups( 
$creator->getGroups() );
                $result = $this->accountCreationThrottle->increase( null, $ip, 
__METHOD__ );
                if ( $result ) {
                        return \StatusValue::newFatal( 
'acct_creation_throttle_hit', $result['count'] );
diff --git a/includes/auth/Throttler.php b/includes/auth/Throttler.php
index f47c606..4d32a4a 100644
--- a/includes/auth/Throttler.php
+++ b/includes/auth/Throttler.php
@@ -49,6 +49,10 @@
        protected $logger;
        /** @var int|float */
        protected $warningLimit;
+       /** @var array */
+       protected $groupMultipliers;
+       /** @var array|null */
+       protected $groups = null;
 
        /**
         * @param array $conditions An array of arrays describing throttling 
conditions.
@@ -61,7 +65,7 @@
         */
        public function __construct( array $conditions = null, array $params = 
[] ) {
                $invalidParams = array_diff_key( $params,
-                       array_fill_keys( [ 'type', 'cache', 'warningLimit' ], 
true ) );
+                       array_fill_keys( [ 'type', 'cache', 'warningLimit', 
'multipliers' ], true ) );
                if ( $invalidParams ) {
                        throw new \InvalidArgumentException( 'unrecognized 
parameters: '
                                . implode( ', ', array_keys( $invalidParams ) ) 
);
@@ -84,6 +88,7 @@
                }
 
                $this->type = $params['type'];
+               $this->groupMultipliers = isset( $params['multipliers'] ) ? 
$params['multipliers'] : [];
                $this->conditions = static::normalizeThrottleConditions( 
$conditions );
                $this->cache = $params['cache'];
                $this->warningLimit = $params['warningLimit'];
@@ -93,6 +98,42 @@
 
        public function setLogger( LoggerInterface $logger ) {
                $this->logger = $logger;
+       }
+
+       /**
+        * Provide user groups of user being throttled
+        *
+        * @param array $groups
+        * @since 1.28
+        */
+       public function setGroups( array $groups ) {
+               $this->groups = $groups;
+       }
+
+       /**
+        * Return the largest multiplier among the groups the user is in,
+        * or 0 if it is one of the multipliers
+        *
+        * @return int
+        * @since 1.28
+        */
+       public function getMultiplier() {
+               if ( $this->groups === null || !$this->groupMultipliers ) {
+                       return 1;
+               }
+               $effectiveGroupMultipliers = [];
+               foreach ( $this->groups as $group ) {
+                       if ( isset( $this->groupMultipliers[$group] ) ) {
+                               $effectiveGroupMultipliers[] = 
$this->groupMultipliers[$group];
+                       }
+               }
+               if ( !$effectiveGroupMultipliers ) {
+                       return 1;
+               }
+               if ( in_array( 0, $effectiveGroupMultipliers ) ) {
+                       return 0;
+               }
+               return max( $effectiveGroupMultipliers );
        }
 
        /**
@@ -117,10 +158,11 @@
                $userKey = $username ? md5( $username ) : null;
                foreach ( $this->conditions as $index => $throttleCondition ) {
                        $ipKey = isset( $throttleCondition['allIPs'] ) ? null : 
$ip;
-                       $count = $throttleCondition['count'];
+                       $count = $this->getMultiplier() * 
$throttleCondition['count'];
                        $expiry = $throttleCondition['seconds'];
 
                        // a limit of 0 is used as a disable flag in some 
throttling configuration settings
+                       // or if the multiplier is 0 which should make the user 
exempt
                        // throttling the whole world is probably a bad idea
                        if ( !$count || $userKey === null && $ipKey === null ) {
                                continue;
diff --git a/tests/phpunit/includes/auth/ThrottlerTest.php 
b/tests/phpunit/includes/auth/ThrottlerTest.php
index 5806003..4b7cd88 100644
--- a/tests/phpunit/includes/auth/ThrottlerTest.php
+++ b/tests/phpunit/includes/auth/ThrottlerTest.php
@@ -234,4 +234,27 @@
                $result = $throttler->increase( 'OtherUser', '1.2.3.4' );
                $this->assertSame( [ 'throttleIndex' => 0, 'count' => 1, 'wait' 
=> 10 ], $result );
        }
+
+       /**
+        * @dataProvider provideGetMultiplier
+        */
+       public function testGetMultiplier( $multipliers, $expected ) {
+               $cache = new \HashBagOStuff();
+               $throttler = new Throttler(
+                       [ [ 'count' => 1, 'seconds' => 10 ] ],
+                       [ 'cache' => $cache, 'multipliers' => $multipliers ]
+                       );
+               $throttler->setGroups( [ 'group1', 'group2' ] );
+               $this->assertSame( $throttler->getMultiplier(), $expected );
+               
+       }
+
+       public function provideGetMultiplier() {
+               return [
+                       [ [ 'group1' => 0, 'group2' => 3 ], 0 ],
+                       [ [ 'group1' => 5, 'group2' => 3, 'group3' => 0 ], 5 ],
+                       [ [], 1],
+                       [ [ 'group3' => 0 ], 1 ],
+               ];
+       }
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/312017
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifb8425aa753731cb2dd441c8092ce39b9028b563
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Cenarium <cenarium.sy...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to