Skip to content

Commit 43a66b7

Browse files
0.379.0
2 parents 9daf462 + 8956ab9 commit 43a66b7

10 files changed

Lines changed: 120 additions & 26 deletions

File tree

Gemfile.lock

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
GIT
22
remote: https://github.com/18F/omniauth_login_dot_gov.git
3-
revision: b4d30dc92f2659e46680161bf02550ba424d768e
3+
revision: 3eeff9bfcd57d781467e2ffb6cc11f459d8202ed
44
branch: main
55
specs:
66
omniauth_login_dot_gov (3.0.0)
@@ -103,10 +103,10 @@ GEM
103103
aes_key_wrap (1.1.0)
104104
ast (2.4.3)
105105
aws-eventstream (1.3.2)
106-
aws-partitions (1.1074.0)
106+
aws-partitions (1.1078.0)
107107
aws-record (2.13.2)
108108
aws-sdk-dynamodb (~> 1, >= 1.85.0)
109-
aws-sdk-core (3.221.0)
109+
aws-sdk-core (3.222.1)
110110
aws-eventstream (~> 1, >= 1.3.0)
111111
aws-partitions (~> 1, >= 1.992.0)
112112
aws-sigv4 (~> 1.9)
@@ -130,7 +130,7 @@ GEM
130130
aws-sessionstore-dynamodb (~> 2)
131131
concurrent-ruby (~> 1.3, >= 1.3.1)
132132
railties (>= 7.0.0)
133-
aws-sdk-s3 (1.182.0)
133+
aws-sdk-s3 (1.183.0)
134134
aws-sdk-core (~> 3, >= 3.216.0)
135135
aws-sdk-kms (~> 1)
136136
aws-sigv4 (~> 1.5)
@@ -329,7 +329,7 @@ GEM
329329
listen (3.9.0)
330330
rb-fsevent (~> 0.10, >= 0.10.3)
331331
rb-inotify (~> 0.9, >= 0.9.10)
332-
logger (1.6.6)
332+
logger (1.7.0)
333333
logstop (0.4.1)
334334
logger
335335
loofah (2.24.0)
@@ -370,24 +370,24 @@ GEM
370370
net-protocol
371371
newrelic_rpm (9.17.0)
372372
nio4r (2.7.4)
373-
nokogiri (1.18.6)
373+
nokogiri (1.18.7)
374374
mini_portile2 (~> 2.8.2)
375375
racc (~> 1.4)
376-
nokogiri (1.18.6-aarch64-linux-gnu)
376+
nokogiri (1.18.7-aarch64-linux-gnu)
377377
racc (~> 1.4)
378-
nokogiri (1.18.6-aarch64-linux-musl)
378+
nokogiri (1.18.7-aarch64-linux-musl)
379379
racc (~> 1.4)
380-
nokogiri (1.18.6-arm-linux-gnu)
380+
nokogiri (1.18.7-arm-linux-gnu)
381381
racc (~> 1.4)
382-
nokogiri (1.18.6-arm-linux-musl)
382+
nokogiri (1.18.7-arm-linux-musl)
383383
racc (~> 1.4)
384-
nokogiri (1.18.6-arm64-darwin)
384+
nokogiri (1.18.7-arm64-darwin)
385385
racc (~> 1.4)
386-
nokogiri (1.18.6-x86_64-darwin)
386+
nokogiri (1.18.7-x86_64-darwin)
387387
racc (~> 1.4)
388-
nokogiri (1.18.6-x86_64-linux-gnu)
388+
nokogiri (1.18.7-x86_64-linux-gnu)
389389
racc (~> 1.4)
390-
nokogiri (1.18.6-x86_64-linux-musl)
390+
nokogiri (1.18.7-x86_64-linux-musl)
391391
racc (~> 1.4)
392392
oauth2 (2.0.9)
393393
faraday (>= 0.17.3, < 3.0)
@@ -415,7 +415,7 @@ GEM
415415
activerecord (>= 6.1)
416416
request_store (~> 1.4)
417417
parallel (1.26.3)
418-
parser (3.3.7.3)
418+
parser (3.3.7.4)
419419
ast (~> 2.4.1)
420420
racc
421421
pg (1.5.9)
@@ -492,7 +492,7 @@ GEM
492492
rb-fsevent (0.11.2)
493493
rb-inotify (0.11.1)
494494
ffi (~> 1.0)
495-
rdoc (6.13.0)
495+
rdoc (6.13.1)
496496
psych (>= 4.0.0)
497497
redis (5.4.0)
498498
redis-client (>= 0.22.0)
@@ -529,7 +529,7 @@ GEM
529529
rspec-support (3.13.2)
530530
rspec_junit_formatter (0.6.0)
531531
rspec-core (>= 2, < 4, != 2.12.0)
532-
rubocop (1.75.0)
532+
rubocop (1.75.1)
533533
json (~> 2.3)
534534
language_server-protocol (~> 3.17.0.2)
535535
lint_roller (~> 1.1.0)
@@ -543,11 +543,11 @@ GEM
543543
rubocop-ast (1.43.0)
544544
parser (>= 3.3.7.2)
545545
prism (~> 1.4)
546-
rubocop-rails (2.30.3)
546+
rubocop-rails (2.31.0)
547547
activesupport (>= 4.2.0)
548548
lint_roller (~> 1.1)
549549
rack (>= 1.1)
550-
rubocop (>= 1.72.1, < 2.0)
550+
rubocop (>= 1.75.0, < 2.0)
551551
rubocop-ast (>= 1.38.0, < 2.0)
552552
rubocop-rspec (3.5.0)
553553
lint_roller (~> 1.1)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ within the Technology Transformation Services'
2626

2727
Touchpoints is online at <https://touchpoints.digital.gov/>.
2828

29-
A current Demo version is online at <https://touchpoints-demo.app.cloud.gov/index/>,
29+
A Demo environment is online at <https://app-demo.touchpoints.digital.gov/>,
3030
and government customers are [encouraged](https://github.com/GSA/touchpoints/wiki/Touchpoints-Demo-Environment/) to sign up and try it out.
3131

3232
## Documentation

app/controllers/admin/forms_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,8 @@ def form_admin_options_params
573573
:kind,
574574
:aasm_state,
575575
:early_submission,
576+
:enable_turnstile,
577+
:append_id_to_success_text,
576578
:notes,
577579
:status,
578580
:title,

app/controllers/submissions_controller.rb

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,21 @@ def create
8181
private
8282

8383
def create_in_local_database(submission)
84+
if submission.form.enable_turnstile? && !verify_turnstile(params["cf-turnstile-response"])
85+
submission.errors.add(:base, "Turnstile verification failed")
86+
end
87+
8488
respond_to do |format|
85-
if submission.save
89+
if submission.errors.empty? && submission.save
8690
format.html do
8791
redirect_to submit_touchpoint_path(submission.form),
8892
notice: 'Thank You. Response was submitted successfully.'
8993
end
9094
format.json do
95+
form_success_text = submission.form.append_id_to_success_text? ?
96+
submission.form.success_text + "<br><br> Your Response ID is: <strong>#{submission.uuid[-12..-1]}</strong>" :
97+
submission.form.success_text
98+
9199
render json: {
92100
submission: {
93101
id: submission.uuid,
@@ -115,6 +123,8 @@ def create_in_local_database(submission)
115123
id: submission.form.uuid,
116124
name: submission.form.name,
117125
organization_name: submission.organization_name,
126+
success_text_heading: submission.form.success_text_heading,
127+
success_text: form_success_text,
118128
},
119129
},
120130
},
@@ -151,10 +161,28 @@ def set_form
151161
def submission_params
152162
permitted_fields = @form.questions.collect(&:answer_field)
153163
permitted_fields << %i[language location_code referer hostname page query_string fba_directive]
164+
permitted_fields << %i[cf-turnstile-response]
154165
params.require(:submission).permit(permitted_fields)
155166
end
156167

157168
def form_requires_verification
158169
@form.verify_csrf?
159170
end
171+
172+
173+
private
174+
175+
def verify_turnstile(response_token)
176+
secret_key = ENV.fetch("TURNSTILE_SECRET_KEY", nil)
177+
uri = URI("https://challenges.cloudflare.com/turnstile/v0/siteverify")
178+
179+
response = Net::HTTP.post_form(uri, {
180+
"secret" => secret_key,
181+
"response" => response_token,
182+
"remoteip" => request.remote_ip
183+
})
184+
185+
json = JSON.parse(response.body)
186+
json["success"] == true
187+
end
160188
end

app/views/admin/forms/_form_manager_options.html.erb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,30 @@
9595
<%= f.text_field :expiration_date, class: "usa-input" %>
9696
</div>
9797

98+
<fieldset class="usa-fieldset margin-top-2">
99+
<legend class="usa-sr-only">Enable Cloudfront Turnstile</legend>
100+
<div class="usa-checkbox">
101+
<%= f.check_box :enable_turnstile, class: "usa-checkbox__input" %>
102+
<%= f.label :enable_turnstile, class: "usa-checkbox__label" do %>
103+
Enable Cloudfront Turnstile
104+
<small class="text-base">
105+
As a spam prevention mechanism
106+
</small>
107+
<% end %>
108+
</div>
109+
</fieldset>
110+
<fieldset class="usa-fieldset margin-top-2">
111+
<legend class="usa-sr-only">Append ID to the form's Success Text</legend>
112+
<div class="usa-checkbox">
113+
<%= f.check_box :append_id_to_success_text, class: "usa-checkbox__input" %>
114+
<%= f.label :append_id_to_success_text, class: "usa-checkbox__label" do %>
115+
Append ID to Form's Success Text
116+
<small class="text-base">
117+
Append "Your Response ID is: 1307" to the Form's Success Text
118+
</small>
119+
<% end %>
120+
</div>
121+
</fieldset>
98122
<fieldset class="usa-fieldset margin-top-2">
99123
<legend class="usa-sr-only">Display Organization Tag Logo</legend>
100124
<div class="usa-checkbox">

app/views/components/forms/_custom.html.erb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@
107107
<% end %>
108108
</div>
109109
<% end %>
110+
<% if form.enable_turnstile? %>
111+
<div class="margin-top-2">
112+
<div class="cf-turnstile" data-sitekey="<%= ENV.fetch("TURNSTILE_SITE_KEY", nil) %>"></div>
113+
<%= hidden_field_tag "cf-turnstile-response", nil %>
114+
</div>
115+
<% end %>
110116
<%- if section == form.form_sections.last && !form.suppress_submit_button %>
111117
<button type="submit" class="usa-button submit_form_button"><%= t 'form.submit' %></button>
112118
<% end %>

app/views/components/widget/_fba.js.erb

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ function FBAform(d, N) {
3838
if (this.options.formSpecificScript) {
3939
this.options.formSpecificScript();
4040
}
41+
<% if form.enable_turnstile? %>
42+
this.loadTurnstile()
43+
<% end %>
4144
d.dispatchEvent(new CustomEvent('onTouchpointsFormLoaded', {
4245
detail: {
4346
formComponent: this
@@ -413,16 +416,16 @@ function FBAform(d, N) {
413416
successText: function() {
414417
return this.options.successText;
415418
},
416-
showFormSuccess: function(e) {
419+
showFormSuccess: function(headerText, bodyHTML) {
417420
var formComponent = this.formComponent();
418421
var formElement = this.formElement();
419422
var alertElement = formComponent.querySelector(".fba-alert");
420423
var alertElementHeading = formComponent.querySelector(".usa-alert__heading");
421424
var alertElementBody = formComponent.querySelector(".usa-alert__text");
422425
423426
// Display success Message
424-
alertElementHeading.innerHTML += this.successHeadingText();
425-
alertElementBody.innerHTML = this.successText();
427+
alertElementHeading.innerHTML = headerText;
428+
alertElementBody.innerHTML = bodyHTML
426429
alertElement.removeAttribute("hidden");
427430
this.formComponent().scrollIntoView();
428431
@@ -489,7 +492,11 @@ function FBAform(d, N) {
489492
if(submitButton) {
490493
submitButton.disabled = true;
491494
}
492-
this.showFormSuccess();
495+
496+
const submission = JSON.parse(e.target.response).submission;
497+
const successHeaderText = submission.form.success_text_heading;
498+
const successBodyText = submission.form.success_text;
499+
this.showFormSuccess(successHeaderText, successBodyText);
493500
} else if (e.target.status === 422) { // FORM ERRORS
494501
this.successState = false;
495502
d.dispatchEvent(new Event('onTouchpointsFormSubmissionError'));
@@ -548,6 +555,9 @@ function FBAform(d, N) {
548555
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8;");
549556
xhr.onload = callback.bind(this);
550557
xhr.send(JSON.stringify({
558+
<% if form.enable_turnstile? %>
559+
"cf-turnstile-response" : form.querySelector("input[name='cf-turnstile-response']") ? form.querySelector("input[name='cf-turnstile-response']").value : null,
560+
<% end %>
551561
"submission": params,
552562
<%- if form.verify_csrf? %>
553563
"authenticity_token": form.querySelector("#authenticity_token") ?
@@ -635,6 +645,18 @@ function FBAform(d, N) {
635645
modalId: function() {
636646
return `fba-modal-${this.options.formId}`;
637647
},
648+
<% if form.enable_turnstile? %>
649+
loadTurnstile: function() {
650+
let script = document.createElement("script");
651+
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js";
652+
script.async = true;
653+
script.defer = true;
654+
script.onload = function() {
655+
document.querySelector("input[name='cf-turnstile-response']").value = token;
656+
};
657+
document.head.appendChild(script);
658+
},
659+
<% end %>
638660
};
639661
};
640662
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AppendIdToSuccessText < ActiveRecord::Migration[8.0]
2+
def change
3+
add_column :forms, :append_id_to_success_text, :boolean, default: false, comment: "Set to true to append a response ID to the form's success_text"
4+
end
5+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddFormTurnstile < ActiveRecord::Migration[8.0]
2+
def change
3+
add_column :forms, :enable_turnstile, :boolean, default: false, comment: "Set to true to enable Cloudfront Turnstile"
4+
end
5+
end

db/schema.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[8.0].define(version: 2025_03_07_211304) do
13+
ActiveRecord::Schema[8.0].define(version: 2025_04_01_223209) do
1414
# These are extensions that must be enabled in order to support this database
1515
enable_extension "pg_catalog.plpgsql"
1616

@@ -302,6 +302,8 @@
302302
t.string "short_uuid", limit: 8
303303
t.boolean "enforce_new_submission_validations", default: true
304304
t.integer "service_stage_id"
305+
t.boolean "append_id_to_success_text", default: false, comment: "Set to true to append a response ID to the form's success_text"
306+
t.boolean "enable_turnstile", default: false, comment: "Set to true to enable Cloudfront Turnstile"
305307
t.index ["legacy_touchpoint_id"], name: "index_forms_on_legacy_touchpoint_id"
306308
t.index ["legacy_touchpoint_uuid"], name: "index_forms_on_legacy_touchpoint_uuid"
307309
t.index ["organization_id"], name: "index_forms_on_organization_id"

0 commit comments

Comments
 (0)