diff --git a/Gemfile b/Gemfile index 9eb64a26d..aa4841bd9 100644 --- a/Gemfile +++ b/Gemfile @@ -50,6 +50,7 @@ gem "paper_trail" # Store active record objects in version whodunnits gem "paper_trail-globalid" # Receive exceptions and configure alerts +gem "rack-attack" gem "sentry-rails" gem "sentry-ruby" diff --git a/Gemfile.lock b/Gemfile.lock index e9d351f7e..e90d7a5cf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -290,6 +290,8 @@ GEM nio4r (~> 2.0) racc (1.6.0) rack (2.2.3) + rack-attack (6.6.0) + rack (>= 1.0, < 3) rack-mini-profiler (2.3.4) rack (>= 1.2.0) rack-proxy (0.7.2) @@ -490,6 +492,7 @@ DEPENDENCIES postcodes_io pry-byebug puma (~> 5.0) + rack-attack rack-mini-profiler (~> 2.0) rails (~> 7.0.1) roo diff --git a/spec/requests/rack_attack_spec.rb b/spec/requests/rack_attack_spec.rb new file mode 100644 index 000000000..446ae9ad1 --- /dev/null +++ b/spec/requests/rack_attack_spec.rb @@ -0,0 +1,43 @@ +require "rails_helper" +require_relative "../support/devise" +require_relative "../support/rack_attack" +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 } + + before do + Rack::Attack.enabled = false + 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 + + context "when a regular user" do + let(:params) { { user: { email: } } } + + context "when a password reset is requested for a valid email" do + let(:user) { FactoryBot.create(:user) } + let(:email) { user.email } + + it "does not throttle" do + under_limit.times do + post "/users/password", params: params + follow_redirect! + end + expect(last_response.status).to eq(200) + + # post "/users/password", params: params + # expect(response).to have_http_status(:redirect) + # follow_redirect! + # expect(response.body).to match(/Check your email/) + end + end + end +end diff --git a/spec/support/rack_attack.rb b/spec/support/rack_attack.rb new file mode 100644 index 000000000..d65130bde --- /dev/null +++ b/spec/support/rack_attack.rb @@ -0,0 +1,3 @@ +RSpec.configure do |config| + config.include Rack::Test::Methods # , type: :component <- this bypasses the email empty, but cannot read last_response method +end