Browse Source
* Add a failing test (for a wrong reason) * Is that correct? * Add rack attack config for reset password * Add support to read redis configuration * Add PaaS configuration for redis * Add too many requests page * Redirect to the too many requests error page * update manifest Co-authored-by: Stéphane Meny <smeny@users.noreply.github.com>pull/359/head
kosiakkatrina
3 years ago
committed by
GitHub
10 changed files with 181 additions and 4 deletions
@ -0,0 +1,8 @@
|
||||
<% content_for :title, "Sorry, you have sent too many requests to our service" %> |
||||
|
||||
<div class="govuk-grid-row"> |
||||
<div class="govuk-grid-column-two-thirds"> |
||||
<h1 class="govuk-heading-l"><%= content_for(:title) %></h1> |
||||
<p class="govuk-body">Try again in a minute.</p> |
||||
</div> |
||||
</div> |
@ -0,0 +1,20 @@
|
||||
if Rails.env.development? || Rails.env.test? |
||||
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new |
||||
Rack::Attack.enabled = false |
||||
else |
||||
redis_url = PaasConfigurationService.new.redis_uris[:"dluhc-core-#{Redis.env}-redis-rate-limit"] |
||||
Rack::Attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(url: redis_url) |
||||
end |
||||
|
||||
Rack::Attack.throttle("password reset requests", limit: 5, period: 60.seconds) do |request| |
||||
if request.params["user"].present? && request.path == "/users/password" && request.post? |
||||
request.params["user"]["email"].to_s.downcase.gsub(/\s+/, "") |
||||
end |
||||
end |
||||
|
||||
Rack::Attack.throttled_responder = lambda do |_env| |
||||
headers = { |
||||
"Location" => "/429", |
||||
} |
||||
[301, headers, []] |
||||
end |
@ -0,0 +1,64 @@
|
||||
require "rails_helper" |
||||
require_relative "../support/devise" |
||||
require "rack/attack" |
||||
|
||||
describe "Rack::Attack" do |
||||
let(:limit) { 5 } |
||||
let(:under_limit) { limit / 2 } |
||||
let(:over_limit) { limit + 1 } |
||||
|
||||
let(:page) { Capybara::Node::Simple.new(response.body) } |
||||
let(:notify_client) { instance_double(Notifications::Client) } |
||||
let(:devise_notify_mailer) { DeviseNotifyMailer.new } |
||||
|
||||
let(:params) { { user: { email: } } } |
||||
let(:user) { FactoryBot.create(:user) } |
||||
let(:email) { user.email } |
||||
|
||||
before do |
||||
Rack::Attack.enabled = true |
||||
allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer) |
||||
allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client) |
||||
allow(notify_client).to receive(:send_email).and_return(true) |
||||
end |
||||
|
||||
after do |
||||
Rack::Attack.enabled = false |
||||
Rack::Attack.reset! |
||||
end |
||||
|
||||
context "when a password reset is requested" do |
||||
context "when the number of requests is under the throttle limit" do |
||||
it "does not throttle" do |
||||
under_limit.times do |
||||
post "/users/password", params: params |
||||
follow_redirect! |
||||
end |
||||
last_response = response |
||||
expect(last_response.status).to eq(200) |
||||
end |
||||
end |
||||
|
||||
context "when the number of requests is at the throttle limit" do |
||||
it "does not throttle" do |
||||
limit.times do |
||||
post "/users/password", params: params |
||||
follow_redirect! |
||||
end |
||||
last_response = response |
||||
expect(last_response.status).to eq(200) |
||||
end |
||||
end |
||||
|
||||
context "when the number of requests is over the throttle limit" do |
||||
it "throttles" do |
||||
over_limit.times do |
||||
post "/users/password", params: params |
||||
follow_redirect! |
||||
end |
||||
last_response = response |
||||
expect(last_response.status).to eq(429) |
||||
end |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue