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