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 %>
+
<%= 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