diff --git a/Gemfile b/Gemfile index fc744b40..a0a85ec5 100644 --- a/Gemfile +++ b/Gemfile @@ -113,3 +113,5 @@ gem 'importmap-rails', '~> 2.0' gem 'cssbundling-rails', '~> 1.1' gem 'stimulus-rails', '~> 1.2' + +gem 'recaptcha', '~> 5.16' diff --git a/Gemfile.lock b/Gemfile.lock index 5c212f5b..3a7f155a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -516,6 +516,7 @@ GEM rake (13.2.1) rdoc (6.7.0) psych (>= 4.0.0) + recaptcha (5.17.0) redcarpet (3.6.0) redis (5.3.0) redis-client (>= 0.22.0) @@ -756,6 +757,7 @@ DEPENDENCIES rails (~> 7.1.3) rails-controller-testing rails_autolink + recaptcha (~> 5.16) redis (~> 5.0) riiif (~> 2.0) rsolr (>= 1.0) diff --git a/app/assets/stylesheets/footer.scss b/app/assets/stylesheets/footer.scss index c95062b2..673235a7 100644 --- a/app/assets/stylesheets/footer.scss +++ b/app/assets/stylesheets/footer.scss @@ -68,3 +68,7 @@ } } } + +.grecaptcha-badge { + visibility: hidden; +} diff --git a/app/controllers/record_feedback_controller.rb b/app/controllers/record_feedback_controller.rb index 9cd07ad7..6702d712 100644 --- a/app/controllers/record_feedback_controller.rb +++ b/app/controllers/record_feedback_controller.rb @@ -6,15 +6,12 @@ # to redirect to the correct place and set the correct notice class RecordFeedbackController < Spotlight::ContactFormsController def create - if @contact_form.valid? - Spotlight::ContactMailer.report_problem(@contact_form).deliver_now + return render 'new' unless @contact_form.valid? - redirect_back( - fallback_location: spotlight.exhibit_solr_document_path(current_exhibit), - notice: t(:'helpers.submit.record_feedback.created') - ) + if verify_recaptcha(action: 'feedback') + send_feedback else - render 'new' + report_failure end end @@ -26,4 +23,15 @@ def build_contact_form @contact_form.request = request @contact_form end + + def send_feedback + Spotlight::ContactMailer.report_problem(@contact_form).deliver_now + redirect_back fallback_location: spotlight.exhibit_solr_document_path(current_exhibit), + notice: t(:'helpers.submit.record_feedback.created') + end + + def report_failure + redirect_back fallback_location: spotlight.new_exhibit_contact_form_path(current_exhibit), + alert: t(:'helpers.submit.record_feedback.error') + end end diff --git a/app/views/spotlight/shared/_report_a_problem.html.erb b/app/views/spotlight/shared/_report_a_problem.html.erb index d486146b..140760af 100644 --- a/app/views/spotlight/shared/_report_a_problem.html.erb +++ b/app/views/spotlight/shared/_report_a_problem.html.erb @@ -12,7 +12,30 @@ <%= f.text_field :name %> <%= render '/spotlight/shared/honeypot_field', f: f %> <%= f.email_field :email %> +
+
+

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

+
+
<%= f.hidden_field :current_url %> + <%= recaptcha_v3(action: 'feedback', inline_script: false) %> +
<%= f.submit nil, class: 'btn btn-primary' %> diff --git a/config/application.rb b/config/application.rb index 46e75ebc..773557ba 100644 --- a/config/application.rb +++ b/config/application.rb @@ -29,5 +29,10 @@ class Application < Rails::Application unless Rails.env.production? config.slowpoke.timeout = 60 end + + Recaptcha.configure do |config| + config.site_key = ENV.fetch('RECAPTCHA_SITE_KEY', '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy') + config.secret_key = ENV.fetch('RECAPTCHA_SECRET_KEY', '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx') + end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index ede7483f..460580de 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -105,6 +105,7 @@ en: created: Thank you. Your feedback has been submitted. record_feedback: created: Thank you. Your feedback has been submitted. + error: There was a problem submitting feedback. metadata_collapse: button: less: less diff --git a/spec/controllers/record_feedback_controller_spec.rb b/spec/controllers/record_feedback_controller_spec.rb index 89fad9f3..4d5bcc1f 100644 --- a/spec/controllers/record_feedback_controller_spec.rb +++ b/spec/controllers/record_feedback_controller_spec.rb @@ -20,8 +20,25 @@ end describe 'POST create' do - it 'sends an email' do - expect do + context 'when recaptcha verification succeeds' do + before do + allow(controller).to receive(:verify_recaptcha).and_return(true) + end + + it 'sends an email' do + expect do + post( + :create, + params: { + exhibit_id: exhibit.id, + id: 'abc123', + contact_form: { name: 'Joe Doe', email: 'jdoe@example.com', message: 'Great record!', honeypot_field_name => '' } + } + ) + end.to change { ActionMailer::Base.deliveries.count }.by(1) + end + + it 'redirects back' do post( :create, params: { @@ -30,31 +47,33 @@ contact_form: { name: 'Joe Doe', email: 'jdoe@example.com', message: 'Great record!', honeypot_field_name => '' } } ) - end.to change { ActionMailer::Base.deliveries.count }.by(1) - end + expect(response).to redirect_to 'http://test.host/' + end - it 'redirects back' do - post( - :create, - params: { - exhibit_id: exhibit.id, - id: 'abc123', - contact_form: { name: 'Joe Doe', email: 'jdoe@example.com', message: 'Great record!', honeypot_field_name => '' } - } - ) - expect(response).to redirect_to 'http://test.host/' + it 'sets a flash message' do + post( + :create, + params: { + exhibit_id: exhibit.id, + id: 'abc123', + contact_form: { name: 'Joe Doe', email: 'jdoe@example.com', message: 'Great record!', honeypot_field_name => '' } + } + ) + expect(flash[:notice]).to eq 'Thank you. Your feedback has been submitted.' + end end - it 'sets a flash message' do - post( - :create, - params: { - exhibit_id: exhibit.id, - id: 'abc123', - contact_form: { name: 'Joe Doe', email: 'jdoe@example.com', message: 'Great record!', honeypot_field_name => '' } - } - ) - expect(flash[:notice]).to eq 'Thank you. Your feedback has been submitted.' + context 'when recaptcha verification fails' do + before do + allow(controller).to receive(:verify_recaptcha).and_return(false) + end + + it 'alerts the failure in the flash message' do + post :create, params: { exhibit_id: exhibit.id, id: 'abc123', + contact_form: { name: 'Joe Doe', email: 'jdoe@example.com', message: 'Great record!', + honeypot_field_name => '' } } + expect(flash[:alert]).to eq 'There was a problem submitting feedback.' + end end end end