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