Merge pull request #753 from kmycode/kbtopic-fix-emoji-reaction-rack-attack-for-lts

Release: 5.20 LTS
This commit is contained in:
KMY(雪あすか) 2024-06-03 07:44:23 +09:00 committed by GitHub
commit e925fd6802
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 49 additions and 3 deletions

View file

@ -141,8 +141,10 @@ class Rack::Attack
req.session[:attempt_user_id] || req.params.dig('user', 'email').presence if req.post? && req.path_matches?('/auth/sign_in') req.session[:attempt_user_id] || req.params.dig('user', 'email').presence if req.post? && req.path_matches?('/auth/sign_in')
end end
API_CREATE_EMOJI_REACTION_REGEX = %r{\A/api/v1/statuses/\d+/emoji_reactions}
throttle('throttle_password_change/account', limit: 10, period: 10.minutes) do |req| throttle('throttle_password_change/account', limit: 10, period: 10.minutes) do |req|
req.warden_user_id if req.put? || (req.patch? && req.path_matches?('/auth')) req.warden_user_id if (req.put? && !req.path.match?(API_CREATE_EMOJI_REACTION_REGEX)) || (req.patch? && req.path_matches?('/auth'))
end end
self.throttled_responder = lambda do |request| self.throttled_responder = lambda do |request|

View file

@ -9,7 +9,7 @@ module Mastodon
end end
def kmyblue_minor def kmyblue_minor
19 20
end end
def kmyblue_flag def kmyblue_flag

View file

@ -7,7 +7,7 @@ describe Rack::Attack, type: :request do
Rails.application Rails.application
end end
shared_examples 'throttled endpoint' do shared_context 'with throttled endpoint base' do
before do before do
# Rack::Attack periods are not rolling, so avoid flaky tests by setting the time in a way # Rack::Attack periods are not rolling, so avoid flaky tests by setting the time in a way
# to avoid crossing period boundaries. # to avoid crossing period boundaries.
@ -18,6 +18,10 @@ describe Rack::Attack, type: :request do
travel_to Time.zone.at((Time.now.to_i / period.seconds).to_i * period.seconds) travel_to Time.zone.at((Time.now.to_i / period.seconds).to_i * period.seconds)
end end
end
shared_examples 'throttled endpoint' do
include_examples 'with throttled endpoint base'
context 'when the number of requests is lower than the limit' do context 'when the number of requests is lower than the limit' do
it 'does not change the request status' do it 'does not change the request status' do
@ -43,6 +47,28 @@ describe Rack::Attack, type: :request do
end end
end end
shared_examples 'does not throttle endpoint' do
include_examples 'with throttled endpoint base'
context 'when the number of requests is lower than the limit' do
it 'does not change the request status' do
limit.times do
request.call
expect(response).to_not have_http_status(429)
end
end
end
context 'when the number of requests is higher than the limit' do
it 'returns http too many requests after limit and returns to normal status after period' do
(limit * 2).times do |_i|
request.call
expect(response).to_not have_http_status(429)
end
end
end
end
let(:remote_ip) { '1.2.3.5' } let(:remote_ip) { '1.2.3.5' }
describe 'throttle excessive sign-up requests by IP address' do describe 'throttle excessive sign-up requests by IP address' do
@ -145,4 +171,22 @@ describe Rack::Attack, type: :request do
it_behaves_like 'throttled endpoint' it_behaves_like 'throttled endpoint'
end end
describe 'throttle excessive emoji reaction requests by account' do
let(:user) { Fabricate(:user, email: 'user@host.example') }
let(:limit) { 10 }
let(:period) { 10.minutes }
let(:request) { -> { put path, headers: { 'REMOTE_ADDR' => remote_ip } } }
let(:status) { Fabricate(:status) }
let(:emoji) { Fabricate(:custom_emoji) }
let(:path) { "/api/v1/statuses/#{status.id}/emoji_reactions/#{emoji.shortcode}" }
before do
sign_in user, scope: :user
get '/'
end
it_behaves_like 'does not throttle endpoint'
end
end end