Browse Source

Throttle admin password reset (#429)

pull/431/head
kosiakkatrina 3 years ago committed by GitHub
parent
commit
4d44729f50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      config/initializers/rack_attack.rb
  2. 47
      spec/requests/rack_attack_spec.rb

6
config/initializers/rack_attack.rb

@ -14,6 +14,12 @@ Rack::Attack.throttle("password reset requests", limit: 5, period: 60.seconds) d
end end
end end
Rack::Attack.throttle("admin password reset requests", limit: 5, period: 60.seconds) do |request|
if request.params["admin_user"].present? && request.path == "/admin/password" && request.post?
request.params["admin_user"]["email"].to_s.downcase.gsub(/\s+/, "")
end
end
Rack::Attack.throttled_responder = lambda do |_env| Rack::Attack.throttled_responder = lambda do |_env|
headers = { headers = {
"Location" => "/429", "Location" => "/429",

47
spec/requests/rack_attack_spec.rb

@ -12,8 +12,11 @@ describe "Rack::Attack" do
let(:devise_notify_mailer) { DeviseNotifyMailer.new } let(:devise_notify_mailer) { DeviseNotifyMailer.new }
let(:params) { { user: { email: } } } let(:params) { { user: { email: } } }
let(:admin_params) { { admin_user: { email: admin_email } } }
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:admin_user) { FactoryBot.create(:admin_user) }
let(:email) { user.email } let(:email) { user.email }
let(:admin_email) { admin_user.email }
before do before do
Rack::Attack.enabled = true Rack::Attack.enabled = true
@ -29,7 +32,7 @@ describe "Rack::Attack" do
context "when a password reset is requested" do context "when a password reset is requested" do
context "when the number of requests is under the throttle limit" do context "when the number of requests is under the throttle limit" do
it "does not throttle" do it "does not throttle for a regular user" do
under_limit.times do under_limit.times do
post "/account/password", params: params post "/account/password", params: params
follow_redirect! follow_redirect!
@ -37,13 +40,42 @@ describe "Rack::Attack" do
last_response = response last_response = response
expect(last_response.status).to eq(200) expect(last_response.status).to eq(200)
end end
it "does not throttle for an admin user" do
under_limit.times do
post "/admin/password", params: admin_params
follow_redirect!
end
last_response = response
expect(last_response.status).to eq(200)
end
end end
context "when the number of requests is at the throttle limit" do context "when the number of requests is at the throttle limit" do
it "does not throttle" do it "does not throttle for a regular user" do
limit.times do
post "/account/password", params: params
follow_redirect!
end
last_response = response
expect(last_response.status).to eq(200)
end
it "does not throttle for an admin user" do
limit.times do
post "/admin/password", params: admin_params
follow_redirect!
end
last_response = response
expect(last_response.status).to eq(200)
end
it "does not throttle if both endpoints are hit" do
limit.times do limit.times do
post "/account/password", params: params post "/account/password", params: params
follow_redirect! follow_redirect!
post "/admin/password", params: admin_params
follow_redirect!
end end
last_response = response last_response = response
expect(last_response.status).to eq(200) expect(last_response.status).to eq(200)
@ -51,7 +83,7 @@ describe "Rack::Attack" do
end end
context "when the number of requests is over the throttle limit" do context "when the number of requests is over the throttle limit" do
it "throttles" do it "throttles for a regular user" do
over_limit.times do over_limit.times do
post "/account/password", params: params post "/account/password", params: params
follow_redirect! follow_redirect!
@ -59,6 +91,15 @@ describe "Rack::Attack" do
last_response = response last_response = response
expect(last_response.status).to eq(429) expect(last_response.status).to eq(429)
end end
it "throttles for an admin user" do
over_limit.times do
post "/admin/password", params: admin_params
follow_redirect!
end
last_response = response
expect(last_response.status).to eq(429)
end
end end
end end
end end

Loading…
Cancel
Save