rate limits: adjust limits for various actions.

* Tie rate limits to both the user's ID and their IP address.

* Make each endpoint have separate rate limits. This means that, for
  example, your post edit rate limit is separate from your post vote
  rate limit. Before all write actions had a shared rate limit.

* Make all write endpoints have rate limits. Before some endpoints, such
  as voting, favoriting, commenting, or forum posting, weren't subject
  to rate limits.

* Add stricter rate limits for some endpoints:

** 1 per 5 minutes for creating new accounts.
** 1 per minute for login attempts, changing your email address, or
   for creating mod reports.
** 1 per minute for sending dmails, creating comments, creating forum
   posts, or creating forum topics.
** 1 per second for voting, favoriting, or disapproving posts.
** These rate limits all have burst factors high enough that they
   shouldn't affect normal, non-automated users.

* Raise the default write rate limit for Gold users from 2 per second to
  4 per second, for all other actions not listed above.

* Raise the default burst factor to 200 for all other actions not listed
  above. Before it was 10 for Members, 30 for Gold, and 60 for Platinum.
This commit is contained in:
evazion
2021-03-05 04:50:37 -06:00
parent 4492610dfe
commit 413cd34c45
15 changed files with 55 additions and 49 deletions

View File

@@ -8,7 +8,7 @@ class ApplicationController < ActionController::Base
before_action :reset_current_user
before_action :set_current_user
before_action :normalize_search
before_action :api_check
before_action :check_rate_limit
before_action :ip_ban_check
before_action :set_variant
before_action :add_headers
@@ -69,18 +69,12 @@ class ApplicationController < ActionController::Base
response.headers["X-Git-Hash"] = Rails.application.config.x.git_hash
end
def api_check
return if CurrentUser.is_anonymous? || request.get? || request.head?
rate_limiter = RateLimiter.new(
"write",
[CurrentUser.user.cache_key],
cost: 1,
rate: CurrentUser.user.api_regen_multiplier,
burst: CurrentUser.user.api_burst_limit
)
def check_rate_limit
return if request.get? || request.head?
rate_limiter = RateLimiter.for_action(controller_name, action_name, CurrentUser.user, CurrentUser.ip_addr)
headers["X-Rate-Limit"] = rate_limiter.to_json
rate_limiter.limit!
end

View File

@@ -1,5 +1,4 @@
class CommentVotesController < ApplicationController
skip_before_action :api_check
respond_to :js, :json, :xml, :html
def index

View File

@@ -1,7 +1,6 @@
class CommentsController < ApplicationController
respond_to :html, :xml, :json, :atom
respond_to :js, only: [:new, :destroy, :undelete]
skip_before_action :api_check
def index
params[:group_by] ||= "comment" if params[:search].present?

View File

@@ -1,6 +1,5 @@
class FavoritesController < ApplicationController
respond_to :html, :xml, :json, :js
skip_before_action :api_check
rescue_with Favorite::Error, status: 422
def index

View File

@@ -1,6 +1,5 @@
class ForumPostsController < ApplicationController
respond_to :html, :xml, :json, :js
skip_before_action :api_check
def new
@forum_post = authorize ForumPost.new_reply(params)

View File

@@ -2,7 +2,6 @@ class ForumTopicsController < ApplicationController
respond_to :html, :xml, :json
respond_to :atom, only: [:index, :show]
before_action :normalize_search, :only => :index
skip_before_action :api_check
def new
@forum_topic = authorize ForumTopic.new

View File

@@ -1,7 +1,6 @@
module Moderator
module Post
class PostsController < ApplicationController
skip_before_action :api_check
respond_to :html, :json, :xml, :js
def confirm_move_favorites

View File

@@ -1,5 +1,4 @@
class PostDisapprovalsController < ApplicationController
skip_before_action :api_check
respond_to :js, :html, :json, :xml
def create

View File

@@ -1,5 +1,4 @@
class PostVotesController < ApplicationController
skip_before_action :api_check
respond_to :js, :json, :xml, :html
def index

View File

@@ -1,6 +1,5 @@
class UsersController < ApplicationController
respond_to :html, :xml, :json
skip_before_action :api_check
def new
@user = authorize User.new