92 $this->logger = LoggerFactory::getInstance(
'ratelimit' );
95 $this->options = $options;
96 $this->wrstatsFactory = $wrstatsFactory;
97 $this->centralIdLookup = $centralIdLookup;
98 $this->userFactory = $userFactory;
99 $this->userGroupManager = $userGroupManager;
100 $this->hookRunner =
new HookRunner( $hookContainer );
142 $ip = $subject->
getIP();
146 $legacyUser = $this->userFactory->newFromUserIdentity( $user );
147 if ( !$this->hookRunner->onPingLimiter( $legacyUser, $action, $result, $incrBy ) ) {
151 if ( !isset( $this->rateLimits[$action] ) ) {
156 if ( $this->canBypass( $action ) && $this->
isExempt( $subject ) ) {
160 $conds = $this->getConditions( $action );
161 $limiter = $this->wrstatsFactory->createRateLimiter( $conds, [
'limiter', $action ] );
162 $limitBatch = $limiter->createBatch( $incrBy );
163 $this->logger->debug( __METHOD__ .
": limiting $action rate for {$user->getName()}" );
165 $id = $user->getId();
166 $isNewbie = $subject->
is( RateLimitSubject::NEWBIE );
170 if ( isset( $conds[
'anon'] ) ) {
171 $limitBatch->localOp(
'anon', [] );
175 if ( isset( $conds[
'user-global'] ) ) {
177 $centralId = $this->centralIdLookup
183 $realm = $this->centralIdLookup->getProviderId();
184 $limitBatch->globalOp(
'user-global', [ $realm, $centralId ] );
187 $limitBatch->localOp(
'user-global', [
'local', $id ] );
192 if ( $isNewbie && $ip ) {
194 if ( isset( $conds[
'ip'] ) ) {
195 $limitBatch->globalOp(
'ip', $ip );
198 if ( isset( $conds[
'subnet'] ) ) {
199 $subnet = IPUtils::getSubnet( $ip );
200 if ( $subnet !==
false ) {
201 $limitBatch->globalOp(
'subnet', $subnet );
207 $userEntityType =
false;
208 if ( $id !== 0 && isset( $conds[
'user'] ) ) {
210 $userEntityType =
'user';
213 if ( $id !== 0 && $isNewbie && isset( $conds[
'newbie'] ) ) {
214 $userEntityType =
'newbie';
218 $userGroups = $this->userGroupManager->getUserGroups( $user );
219 foreach ( $userGroups as $group ) {
220 if ( isset( $conds[$group] ) ) {
221 if ( $userEntityType ===
false
222 || $conds[$group]->perSecond() > $conds[$userEntityType]->perSecond()
224 $userEntityType = $group;
231 if ( $userEntityType !==
false ) {
232 $limitBatch->localOp( $userEntityType, $id );
236 if ( isset( $conds[
'ip-all'] ) && $ip ) {
238 if ( $isNewbie || $userEntityType ===
false
239 || $conds[
'ip-all']->perSecond() > $conds[$userEntityType]->perSecond()
241 $limitBatch->globalOp(
'ip-all', $ip );
246 if ( isset( $conds[
'subnet-all'] ) && $ip ) {
247 $subnet = IPUtils::getSubnet( $ip );
248 if ( $subnet !==
false ) {
250 if ( $isNewbie || $userEntityType ===
false
251 || $conds[
'ip-all']->perSecond() > $conds[$userEntityType]->perSecond()
253 $limitBatch->globalOp(
'subnet-all', $subnet );
259 'name' => $user->getName(),
263 $batchResult = $limitBatch->tryIncr();
264 foreach ( $batchResult->getFailedResults() as
$type => $result ) {
266 'User::pingLimiter: User tripped rate limit',
269 'limit' => $result->condition->limit,
270 'period' => $result->condition->window,
271 'count' => $result->prevTotal,
277 return !$batchResult->isAllowed();