[deploy] Limit Reactions Created in a 30 second Timeframe (#7683)

This commit is contained in:
Molly Struve 2020-05-06 08:30:05 -05:00 committed by GitHub
parent bac4a3ca4b
commit 3ede8912b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 2 deletions

View file

@ -1,5 +1,6 @@
class ReactionsController < ApplicationController
before_action :set_cache_control_headers, only: [:index], unless: -> { current_user }
before_action :check_limit, only: [:create]
after_action :verify_authorized
def index
@ -73,6 +74,7 @@ class ReactionsController < ApplicationController
reaction = build_reaction(category)
if reaction.save
rate_limiter.track_limit_by_action(:reaction_creation)
Moderator::SinkArticles.call(reaction.reactable_id) if reaction.vomit_on_user?
Notification.send_reaction_notification(reaction, reaction.target_user)
@ -130,4 +132,8 @@ class ReactionsController < ApplicationController
context: "readinglist_reaction",
rating: current_user.experience_level)
end
def check_limit
rate_limit!(:reaction_creation)
end
end

View file

@ -77,6 +77,7 @@ class SiteConfig < RailsSettings::Base
field :rate_limit_listing_creation, type: :integer, default: 1
field :rate_limit_published_article_creation, type: :integer, default: 9
field :rate_limit_organization_creation, type: :integer, default: 1
field :rate_limit_reaction_creation, type: :integer, default: 10
field :rate_limit_image_upload, type: :integer, default: 9
field :rate_limit_email_recipient, type: :integer, default: 5
field :rate_limit_article_update, type: :integer, default: 150

View file

@ -7,7 +7,8 @@ class RateLimitChecker
image_upload: { retry_after: 30 },
listing_creation: { retry_after: 60 },
published_article_creation: { retry_after: 30 },
organization_creation: { retry_after: 300 }
organization_creation: { retry_after: 300 },
reaction_creation: { retry_after: 30 }
}.with_indifferent_access.freeze
CONFIGURABLE_RATES = {
@ -17,7 +18,8 @@ class RateLimitChecker
rate_limit_published_article_creation: { min: 0, placeholder: 9, description: "The number of articles a user can create within 30 seconds" },
rate_limit_image_upload: { min: 0, placeholder: 9, description: "The number of images a user can upload within 30 seconds" },
rate_limit_email_recipient: { min: 0, placeholder: 5, description: "The number of emails we send to a user within 2 minutes" },
rate_limit_organization_creation: { min: 1, placeholder: 1, description: "The number of organizations a user can create within a 5 minute period" }
rate_limit_organization_creation: { min: 1, placeholder: 1, description: "The number of organizations a user can create within a 5 minute period" },
rate_limit_reaction_creation: { min: 1, placeholder: 10, description: "The number of times a user can react in a 30 second period" }
}.freeze
def initialize(user = nil)

View file

@ -148,6 +148,29 @@ RSpec.describe "Reactions", type: :request do
}
end
context "when rate limiting" do
let(:rate_limiter) { RateLimitChecker.new(user) }
before do
allow(RateLimitChecker).to receive(:new).and_return(rate_limiter)
sign_in user
end
it "increments rate limit for reaction_creation" do
allow(rate_limiter).to receive(:track_limit_by_action)
post "/reactions", params: article_params
expect(rate_limiter).to have_received(:track_limit_by_action).with(:reaction_creation)
end
it "returns a 429 status when rate limit is reached" do
allow(rate_limiter).to receive(:limit_by_action).and_return(true)
post "/reactions", params: article_params
expect(response.status).to eq(429)
end
end
context "when reacting to an article" do
before do
sign_in user