From 78236e6c7baeba9404e8a900bcbd438d6644915e Mon Sep 17 00:00:00 2001
From: Zach Margolis
Date: Thu, 25 Feb 2021 11:26:28 -0800
Subject: [PATCH] Revert "Merge pull request #4714 from
18F/stages/rc-2021-02-25"
This reverts commit e539c88a72f4b930a9aaceaff1d4d47d258814e4, reversing
changes made to ae0189c16111a742a02a419aaaf7fef76609eed1.
---
.circleci/config.yml | 12 +-
.eslintrc | 12 +-
Gemfile | 5 +-
Gemfile.lock | 23 +-
README.md | 2 -
app/assets/images/wait.gif | Bin 0 -> 7312 bytes
app/controllers/analytics_controller.rb | 33 +++
app/controllers/application_controller.rb | 19 +-
.../concerns/fully_authenticatable.rb | 1 -
.../concerns/idv/document_capture_concern.rb | 15 --
.../concerns/verify_sp_attributes_concern.rb | 4 +
app/controllers/idv/cac_controller.rb | 5 +
.../idv/cancellations_controller.rb | 20 +-
app/controllers/idv/capture_doc_controller.rb | 18 +-
.../idv/capture_doc_status_controller.rb | 4 +-
app/controllers/idv/doc_auth_controller.rb | 13 +-
.../idv/image_uploads_controller.rb | 45 +---
app/controllers/idv_controller.rb | 5 +-
.../authorization_controller.rb | 10 +-
.../openid_connect/logout_controller.rb | 3 +
app/controllers/saml_idp_controller.rb | 3 +-
.../users/piv_cac_login_controller.rb | 2 +-
app/controllers/users/sessions_controller.rb | 6 +-
app/helpers/go_back_helper.rb | 22 --
app/helpers/session_timeout_warning_helper.rb | 41 +++-
app/javascript/app/platform-authenticator.js | 20 ++
.../components/acuant-capture.jsx | 60 +-----
.../components/file-input.jsx | 2 +-
.../document-capture/context/acuant.jsx | 31 +--
.../document-capture/context/analytics.jsx | 2 +-
.../with-background-encrypted-upload.jsx | 13 +-
app/javascript/packages/polyfill/index.js | 8 +-
app/javascript/packages/polyfill/package.json | 1 +
app/javascript/packs/application.js | 1 +
app/javascript/packs/document-capture.jsx | 61 +++---
app/javascript/packs/ial2-consent-button.js | 5 +-
.../packs/session-expire-session.js | 10 -
app/javascript/packs/session-timeout-ping.js | 135 ------------
app/javascript/packs/submit-with-spinner.js | 8 +
app/models/agency.rb | 1 -
app/models/letter_requests_to_usps_ftp_log.rb | 4 -
app/models/null_service_provider.rb | 5 -
app/models/service_provider.rb | 6 -
app/presenters/cancellation_presenter.rb | 1 -
app/presenters/idv/usps_presenter.rb | 8 +-
app/services/agency_seeder.rb | 1 +
app/services/analytics.rb | 4 +-
.../data_requests/write_cloudwatch_logs.rb | 51 ++---
app/services/db/sp_cost/add_sp_cost.rb | 10 +-
app/services/doc_auth_router.rb | 10 +
.../document_capture_session_async_result.rb | 2 -
.../encryption/multi_region_kms_client.rb | 2 +-
app/services/flow/flow_state_machine.rb | 45 +---
app/services/identity_linker.rb | 1 -
.../idv/actions/cancel_link_sent_action.rb | 9 -
.../idv/actions/cancel_send_link_action.rb | 9 -
.../idv/actions/verify_document_action.rb | 10 +-
.../actions/verify_document_status_action.rb | 10 +-
app/services/idv/flows/cac_flow.rb | 1 +
app/services/idv/flows/capture_doc_flow.rb | 2 -
app/services/idv/flows/doc_auth_flow.rb | 2 -
app/services/idv/steps/cac/success_step.rb | 9 +
app/services/idv/steps/doc_auth_base_step.rb | 8 +-
app/services/idv/steps/link_sent_step.rb | 5 +-
app/services/idv/steps/verify_base_step.rb | 10 +-
.../monthly_usps_letter_requests_report.rb | 22 --
app/services/sp_handoff_bounce.rb | 13 --
.../add_handoff_time_to_session.rb | 7 +
app/services/sp_handoff_bounce/is_bounced.rb | 11 +
app/services/store_sp_metadata_in_session.rb | 1 -
app/services/usps_confirmation_uploader.rb | 7 +-
.../confirm_delete_account/show.html.erb | 2 +-
.../delete_account/show.html.erb | 2 +-
app/views/devise/sessions/new.html.erb | 2 +-
app/views/idv/address/new.html.erb | 4 +-
app/views/idv/cac/success.html.erb | 22 ++
app/views/idv/doc_auth/_back.html.erb | 31 ---
app/views/idv/doc_auth/_spinner.html.erb | 11 +
.../doc_auth/_submit_with_spinner.html.erb | 6 +
app/views/idv/doc_auth/link_sent.html.erb | 2 +-
app/views/idv/doc_auth/send_link.html.erb | 2 +-
app/views/idv/doc_auth/upload.html.erb | 2 +-
app/views/idv/doc_auth/welcome.html.erb | 3 +-
.../idv/shared/_document_capture.html.erb | 9 +-
app/views/idv/usps/index.html.erb | 5 +-
app/views/layouts/base.html.erb | 24 +--
.../session_timeout/_expire_session.html.erb | 7 -
.../session_timeout/_expire_session.js.erb | 7 +
app/views/session_timeout/_ping.html.erb | 11 -
app/views/session_timeout/_ping.js.erb | 84 ++++++++
.../account_reset_request.html.erb | 2 +-
app/views/users/delete/show.html.erb | 1 -
bin/smoke_test | 19 +-
config/application.yml.default | 31 +--
.../acuant_simulator_config_validation.rb | 37 ++++
config/initializers/job_configurations.rb | 8 -
config/initializers/saml_idp.rb | 4 +-
config/locales/account_reset/en.yml | 5 +-
config/locales/account_reset/es.yml | 9 +-
config/locales/account_reset/fr.yml | 5 +-
config/locales/cac_proofing/en.yml | 1 +
config/locales/cac_proofing/es.yml | 1 +
config/locales/cac_proofing/fr.yml | 1 +
config/locales/image_description/en.yml | 1 +
config/locales/image_description/es.yml | 1 +
config/locales/image_description/fr.yml | 1 +
config/locales/user_mailer/en.yml | 25 +--
config/locales/user_mailer/es.yml | 27 +--
config/locales/user_mailer/fr.yml | 30 ++-
config/locales/users/en.yml | 2 -
config/locales/users/es.yml | 2 -
config/locales/users/fr.yml | 2 -
config/routes.rb | 16 +-
config/service_providers.localdev.yml | 21 --
...185311_remove_user_id_index_from_events.rb | 5 -
...7_add_uniqueness_to_agency_abbreviation.rb | 7 -
...23232534_add_transaction_id_to_sp_costs.rb | 5 -
...245131_letter_requests_to_usps_ftp_logs.rb | 9 -
db/schema.rb | 15 +-
lib/feature_management.rb | 4 +
lib/lambda_jobs/git_ref.rb | 2 +-
mac-test-passphrase-prompt.png | Bin 0 -> 50358 bytes
package.json | 2 +-
.../config/initializers/job_configurations.rb | 14 --
.../idv/document_capture_concern_spec.rb | 28 ---
.../idv/capture_doc_controller_spec.rb | 21 ++
.../idv/doc_auth_controller_spec.rb | 64 ++----
.../idv/image_uploads_controller_spec.rb | 154 +------------
.../authorization_controller_spec.rb | 1 -
spec/controllers/saml_idp_controller_spec.rb | 4 +-
.../sign_up/completions_controller_spec.rb | 4 +-
.../actions/cancel_link_sent_action_spec.rb | 17 --
.../actions/cancel_send_link_action_spec.rb | 17 --
spec/features/idv/cac/success_step_spec.rb | 20 ++
spec/features/idv/cac/use_cac_step_spec.rb | 11 +-
spec/features/idv/cac/verify_step_spec.rb | 8 +-
.../idv/clearing_and_restarting_spec.rb | 26 +++
.../idv/doc_auth/address_step_spec.rb | 6 -
.../doc_auth/document_capture_step_spec.rb | 13 --
.../idv/doc_auth/link_sent_step_spec.rb | 11 +-
.../idv/doc_auth/send_link_step_spec.rb | 7 +-
.../idv/doc_auth/welcome_step_spec.rb | 8 -
.../doc_capture/document_capture_step_spec.rb | 53 +----
spec/features/idv/hybrid_flow_spec.rb | 62 ------
.../phone_otp_delivery_selection_step_spec.rb | 13 --
spec/features/idv/steps/phone_step_spec.rb | 15 --
spec/features/idv/steps/usps_step_spec.rb | 17 +-
.../openid_connect/openid_connect_spec.rb | 8 +
.../reports/authorization_count_spec.rb | 203 ------------------
...onthly_usps_letter_requests_report_spec.rb | 37 ----
spec/features/saml/ial1_sso_spec.rb | 1 +
spec/features/sp_cost_tracking_spec.rb | 9 +-
.../multiple_tabs_spec.rb | 9 +
spec/features/users/sign_in_spec.rb | 23 +-
spec/helpers/go_back_helper_spec.rb | 87 --------
.../components/acuant-capture-canvas-spec.jsx | 18 +-
.../components/acuant-capture-spec.jsx | 198 +++++++----------
.../components/document-capture-spec.jsx | 103 ++++++---
.../components/file-image-spec.jsx | 34 +--
.../components/file-input-spec.jsx | 49 +++--
.../components/selfie-capture-spec.jsx | 6 +-
.../components/selfie-step-spec.jsx | 52 ++---
.../document-capture/context/acuant-spec.jsx | 202 +++++++----------
.../with-background-encrypted-upload-spec.jsx | 12 +-
.../packs/submit-with-spinner-spec.js | 41 ++++
spec/javascripts/spec_helper.js | 10 -
spec/javascripts/support/crypto.js | 33 ---
spec/javascripts/support/dom.js | 12 +-
spec/javascripts/support/file.js | 51 -----
spec/mailers/user_mailer_spec.rb | 5 +-
spec/models/agency_spec.rb | 1 -
spec/models/null_service_provider_spec.rb | 8 -
spec/models/service_provider_spec.rb | 12 --
spec/monitor_spec_helper.rb | 31 ---
spec/presenters/idv/usps_presenter_spec.rb | 8 +-
spec/requests/frontend_analytics_spec.rb | 63 ++++++
spec/services/agency_seeder_spec.rb | 2 +
.../write_cloudwatch_logs_spec.rb | 97 ---------
spec/services/doc_auth_router_spec.rb | 13 ++
.../encryption/contextless_kms_client_spec.rb | 16 +-
spec/services/encryption/kms_client_spec.rb | 44 +---
.../multi_region_kms_client_spec.rb | 68 +++---
spec/services/identity_linker_spec.rb | 4 +-
spec/services/idv/agent_spec.rb | 30 +--
.../store_sp_metadata_in_session_spec.rb | 2 -
.../usps_confirmation_uploader_spec.rb | 8 +-
spec/support/aws_kms_client.rb | 29 +--
spec/support/fake_analytics.rb | 3 +-
spec/support/features/cac_proofing_helper.rb | 4 +
spec/support/features/doc_auth_helper.rb | 13 --
spec/support/saml_auth_helper.rb | 20 --
.../shared_examples/account_creation.rb | 2 +
spec/support/shared_examples/ial2_consent.rb | 9 +-
spec/support/shared_examples/sign_in.rb | 21 ++
.../views/idv/doc_auth/_back.html.erb_spec.rb | 40 ----
.../shared/_document_capture.html.erb_spec.rb | 31 +--
spec/views/idv/usps/index.html.erb_spec.rb | 69 +-----
spec/views/users/delete/show.html.erb_spec.rb | 1 -
tsconfig.json | 3 +-
yarn.lock | 67 +++---
200 files changed, 1381 insertions(+), 2639 deletions(-)
create mode 100644 app/assets/images/wait.gif
delete mode 100644 app/controllers/concerns/idv/document_capture_concern.rb
delete mode 100644 app/helpers/go_back_helper.rb
create mode 100644 app/javascript/app/platform-authenticator.js
delete mode 100644 app/javascript/packs/session-expire-session.js
delete mode 100644 app/javascript/packs/session-timeout-ping.js
create mode 100644 app/javascript/packs/submit-with-spinner.js
delete mode 100644 app/models/letter_requests_to_usps_ftp_log.rb
delete mode 100644 app/services/idv/actions/cancel_link_sent_action.rb
delete mode 100644 app/services/idv/actions/cancel_send_link_action.rb
create mode 100644 app/services/idv/steps/cac/success_step.rb
delete mode 100644 app/services/reports/monthly_usps_letter_requests_report.rb
delete mode 100644 app/services/sp_handoff_bounce.rb
create mode 100644 app/services/sp_handoff_bounce/add_handoff_time_to_session.rb
create mode 100644 app/services/sp_handoff_bounce/is_bounced.rb
create mode 100644 app/views/idv/cac/success.html.erb
delete mode 100644 app/views/idv/doc_auth/_back.html.erb
create mode 100644 app/views/idv/doc_auth/_spinner.html.erb
create mode 100644 app/views/idv/doc_auth/_submit_with_spinner.html.erb
delete mode 100644 app/views/session_timeout/_expire_session.html.erb
create mode 100644 app/views/session_timeout/_expire_session.js.erb
delete mode 100644 app/views/session_timeout/_ping.html.erb
create mode 100644 app/views/session_timeout/_ping.js.erb
create mode 100644 config/initializers/acuant_simulator_config_validation.rb
delete mode 100644 db/migrate/20210218185311_remove_user_id_index_from_events.rb
delete mode 100644 db/migrate/20210223011217_add_uniqueness_to_agency_abbreviation.rb
delete mode 100644 db/migrate/20210223232534_add_transaction_id_to_sp_costs.rb
delete mode 100644 db/migrate/202102245131_letter_requests_to_usps_ftp_logs.rb
create mode 100644 mac-test-passphrase-prompt.png
delete mode 100644 spec/controllers/concerns/idv/document_capture_concern_spec.rb
delete mode 100644 spec/features/idv/actions/cancel_link_sent_action_spec.rb
delete mode 100644 spec/features/idv/actions/cancel_send_link_action_spec.rb
create mode 100644 spec/features/idv/cac/success_step_spec.rb
delete mode 100644 spec/features/idv/hybrid_flow_spec.rb
delete mode 100644 spec/features/reports/authorization_count_spec.rb
delete mode 100644 spec/features/reports/monthly_usps_letter_requests_report_spec.rb
create mode 100644 spec/features/two_factor_authentication/multiple_tabs_spec.rb
delete mode 100644 spec/helpers/go_back_helper_spec.rb
create mode 100644 spec/javascripts/packs/submit-with-spinner-spec.js
delete mode 100644 spec/javascripts/support/crypto.js
delete mode 100644 spec/javascripts/support/file.js
create mode 100644 spec/requests/frontend_analytics_spec.rb
delete mode 100644 spec/services/data_requests/write_cloudwatch_logs_spec.rb
delete mode 100644 spec/views/idv/doc_auth/_back.html.erb_spec.rb
diff --git a/.circleci/config.yml b/.circleci/config.yml
index cfa5be2cef3..9a31b401136 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -105,13 +105,6 @@ commands:
fail_only: true
failure_message: ":smokeybear::red_circle: Smoke tests failed in environment: $MONITOR_ENV"
include_project_field: false
- store-smoketest-results:
- steps:
- - store_test_results:
- path: tmp/capybara
- - store_artifacts:
- path: tmp/capybara
- destination: capybara
jobs:
build:
@@ -221,7 +214,6 @@ jobs:
command: |
bin/smoke_test --remote --no-source-env
- notify-slack-smoke-test-status
- - store-smoketest-results
smoketest-int:
working_directory: ~/identity-idp
executor: ruby_browsers
@@ -237,7 +229,6 @@ jobs:
command: |
bin/smoke_test --remote --no-source-env
- notify-slack-smoke-test-status
- - store-smoketest-results
smoketest-staging:
working_directory: ~/identity-idp
executor: ruby_browsers
@@ -253,7 +244,6 @@ jobs:
command: |
bin/smoke_test --remote --no-source-env
- notify-slack-smoke-test-status
- - store-smoketest-results
smoketest-prod:
working_directory: ~/identity-idp
executor: ruby_browsers
@@ -267,7 +257,7 @@ jobs:
command: |
bin/smoke_test --remote --no-source-env
- notify-slack-smoke-test-status
- - store-smoketest-results
+
workflows:
version: 2
release:
diff --git a/.eslintrc b/.eslintrc
index 3e4269b137b..ed988201927 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -25,7 +25,6 @@
"indent": "off",
"max-classes-per-file": "off",
"newline-per-chained-call": "off",
- "no-console": "error",
"no-empty": ["error", { "allowEmptyCatch": true }],
"no-param-reassign": ["off", "never"],
"no-confusing-arrow": "off",
@@ -37,12 +36,12 @@
"message": "Use CustomEvent constructor with polyfill for Internet Explorer"
},
{
- "selector": "AssignmentExpression[left.property.name='href'][right.type=/(Template)?Literal/]",
- "message": "Do not assign window.location.href to a string or string template to avoid losing i18n parameters"
+ "selector": "ArrayExpression > SpreadElement",
+ "message": "Don't use array spread, issue with IE 11 (use Array.from instead)"
},
{
- "selector": "CallExpression[callee.object.name=/^(it|describe|context)$/][callee.property.name='only'] > MemberExpression",
- "message": "Test exclusivity should not be committed"
+ "selector": "AssignmentExpression[left.property.name='href'][right.type=/(Template)?Literal/]",
+ "message": "Do not assign window.location.href to a string or string template to avoid losing i18n parameters"
}
],
"no-unused-expressions": "off",
@@ -76,7 +75,8 @@
{
"files": "spec/javascripts/**/*",
"rules": {
- "react/jsx-props-no-spreading": "off"
+ "react/jsx-props-no-spreading": "off",
+ "no-restricted-syntax": "off"
}
}
]
diff --git a/Gemfile b/Gemfile
index 269666ddbd1..30a5010e00d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -20,7 +20,7 @@ gem 'faraday'
gem 'foundation_emails'
gem 'hiredis'
gem 'http_accept_language'
-gem 'identity-doc-auth', github: '18F/identity-doc-auth', tag: 'v0.4.0'
+gem 'identity-doc-auth', github: '18F/identity-doc-auth', tag: 'v0.3.3'
gem 'identity-hostdata', github: '18F/identity-hostdata', tag: 'v0.4.3'
require File.join(__dir__, 'lib', 'lambda_jobs', 'git_ref.rb')
gem 'identity-idp-functions', github: '18F/identity-idp-functions', ref: LambdaJobs::GIT_REF
@@ -109,7 +109,6 @@ group :test do
gem 'rack_session_access', '>= 0.2.0'
gem 'rack-test', '>= 1.1.0'
gem 'rails-controller-testing', '>= 1.0.4'
- gem 'rspec-retry'
gem 'shoulda-matchers', '~> 4.0', require: false
gem 'timecop'
gem 'webdrivers', '~> 4.0'
@@ -118,6 +117,6 @@ group :test do
end
group :production do
- gem 'aamva', github: '18F/identity-aamva-api-client-gem', tag: 'v3.6.0'
+ gem 'aamva', github: '18F/identity-aamva-api-client-gem', tag: 'v3.4.1'
gem 'lexisnexis', github: '18F/identity-lexisnexis-api-client-gem', tag: 'v2.5.1.pre'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 8aad49c7fa5..be60bb9d55a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,22 +1,21 @@
GIT
remote: https://github.com/18F/identity-aamva-api-client-gem.git
- revision: dbf3d2e102603530a29cb43308b9aa639efaea1f
- tag: v3.6.0
+ revision: 149b5b480f0319ec39410e497bb4bbffd1652014
+ tag: v3.4.1
specs:
- aamva (3.6.0)
+ aamva (3.4.1)
dotenv
faraday
hashie
- proofer (>= 2.7.1)
retries
xmldsig
GIT
remote: https://github.com/18F/identity-doc-auth.git
- revision: 164a507fd17ecffe4ef2289120d89156358b3a80
- tag: v0.4.0
+ revision: 4e1e09d7e5eb673dfbc1e301feacc74859d25d29
+ tag: v0.3.3
specs:
- identity-doc-auth (0.4.0)
+ identity-doc-auth (0.3.3)
activesupport
faraday
@@ -30,11 +29,10 @@ GIT
GIT
remote: https://github.com/18F/identity-idp-functions.git
- revision: eb8aa1657173af64fd9fcad2ab4df2a5741eb51d
- ref: eb8aa1657173af64fd9fcad2ab4df2a5741eb51d
+ revision: 8c16776e19b211d15bda7246d99ff95155d60c11
+ ref: 8c16776e19b211d15bda7246d99ff95155d60c11
specs:
- identity-idp-functions (0.11.0)
- aamva (>= 3.5.0)
+ identity-idp-functions (0.10.0)
aws-sdk-s3 (>= 1.73)
aws-sdk-ssm (>= 1.55)
retries (>= 0.0.5)
@@ -573,8 +571,6 @@ GEM
rspec-expectations (~> 3.9)
rspec-mocks (~> 3.9)
rspec-support (~> 3.9)
- rspec-retry (0.6.2)
- rspec-core (> 3.3)
rspec-support (3.10.0)
rubocop (1.4.2)
parallel (~> 1.10)
@@ -801,7 +797,6 @@ DEPENDENCIES
rotp (~> 6.1)
rqrcode
rspec-rails (~> 4.0)
- rspec-retry
rubocop (~> 1.4.0)
rubocop-rails (>= 2.5.2)
ruby-progressbar
diff --git a/README.md b/README.md
index 603f18672c6..53bcf042807 100644
--- a/README.md
+++ b/README.md
@@ -113,8 +113,6 @@ We recommend using [Homebrew](https://brew.sh/), [rbenv](https://github.com/rben
MONITOR_ENV=INT ./bin/smoke_test --remote
```
- For remote smoke tests, we save a screenshot of failed test scenarios to help debugging in `tmp/capybara`, and they are exported to CircleCI as build artifacts as well.
-
#### Speeding up local development and testing
To automatically run the test that corresponds to the file you are editing,
diff --git a/app/assets/images/wait.gif b/app/assets/images/wait.gif
new file mode 100644
index 0000000000000000000000000000000000000000..209efd816c002a23803b2f6efe675d93be519699
GIT binary patch
literal 7312
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
literal 0
HcmV?d00001
diff --git a/app/controllers/analytics_controller.rb b/app/controllers/analytics_controller.rb
index d25ed58d006..866b616e704 100644
--- a/app/controllers/analytics_controller.rb
+++ b/app/controllers/analytics_controller.rb
@@ -2,6 +2,39 @@ class AnalyticsController < ApplicationController
skip_before_action :verify_authenticity_token
def create
+ results.each do |event, result|
+ next if result.nil?
+
+ analytics.track_event(event, result.to_h)
+ end
head :ok
end
+
+ private
+
+ def results
+ {
+ Analytics::FRONTEND_BROWSER_CAPABILITIES => platform_authenticator_result,
+ }
+ end
+
+ def platform_authenticator_result
+ return unless current_user
+ return if platform_authenticator_results_saved? || platform_authenticator_available?.nil?
+
+ session[:platform_authenticator_analytics_saved] = true
+ extra = { platform_authenticator: platform_authenticator_available? }
+ FormResponse.new(success: true, errors: {}, extra: extra)
+ end
+
+ def platform_authenticator_available?
+ @platform_authenticator_available ||= begin
+ available = params.dig(:platform_authenticator, :available)
+ available == 'true' if %w[true false].include?(available)
+ end
+ end
+
+ def platform_authenticator_results_saved?
+ session[:platform_authenticator_analytics_saved] == true
+ end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 9bd9a780fd5..0904edeefcb 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -274,24 +274,15 @@ def set_locale
I18n.locale = LocaleChooser.new(params[:locale], request).locale
end
- def sp_session_ial
- sp_session[:ial]
- end
-
- def sp_session_ial_1_or_2
- return 1 if sp_session[:ial].blank?
- sp_session[:ial] > 1 ? 2 : 1
- end
-
def increment_monthly_auth_count
return unless current_user&.id
issuer = sp_session[:issuer]
- return if issuer.blank? || !first_auth_of_session?(issuer, sp_session_ial)
- MonthlySpAuthCount.increment(current_user.id, issuer, sp_session_ial_1_or_2)
+ return if issuer.blank? || !first_auth_of_session?(issuer)
+ MonthlySpAuthCount.increment(current_user.id, issuer, sp_session[:ial2] ? 2 : 1)
end
- def first_auth_of_session?(issuer, ial)
- authenticated_to_sp_token = "auth_counted_ial#{ial}_#{issuer}"
+ def first_auth_of_session?(issuer)
+ authenticated_to_sp_token = "auth-counted-#{issuer}"
authenticated_to_sp = user_session[authenticated_to_sp_token]
return if authenticated_to_sp
user_session[authenticated_to_sp_token] = true
@@ -353,7 +344,7 @@ def analytics_exception_info(exception)
end
def add_sp_cost(token)
- Db::SpCost::AddSpCost.call(sp_session[:issuer].to_s, sp_session_ial_1_or_2, token)
+ Db::SpCost::AddSpCost.call(sp_session[:issuer].to_s, sp_session[:ial2] ? 2 : 1, token)
end
def mobile?
diff --git a/app/controllers/concerns/fully_authenticatable.rb b/app/controllers/concerns/fully_authenticatable.rb
index 3b746f8b833..bd0ce49dbcb 100644
--- a/app/controllers/concerns/fully_authenticatable.rb
+++ b/app/controllers/concerns/fully_authenticatable.rb
@@ -1,7 +1,6 @@
module FullyAuthenticatable
def delete_branded_experience
ServiceProviderRequestProxy.delete(request_id)
- session.delete(:sp)
end
def request_id
diff --git a/app/controllers/concerns/idv/document_capture_concern.rb b/app/controllers/concerns/idv/document_capture_concern.rb
deleted file mode 100644
index 1902b85fc4d..00000000000
--- a/app/controllers/concerns/idv/document_capture_concern.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-module Idv
- module DocumentCaptureConcern
- def override_document_capture_step_csp
- return if params[:step] != 'document_capture'
-
- SecureHeaders.append_content_security_policy_directives(
- request,
- # required to run wasm until wasm-eval is available
- script_src: ['\'unsafe-eval\''],
- # required for retrieving image dimensions from uploaded images
- img_src: ['blob:'],
- )
- end
- end
-end
diff --git a/app/controllers/concerns/verify_sp_attributes_concern.rb b/app/controllers/concerns/verify_sp_attributes_concern.rb
index 47b29173740..3a29feddc61 100644
--- a/app/controllers/concerns/verify_sp_attributes_concern.rb
+++ b/app/controllers/concerns/verify_sp_attributes_concern.rb
@@ -74,4 +74,8 @@ def requested_attributes_verified?
sp_session[:requested_attributes] - @sp_session_identity.verified_attributes.to_a
).empty?
end
+
+ def sp_session_ial
+ sp_session[:ial2] ? 2 : 1
+ end
end
diff --git a/app/controllers/idv/cac_controller.rb b/app/controllers/idv/cac_controller.rb
index fc19cd3b819..ae005d2edde 100644
--- a/app/controllers/idv/cac_controller.rb
+++ b/app/controllers/idv/cac_controller.rb
@@ -2,6 +2,7 @@ module Idv
class CacController < ApplicationController
include PivCacConcern
+ before_action :render_404_if_disabled
before_action :confirm_two_factor_authenticated
before_action :cac_callback
@@ -25,6 +26,10 @@ def redirect_to_piv_cac_service
private
+ def render_404_if_disabled
+ render_not_found unless AppConfig.env.cac_proofing_enabled == 'true'
+ end
+
def cac_callback
return unless request.path == idv_cac_step_path(:present_cac) && params[:token]
diff --git a/app/controllers/idv/cancellations_controller.rb b/app/controllers/idv/cancellations_controller.rb
index 95aa6690bd2..9c326347cfc 100644
--- a/app/controllers/idv/cancellations_controller.rb
+++ b/app/controllers/idv/cancellations_controller.rb
@@ -1,7 +1,6 @@
module Idv
class CancellationsController < ApplicationController
include IdvSession
- include GoBackHelper
before_action :confirm_two_factor_authenticated
before_action :confirm_idv_needed
@@ -9,7 +8,7 @@ class CancellationsController < ApplicationController
def new
properties = ParseControllerFromReferer.new(request.referer).call
analytics.track_event(Analytics::IDV_CANCELLATION, properties)
- @go_back_path = go_back_path || idv_path
+ @go_back_path = go_back_path
end
def destroy
@@ -25,5 +24,22 @@ def reset_doc_auth
user_session.delete('idv/doc_auth')
user_session['idv'] = { params: {}, step_attempts: { phone: 0 } }
end
+
+ def go_back_path
+ referer_path || idv_path
+ end
+
+ def referer_path
+ referer_string = request.env['HTTP_REFERER']
+ return if referer_string.blank?
+ referer_uri = URI.parse(referer_string)
+ return if referer_uri.scheme == 'javascript'
+ return unless referer_uri.host == AppConfig.env.domain_name
+ extract_path_and_query_from_uri(referer_uri)
+ end
+
+ def extract_path_and_query_from_uri(uri)
+ [uri.path, uri.query].compact.join('?')
+ end
end
end
diff --git a/app/controllers/idv/capture_doc_controller.rb b/app/controllers/idv/capture_doc_controller.rb
index 6d7ab0125a7..cff36b91832 100644
--- a/app/controllers/idv/capture_doc_controller.rb
+++ b/app/controllers/idv/capture_doc_controller.rb
@@ -1,11 +1,9 @@
module Idv
class CaptureDocController < ApplicationController
before_action :ensure_user_id_in_session
+ before_action :add_unsafe_eval_to_capture_steps
include Flow::FlowStateMachine
- include Idv::DocumentCaptureConcern
-
- before_action :override_document_capture_step_csp
FSM_SETTINGS = {
step_url: :idv_capture_doc_step_url,
@@ -27,6 +25,16 @@ def ensure_user_id_in_session
process_result(result)
end
+ def add_unsafe_eval_to_capture_steps
+ return unless current_step == 'document_capture'
+
+ # required to run wasm until wasm-eval is available
+ SecureHeaders.append_content_security_policy_directives(
+ request,
+ script_src: ['\'unsafe-eval\''],
+ )
+ end
+
def process_result(result)
if result.success?
reset_session
@@ -52,9 +60,5 @@ def token
def document_capture_session_uuid
params['document-capture-session']
end
-
- def analytics_user
- user_id_from_token ? User.find(user_id_from_token) : super
- end
end
end
diff --git a/app/controllers/idv/capture_doc_status_controller.rb b/app/controllers/idv/capture_doc_status_controller.rb
index 42cac305011..b73f4a71e97 100644
--- a/app/controllers/idv/capture_doc_status_controller.rb
+++ b/app/controllers/idv/capture_doc_status_controller.rb
@@ -16,9 +16,7 @@ def document_capture_session_poll_render_result
document_capture_session = DocumentCaptureSession.find_by(uuid: session_uuid)
return { plain: 'Unauthorized', status: :unauthorized } unless document_capture_session
- result = document_capture_session.load_result ||
- document_capture_session.load_doc_auth_async_result
-
+ result = document_capture_session.load_result
return { plain: 'Pending', status: :accepted } if result.blank?
return { plain: 'Unauthorized', status: :unauthorized } unless result.success?
{ plain: 'Complete', status: :ok }
diff --git a/app/controllers/idv/doc_auth_controller.rb b/app/controllers/idv/doc_auth_controller.rb
index c4a71aad335..1151587e570 100644
--- a/app/controllers/idv/doc_auth_controller.rb
+++ b/app/controllers/idv/doc_auth_controller.rb
@@ -4,12 +4,11 @@ class DocAuthController < ApplicationController
before_action :redirect_if_mail_bounced
before_action :redirect_if_pending_profile
before_action :extend_timeout_using_meta_refresh_for_select_paths
+ before_action :add_unsafe_eval_to_capture_steps
include IdvSession # remove if we retire the non docauth LOA3 flow
include Flow::FlowStateMachine
- include Idv::DocumentCaptureConcern
- before_action :override_document_capture_step_csp
before_action :update_if_skipping_upload
FSM_SETTINGS = {
@@ -50,5 +49,15 @@ def do_meta_refresh(meta_refresh_count)
def flow_session
user_session['idv/doc_auth']
end
+
+ def add_unsafe_eval_to_capture_steps
+ return unless params[:step] == 'document_capture'
+
+ # required to run wasm until wasm-eval is available
+ SecureHeaders.append_content_security_policy_directives(
+ request,
+ script_src: ['\'unsafe-eval\''],
+ )
+ end
end
end
diff --git a/app/controllers/idv/image_uploads_controller.rb b/app/controllers/idv/image_uploads_controller.rb
index e452ee771f0..a6e06a76ae6 100644
--- a/app/controllers/idv/image_uploads_controller.rb
+++ b/app/controllers/idv/image_uploads_controller.rb
@@ -5,16 +5,10 @@ class ImageUploadsController < ApplicationController
respond_to :json
def create
- image_form_response = image_form.submit
- analytics.track_event(
- Analytics::IDV_DOC_AUTH_SUBMITTED_IMAGE_UPLOAD_FORM,
- image_form_response.to_h,
- )
-
+ form_response = image_form.submit
client_response = nil
- doc_pii_form_response = nil
- if image_form_response.success?
+ if form_response.success?
client_response = doc_auth_client.post_images(
front_image: image_form.front.read,
back_image: image_form.back.read,
@@ -26,24 +20,16 @@ def create
if client_response.success?
doc_pii_form_response = Idv::DocPiiForm.new(client_response.pii_from_doc).submit
- analytics.track_event(
- Analytics::IDV_DOC_AUTH_SUBMITTED_PII_VALIDATION,
- doc_pii_form_response.to_h.merge(user_id: user_uuid),
- )
+ form_response = form_response.merge(doc_pii_form_response)
store_pii(client_response) if client_response.success? && doc_pii_form_response.success?
-
- # merge in the image_form_response to pick up the remaining_attempts
- doc_pii_form_response = image_form_response.merge(doc_pii_form_response)
end
end
+ analytics.track_event(Analytics::IDV_DOC_AUTH_SUBMITTED_IMAGE_UPLOAD_FORM, form_response.to_h)
+
presenter = ImageUploadResponsePresenter.new(
form: image_form,
- form_response: presenter_response(
- image_form_response: image_form_response,
- client_response: client_response,
- doc_pii_form_response: doc_pii_form_response,
- ),
+ form_response: presenter_response(form_response, client_response),
url_options: url_options,
)
@@ -72,7 +58,7 @@ def update_analytics(client_response)
update_funnel(client_response)
analytics.track_event(
Analytics::IDV_DOC_AUTH_SUBMITTED_IMAGE_UPLOAD_VENDOR,
- client_response.to_h.merge(user_id: user_uuid),
+ client_response.to_h.merge(user_id: image_form.document_capture_session.user.uuid),
)
end
@@ -94,20 +80,9 @@ def add_costs(client_response)
call(client_response)
end
- def presenter_response(image_form_response:, client_response:, doc_pii_form_response:)
- # image form wasn't valid
- return image_form_response unless image_form_response.success?
-
- # doc_pii_form exists, but wasn't valid
- if doc_pii_form_response.present? && !doc_pii_form_response.success?
- return doc_pii_form_response
- end
-
- client_response
- end
-
- def user_uuid
- image_form.document_capture_session.user.uuid
+ def presenter_response(form_response, client_response)
+ return client_response if form_response.success? && client_response.present?
+ form_response
end
end
end
diff --git a/app/controllers/idv_controller.rb b/app/controllers/idv_controller.rb
index 0018113c4bd..421e3f325f6 100644
--- a/app/controllers/idv_controller.rb
+++ b/app/controllers/idv_controller.rb
@@ -61,7 +61,8 @@ def active_profile?
end
def proof_with_cac?
- Db::EmailAddress::HasGovOrMil.call(current_user) ||
- current_user.piv_cac_configurations.any?
+ AppConfig.env.cac_proofing_enabled == 'true' &&
+ (Db::EmailAddress::HasGovOrMil.call(current_user) ||
+ current_user.piv_cac_configurations.any?)
end
end
diff --git a/app/controllers/openid_connect/authorization_controller.rb b/app/controllers/openid_connect/authorization_controller.rb
index 946501f888f..34cad9a6011 100644
--- a/app/controllers/openid_connect/authorization_controller.rb
+++ b/app/controllers/openid_connect/authorization_controller.rb
@@ -32,7 +32,7 @@ def check_sp_active
end
def check_sp_handoff_bounced
- return unless SpHandoffBounce.is_bounced?(session)
+ return unless SpHandoffBounce::IsBounced.call(sp_session)
analytics.track_event(Analytics::SP_HANDOFF_BOUNCED_DETECTED)
redirect_to bounced_url
true
@@ -56,7 +56,7 @@ def link_identity_to_service_provider
def handle_successful_handoff
track_events
- SpHandoffBounce.add_handoff_time_to_session(session)
+ SpHandoffBounce::AddHandoffTimeToSession.call(sp_session)
redirect_to @authorize_form.success_redirect_uri
delete_branded_experience
end
@@ -130,13 +130,15 @@ def store_request
end
def pii_requested_but_locked?
- sp_session && sp_session_ial > 1 &&
+ FeatureManagement.allow_piv_cac_login? &&
+ sp_session && sp_session_ial > 1 &&
UserDecorator.new(current_user).identity_verified? &&
user_session[:decrypted_pii].blank?
end
def track_events
- analytics.track_event(Analytics::SP_REDIRECT_INITIATED, ial: sp_session_ial)
+ ial = sp_session[:ial2] ? 2 : 1
+ analytics.track_event(Analytics::SP_REDIRECT_INITIATED, ial: ial)
Db::SpReturnLog::AddReturn.call(request_id, current_user.id)
increment_monthly_auth_count
add_sp_cost(:authentication)
diff --git a/app/controllers/openid_connect/logout_controller.rb b/app/controllers/openid_connect/logout_controller.rb
index f4cdc83e21e..fadd49041bc 100644
--- a/app/controllers/openid_connect/logout_controller.rb
+++ b/app/controllers/openid_connect/logout_controller.rb
@@ -1,5 +1,8 @@
module OpenidConnect
class LogoutController < ApplicationController
+ include SecureHeadersConcern
+
+ before_action :apply_secure_headers_override, only: [:index]
def index
@logout_form = OpenidConnectLogoutForm.new(params)
diff --git a/app/controllers/saml_idp_controller.rb b/app/controllers/saml_idp_controller.rb
index 9c519bcbcf5..c6818c74526 100644
--- a/app/controllers/saml_idp_controller.rb
+++ b/app/controllers/saml_idp_controller.rb
@@ -102,7 +102,8 @@ def render_template_for(message, action_url, type)
end
def track_events
- analytics.track_event(Analytics::SP_REDIRECT_INITIATED, ial: sp_session_ial)
+ ial = sp_session[:ial2] ? 2 : 1
+ analytics.track_event(Analytics::SP_REDIRECT_INITIATED, ial: ial)
Db::SpReturnLog::AddReturn.call(request_id, current_user.id)
increment_monthly_auth_count
add_sp_cost(:authentication)
diff --git a/app/controllers/users/piv_cac_login_controller.rb b/app/controllers/users/piv_cac_login_controller.rb
index 8a6ea0d2c8b..ee04cabb181 100644
--- a/app/controllers/users/piv_cac_login_controller.rb
+++ b/app/controllers/users/piv_cac_login_controller.rb
@@ -85,7 +85,7 @@ def request_is_ial2?
end
def request_ial
- sp_session ? sp_session_ial_1_or_2 : 1
+ sp_session ? sp_session_ial : 1
end
def process_invalid_submission
diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb
index a52892c9bc2..29d42b344b6 100644
--- a/app/controllers/users/sessions_controller.rb
+++ b/app/controllers/users/sessions_controller.rb
@@ -21,7 +21,7 @@ def new
)
@request_id = request_id_if_valid
- @ial = sp_session ? sp_session_ial_1_or_2 : 1
+ @ial = sp_session ? sp_session_ial : 1
session[:ial2_with_no_sp_campaign] = campaign if sp_session.blank? && params[:ial] == '2'
super
end
@@ -173,6 +173,10 @@ def request_id
params.fetch(:request_id, '')
end
+ def sp_session_ial
+ sp_session[:ial2] ? 2 : 1
+ end
+
def redirect_to_2fa_or_pending_reset
if pending_account_reset_request.present?
redirect_to account_reset_pending_url
diff --git a/app/helpers/go_back_helper.rb b/app/helpers/go_back_helper.rb
deleted file mode 100644
index bc8b149643f..00000000000
--- a/app/helpers/go_back_helper.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-module GoBackHelper
- def go_back_path
- referer_string = request.referer
- return if referer_string.blank?
- referer_uri = URI.parse(referer_string)
- return if referer_uri.scheme == 'javascript'
- return unless referer_uri.host == app_host
- extract_path_and_query_from_uri(referer_uri)
- end
-
- private
-
- def extract_path_and_query_from_uri(uri)
- [uri.path, uri.query].compact.join('?')
- end
-
- def app_host
- AppConfig.env.domain_name.split(':')[0]
- end
-end
-
-ActionView::Base.send :include, GoBackHelper
diff --git a/app/helpers/session_timeout_warning_helper.rb b/app/helpers/session_timeout_warning_helper.rb
index 395a20405e1..1dae0a8e7d0 100644
--- a/app/helpers/session_timeout_warning_helper.rb
+++ b/app/helpers/session_timeout_warning_helper.rb
@@ -1,13 +1,13 @@
module SessionTimeoutWarningHelper
- def session_timeout_frequency
+ def frequency
(AppConfig.env.session_check_frequency || 150).to_i
end
- def session_timeout_start
+ def start
(AppConfig.env.session_check_delay || 30).to_i
end
- def session_timeout_warning
+ def warning
(AppConfig.env.session_timeout_warning_seconds || 30).to_i
end
@@ -18,15 +18,44 @@ def timeout_refresh_path
)&.html_safe # rubocop:disable Rails/OutputSafety
end
+ def auto_session_timeout_js
+ nonced_javascript_tag do
+ render partial: 'session_timeout/ping',
+ formats: [:js],
+ locals: {
+ timeout_url: timeout_url,
+ warning: warning,
+ start: start,
+ frequency: frequency,
+ modal: modal,
+ }
+ end
+ end
+
+ # rubocop:disable Rails/HelperInstanceVariable
+ def auto_session_expired_js
+ return if @skip_session_expiration
+
+ session_timeout_in = Devise.timeout_in
+ nonced_javascript_tag do
+ render(
+ partial: 'session_timeout/expire_session',
+ formats: [:js],
+ locals: { session_timeout_in: session_timeout_in },
+ )
+ end
+ end
+ # rubocop:enable Rails/HelperInstanceVariable
+
def time_left_in_session
distance_of_time_in_words(
- session_timeout_warning,
+ warning,
0,
two_words_connector: " #{I18n.t('datetime.dotiw.two_words_connector')} ",
)
end
- def session_modal
+ def modal
if user_fully_authenticated?
FullySignedInModalPresenter.new(time_left_in_session)
else
@@ -34,3 +63,5 @@ def session_modal
end
end
end
+
+ActionView::Base.send :include, SessionTimeoutWarningHelper
diff --git a/app/javascript/app/platform-authenticator.js b/app/javascript/app/platform-authenticator.js
new file mode 100644
index 00000000000..5cf9657e364
--- /dev/null
+++ b/app/javascript/app/platform-authenticator.js
@@ -0,0 +1,20 @@
+function postPlatformAuthenticator(userIntent) {
+ const xhr = new XMLHttpRequest();
+ xhr.open('POST', '/analytics', true);
+ xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+ xhr.send(`platform_authenticator[available]=${userIntent}`);
+}
+function platformAuthenticator() {
+ if (document.querySelector('[data-platform-authenticator-enabled]')) {
+ if (!window.PublicKeyCredential) {
+ postPlatformAuthenticator(false);
+ return;
+ }
+ window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().then(function (
+ userIntent,
+ ) {
+ postPlatformAuthenticator(userIntent);
+ });
+ }
+}
+document.addEventListener('DOMContentLoaded', platformAuthenticator);
diff --git a/app/javascript/packages/document-capture/components/acuant-capture.jsx b/app/javascript/packages/document-capture/components/acuant-capture.jsx
index 1bf5badbf2e..698cbb9bf24 100644
--- a/app/javascript/packages/document-capture/components/acuant-capture.jsx
+++ b/app/javascript/packages/document-capture/components/acuant-capture.jsx
@@ -32,14 +32,14 @@ import './acuant-capture.scss';
*/
/**
- * @typedef {"acuant"|"upload"} ImageSource
+ * @typedef {"acuant"} ImageSource
*/
/**
* @typedef ImageAnalyticsPayload
*
- * @prop {number?} width Image width, or null if unknown.
- * @prop {number?} height Image height, or null if unknown.
+ * @prop {number} width
+ * @prop {number} height
* @prop {string?} mimeType Mime type, or null if unknown.
* @prop {ImageSource} source Method by which image was added.
*/
@@ -125,27 +125,6 @@ function getDocumentTypeLabel(documentType) {
}
}
-/**
- * @param {File} file Image file.
- *
- * @return {Promise<{width: number?, height: number?}>}
- */
-function getImageDimensions(file) {
- let objectURL;
- return file.type.indexOf('image/') === 0
- ? new Promise((resolve) => {
- objectURL = window.URL.createObjectURL(file);
- const image = new window.Image();
- image.onload = () => resolve({ width: image.width, height: image.height });
- image.onerror = () => resolve({ width: null, height: null });
- image.src = objectURL;
- }).then(({ width, height }) => {
- window.URL.revokeObjectURL(objectURL);
- return { width, height };
- })
- : Promise.resolve({ width: null, height: null });
-}
-
/**
* Returns an element serving as an enhanced FileInput, supporting direct capture using Acuant SDK
* in supported devices.
@@ -166,7 +145,7 @@ function AcuantCapture(
},
ref,
) {
- const { isReady, isAcuantLoaded, isError, isCameraSupported } = useContext(AcuantContext);
+ const { isReady, isError, isCameraSupported } = useContext(AcuantContext);
const { isMockClient } = useContext(UploadContext);
const { addPageAction } = useContext(AnalyticsContext);
const inputRef = useRef(/** @type {?HTMLInputElement} */ (null));
@@ -198,32 +177,6 @@ function AcuantCapture(
onChange(nextValue);
}
- /**
- * Handler for file input change events.
- *
- * @param {File?} nextValue Next value, if set.
- */
- function onUpload(nextValue) {
- if (nextValue) {
- getImageDimensions(nextValue).then(({ width, height }) => {
- /** @type {ImageAnalyticsPayload} */
- const analyticsPayload = {
- width,
- height,
- mimeType: nextValue.type,
- source: 'upload',
- };
-
- addPageAction({
- label: `IdV: ${analyticsPrefix} added`,
- payload: analyticsPayload,
- });
- });
- }
-
- onChangeAndResetError(nextValue);
- }
-
/**
* Responds to a click by starting capture if supported in the environment, or triggering the
* default file picker prompt. The click event may originate from the file input itself, or
@@ -235,8 +188,7 @@ function AcuantCapture(
if (event.target === inputRef.current) {
const shouldStartEnvironmentCapture =
hasCapture && capture !== 'user' && !isForceUploading.current;
- const shouldStartSelfieCapture =
- isAcuantLoaded && capture === 'user' && !isForceUploading.current;
+ const shouldStartSelfieCapture = capture === 'user' && !isForceUploading.current;
if (!allowUpload || shouldStartSelfieCapture || shouldStartEnvironmentCapture) {
event.preventDefault();
@@ -357,7 +309,7 @@ function AcuantCapture(
value={value}
errorMessage={ownErrorMessage ?? errorMessage}
onClick={startCaptureOrTriggerUpload}
- onChange={onUpload}
+ onChange={onChangeAndResetError}
onError={() => setOwnErrorMessage(null)}
/>
diff --git a/app/javascript/packages/document-capture/components/file-input.jsx b/app/javascript/packages/document-capture/components/file-input.jsx
index b798f43db10..08c96cb5340 100644
--- a/app/javascript/packages/document-capture/components/file-input.jsx
+++ b/app/javascript/packages/document-capture/components/file-input.jsx
@@ -23,7 +23,7 @@ import usePrevious from '../hooks/use-previous';
* @prop {Blob|string|null|undefined} value Current value.
* @prop {ReactNode=} errorMessage Error to show.
* @prop {(event:ReactMouseEvent)=>void=} onClick Input click handler.
- * @prop {(nextValue:File?)=>void=} onChange Input change handler.
+ * @prop {(nextValue:Blob?)=>void=} onChange Input change handler.
* @prop {(message:ReactNode)=>void=} onError Callback to trigger if upload error occurs.
*/
diff --git a/app/javascript/packages/document-capture/context/acuant.jsx b/app/javascript/packages/document-capture/context/acuant.jsx
index 94fc7a9dba7..c5932ed02d5 100644
--- a/app/javascript/packages/document-capture/context/acuant.jsx
+++ b/app/javascript/packages/document-capture/context/acuant.jsx
@@ -1,5 +1,4 @@
-import { createContext, useContext, useMemo, useEffect, useState } from 'react';
-import DeviceContext from './device';
+import { createContext, useMemo, useEffect, useState } from 'react';
/** @typedef {import('react').ReactNode} ReactNode */
@@ -49,7 +48,6 @@ import DeviceContext from './device';
const AcuantContext = createContext({
isReady: false,
- isAcuantLoaded: false,
isError: false,
isCameraSupported: /** @type {boolean?} */ (null),
credentials: /** @type {string?} */ (null),
@@ -65,26 +63,18 @@ function AcuantContextProvider({
endpoint = null,
children,
}) {
- const { isMobile } = useContext(DeviceContext);
- // Only mobile devices should load the Acuant SDK. Consider immediately ready otherwise.
- const [isReady, setIsReady] = useState(!isMobile);
- const [isAcuantLoaded, setIsAcuantLoaded] = useState(false);
+ const [isReady, setIsReady] = useState(false);
const [isError, setIsError] = useState(false);
- // If the user is on a mobile device, it can't be known that the camera is supported until after
- // Acuant SDK loads, so assign a value of `null` as representing this unknown state. Other device
- // types should treat camera as unsupported, since it's not relevant for Acuant SDK usage.
- const [isCameraSupported, setIsCameraSupported] = useState(isMobile ? null : false);
- const value = useMemo(
- () => ({ isReady, isAcuantLoaded, isError, isCameraSupported, endpoint, credentials }),
- [isReady, isAcuantLoaded, isError, isCameraSupported, endpoint, credentials],
- );
+ const [isCameraSupported, setIsCameraSupported] = useState(/** @type {?boolean} */ (null));
+ const value = useMemo(() => ({ isReady, isError, isCameraSupported, endpoint, credentials }), [
+ isReady,
+ isError,
+ isCameraSupported,
+ endpoint,
+ credentials,
+ ]);
useEffect(() => {
- // If state is already ready (via consideration of device type), skip loading Acuant SDK.
- if (isReady) {
- return;
- }
-
// Acuant SDK expects this global to be assigned at the time the script is
// loaded, which is why the script element is manually appended to the DOM.
const originalOnAcuantSdkLoaded = /** @type {AcuantGlobal} */ (window).onAcuantSdkLoaded;
@@ -98,7 +88,6 @@ function AcuantContextProvider({
/** @type {AcuantGlobal} */ (window).AcuantCamera.isCameraSupported,
);
setIsReady(true);
- setIsAcuantLoaded(true);
},
onFail: () => setIsError(true),
},
diff --git a/app/javascript/packages/document-capture/context/analytics.jsx b/app/javascript/packages/document-capture/context/analytics.jsx
index bdd3b446883..1f07f854f92 100644
--- a/app/javascript/packages/document-capture/context/analytics.jsx
+++ b/app/javascript/packages/document-capture/context/analytics.jsx
@@ -5,7 +5,7 @@ import { createContext } from 'react';
/**
* @typedef PageAction
*
- * @property {string=} key Short, camel-cased, dot-namespaced key describing event.
+ * @property {string} key Short, camel-cased, dot-namespaced key describing event.
* @property {string} label Long-form, human-readable label describing event action.
* @property {Payload} payload Additional payload arguments to log with action.
*/
diff --git a/app/javascript/packages/document-capture/higher-order/with-background-encrypted-upload.jsx b/app/javascript/packages/document-capture/higher-order/with-background-encrypted-upload.jsx
index ef8f4d2e6e3..a99869e1875 100644
--- a/app/javascript/packages/document-capture/higher-order/with-background-encrypted-upload.jsx
+++ b/app/javascript/packages/document-capture/higher-order/with-background-encrypted-upload.jsx
@@ -3,17 +3,17 @@ import UploadContext from '../context/upload';
import AnalyticsContext from '../context/analytics';
/**
- * Returns a promise resolving to an ArrayBuffer representation of the given Blob object.
+ * Returns a promise resolving to an DataView representation of the given Blob object.
*
* @param {Blob} blob Blob object.
*
- * @return {Promise
}
+ * @return {Promise}
*/
-export function blobToArrayBuffer(blob) {
+export function blobToDataView(blob) {
return new Promise((resolve, reject) => {
const reader = new window.FileReader();
reader.onload = ({ target }) => {
- resolve(/** @type {ArrayBuffer} */ (target?.result));
+ resolve(new DataView(/** @type {ArrayBuffer} */ (target?.result)));
};
reader.onerror = () => reject(reader.error);
reader.readAsArrayBuffer(blob);
@@ -31,15 +31,12 @@ export function blobToArrayBuffer(blob) {
*/
export async function encrypt(key, iv, value) {
const data =
- typeof value === 'string' ? new TextEncoder().encode(value) : await blobToArrayBuffer(value);
+ typeof value === 'string' ? new TextEncoder().encode(value) : await blobToDataView(value);
return window.crypto.subtle.encrypt(
/** @type {AesGcmParams} */ ({
name: 'AES-GCM',
iv,
- // Normally, it would not be expected to assign this value, since the property is optional and
- // the default is 128. However, if not specified, Internet Explorer will throw an error.
- tagLength: 128,
}),
key,
data,
diff --git a/app/javascript/packages/polyfill/index.js b/app/javascript/packages/polyfill/index.js
index a7b97185da1..cb0e7d1241f 100644
--- a/app/javascript/packages/polyfill/index.js
+++ b/app/javascript/packages/polyfill/index.js
@@ -6,17 +6,21 @@
*/
/**
- * @typedef {"fetch"|"classlist"|"crypto"|"custom-event"} SupportedPolyfills
+ * @typedef {"fetch"|"element-closest"|"classlist"|"crypto"|"custom-event"} SupportedPolyfills
*/
/**
- * @type {Record}
+ * @type {Record}
*/
const POLYFILLS = {
fetch: {
test: () => 'fetch' in window,
load: () => import(/* webpackChunkName: "whatwg-fetch" */ 'whatwg-fetch'),
},
+ 'element-closest': {
+ test: () => !!Element.prototype.closest,
+ load: () => import(/* webpackChunkName: "element-closest" */ 'element-closest'),
+ },
classlist: {
test: () => 'classList' in Element.prototype,
load: () => import(/* webpackChunkName: "classlist-polyfill" */ 'classlist-polyfill'),
diff --git a/app/javascript/packages/polyfill/package.json b/app/javascript/packages/polyfill/package.json
index 482a09301af..2058b332186 100644
--- a/app/javascript/packages/polyfill/package.json
+++ b/app/javascript/packages/polyfill/package.json
@@ -5,6 +5,7 @@
"dependencies": {
"classlist-polyfill": "^1.2.0",
"custom-event-polyfill": "^1.0.7",
+ "element-closest": "^3.0.2",
"webcrypto-shim": "^0.1.6",
"whatwg-fetch": "^3.4.0"
}
diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js
index c8e98e128a0..b3ecb14e07d 100644
--- a/app/javascript/packs/application.js
+++ b/app/javascript/packs/application.js
@@ -6,5 +6,6 @@ require('../app/form-field-format');
require('../app/radio-btn');
require('../app/print-personal-key');
require('../app/i18n-dropdown');
+require('../app/platform-authenticator');
require('../app/accessible-forms');
require('../app/ssn-field');
diff --git a/app/javascript/packs/document-capture.jsx b/app/javascript/packs/document-capture.jsx
index 97f23f90b2a..7057b1b03ec 100644
--- a/app/javascript/packs/document-capture.jsx
+++ b/app/javascript/packs/document-capture.jsx
@@ -98,10 +98,7 @@ const device = {
/** @type {import('@18f/identity-document-capture/context/analytics').AddPageAction} */
function addPageAction(action) {
- const { newrelic } = /** @type {DocumentCaptureGlobal} */ (window);
- if (action.key && newrelic) {
- newrelic.addPageAction(action.key, action.payload);
- }
+ /** @type {DocumentCaptureGlobal} */ (window).newrelic?.addPageAction(action.key, action.payload);
window.fetch(logEndpoint, {
method: 'POST',
@@ -140,36 +137,36 @@ loadPolyfills(['fetch', 'crypto']).then(async () => {
window.fetch(keepAliveEndpoint, { method: 'POST', headers: { 'X-CSRF-Token': csrf } });
render(
-
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+ ,
appRoot,
);
});
diff --git a/app/javascript/packs/ial2-consent-button.js b/app/javascript/packs/ial2-consent-button.js
index b02bd76855c..d237407e2eb 100644
--- a/app/javascript/packs/ial2-consent-button.js
+++ b/app/javascript/packs/ial2-consent-button.js
@@ -1,9 +1,10 @@
function toggleButton() {
- const continueButton = document.querySelector('button[type="submit"]');
+ const continueButton = document.querySelector('input[value="Continue"]');
const checkbox = document.querySelector('input[name="ial2_consent_given"]');
function sync() {
- continueButton.classList.toggle('btn-disabled', !checkbox.checked);
+ continueButton.disabled = !checkbox.checked;
+ continueButton.classList.toggle('btn-disabled', continueButton.disabled);
}
sync();
diff --git a/app/javascript/packs/session-expire-session.js b/app/javascript/packs/session-expire-session.js
deleted file mode 100644
index e92090085cd..00000000000
--- a/app/javascript/packs/session-expire-session.js
+++ /dev/null
@@ -1,10 +0,0 @@
-const expireConfig = document.getElementById('js-expire-session');
-
-if (expireConfig && expireConfig.dataset.sessionTimeoutIn) {
- const sessionTimeoutIn = parseInt(expireConfig.dataset.sessionTimeoutIn, 10) * 1000;
- const timeoutRefreshPath = expireConfig.dataset.timeoutRefreshPath || '';
-
- setTimeout(() => {
- document.location.href = timeoutRefreshPath;
- }, sessionTimeoutIn);
-}
diff --git a/app/javascript/packs/session-timeout-ping.js b/app/javascript/packs/session-timeout-ping.js
deleted file mode 100644
index fe705f4153c..00000000000
--- a/app/javascript/packs/session-timeout-ping.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- * @typedef NewRelicAgent
- *
- * @prop {(name:string,attributes:object)=>void} addPageAction Log page action to New Relic.
- */
-
-/**
- * @typedef LoginGov
- *
- * @prop {(any)=>void} Modal
- * @prop {(string)=>void} autoLogout
- * @prop {(el:HTMLElement?,timeLeft:number,endTime:number,interval?:number)=>void} countdownTimer
- */
-
-/**
- * @typedef NewRelicGlobals
- *
- * @prop {NewRelicAgent=} newrelic New Relic agent.
- */
-
-/**
- * @typedef LoginGovGlobals
- *
- * @prop {LoginGov} LoginGov
- */
-
-/**
- * @typedef {typeof window & NewRelicGlobals & LoginGovGlobals} LoginGovGlobal
- */
-
-const login = /** @type {LoginGovGlobal} */ (window).LoginGov;
-
-const warningEl = document.getElementById('session-timeout-cntnr');
-
-const defaultTime = '60';
-
-const frequency = parseInt(warningEl?.dataset.frequency || defaultTime, 10) * 1000;
-const warning = parseInt(warningEl?.dataset.warning || defaultTime, 10) * 1000;
-const start = parseInt(warningEl?.dataset.start || defaultTime, 10) * 1000;
-const timeoutUrl = warningEl?.dataset.timeoutUrl;
-const warningInfo = warningEl?.dataset.warningInfoHtml || '';
-warningEl?.insertAdjacentHTML('afterbegin', warningInfo);
-const initialTime = new Date();
-
-const modal = new login.Modal({ el: '#session-timeout-msg' });
-const keepaliveEl = document.getElementById('session-keepalive-btn');
-/** @type {HTMLMetaElement?} */
-const csrfEl = document.querySelector('meta[name="csrf-token"]');
-
-let csrfToken = '';
-if (csrfEl) {
- csrfToken = csrfEl.content;
-}
-
-let countdownInterval;
-
-function notifyNewRelic(request, error, actionName) {
- /** @type {LoginGovGlobal} */ (window).newrelic?.addPageAction('Session Ping Error', {
- action_name: actionName,
- request_status: request.status,
- time_elapsed_ms: new Date().valueOf() - initialTime.valueOf(),
- error: error.message,
- });
-}
-
-function success(data) {
- let timeRemaining = data.remaining * 1000;
- const timeTimeout = new Date().getTime() + timeRemaining;
- const showWarning = timeRemaining < warning;
-
- if (!data.live) {
- login.autoLogout(timeoutUrl);
- return;
- }
-
- if (showWarning && !modal.shown) {
- modal.show();
-
- if (countdownInterval) {
- clearInterval(countdownInterval);
- }
- countdownInterval = login.countdownTimer(
- document.getElementById('countdown'),
- timeRemaining,
- timeTimeout,
- );
- }
-
- if (!showWarning && modal.shown) {
- modal.hide();
- }
-
- if (timeRemaining < frequency) {
- timeRemaining = timeRemaining < 0 ? 0 : timeRemaining;
- // Disable reason: circular dependency between ping and success
- // eslint-disable-next-line no-use-before-define
- setTimeout(ping, timeRemaining);
- }
-}
-
-function ping() {
- const request = new XMLHttpRequest();
- request.open('GET', '/active', true);
-
- request.onload = function () {
- try {
- success(JSON.parse(request.responseText));
- } catch (error) {
- notifyNewRelic(request, error, 'ping');
- }
- };
-
- request.send();
- setTimeout(ping, frequency);
-}
-
-function keepalive() {
- const request = new XMLHttpRequest();
- request.open('POST', '/sessions/keepalive', true);
- request.setRequestHeader('X-CSRF-Token', csrfToken);
-
- request.onload = function () {
- try {
- success(JSON.parse(request.responseText));
- modal.hide();
- } catch (error) {
- notifyNewRelic(request, error, 'keepalive');
- }
- };
-
- request.send();
-}
-
-keepaliveEl?.addEventListener('click', keepalive, false);
-setTimeout(ping, start);
diff --git a/app/javascript/packs/submit-with-spinner.js b/app/javascript/packs/submit-with-spinner.js
new file mode 100644
index 00000000000..9eca956cc3f
--- /dev/null
+++ b/app/javascript/packs/submit-with-spinner.js
@@ -0,0 +1,8 @@
+import { loadPolyfills } from '@18f/identity-polyfill';
+
+loadPolyfills(['element-closest']).then(() => {
+ const spinner = /** @type {HTMLDivElement} */ (document.getElementById('submit-spinner'));
+ spinner.closest('form')?.addEventListener('submit', () => {
+ spinner.className = '';
+ });
+});
diff --git a/app/models/agency.rb b/app/models/agency.rb
index a8f67ad49bd..58f99e1ec9a 100644
--- a/app/models/agency.rb
+++ b/app/models/agency.rb
@@ -4,5 +4,4 @@ class Agency < ApplicationRecord
has_many :service_providers, inverse_of: :agency
# rubocop:enable Rails/HasManyOrHasOneDependent
validates :name, presence: true
- validates :abbreviation, uniqueness: { case_sensitive: false, allow_nil: true }
end
diff --git a/app/models/letter_requests_to_usps_ftp_log.rb b/app/models/letter_requests_to_usps_ftp_log.rb
deleted file mode 100644
index 17a163e0d74..00000000000
--- a/app/models/letter_requests_to_usps_ftp_log.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-class LetterRequestsToUspsFtpLog < ApplicationRecord
- validates :ftp_at, presence: true
- validates :letter_requests_count, presence: true
-end
diff --git a/app/models/null_service_provider.rb b/app/models/null_service_provider.rb
index 2f96ee7eb19..1ed8e41613c 100644
--- a/app/models/null_service_provider.rb
+++ b/app/models/null_service_provider.rb
@@ -26,7 +26,6 @@ class NullServiceProvider
iaa_start_date
ial2_quota
id
- identities
launch_date
logo
metadata_url
@@ -73,10 +72,6 @@ def redirect_uris
[]
end
- def identities
- []
- end
-
def liveness_checking_required
false
end
diff --git a/app/models/service_provider.rb b/app/models/service_provider.rb
index a8fb68c0f8e..27700151df5 100644
--- a/app/models/service_provider.rb
+++ b/app/models/service_provider.rb
@@ -6,12 +6,6 @@ class ServiceProvider < ApplicationRecord
belongs_to :agency
- # rubocop:disable Rails/HasManyOrHasOneDependent
- has_many :identities, inverse_of: :service_provider_record,
- foreign_key: 'service_provider',
- primary_key: 'issuer'
- # rubocop:enable Rails/HasManyOrHasOneDependent
-
# Do not define validations in this model.
# See https://github.com/18F/identity_validations
include IdentityValidations::ServiceProviderValidation
diff --git a/app/presenters/cancellation_presenter.rb b/app/presenters/cancellation_presenter.rb
index 56fc839bbe3..5117f48adab 100644
--- a/app/presenters/cancellation_presenter.rb
+++ b/app/presenters/cancellation_presenter.rb
@@ -23,7 +23,6 @@ def cancellation_warnings
t('users.delete.bullet_1', app: APP_NAME),
t('users.delete.bullet_2_loa1'),
t('users.delete.bullet_3', app: APP_NAME),
- t('users.delete.bullet_4', app: APP_NAME),
]
end
diff --git a/app/presenters/idv/usps_presenter.rb b/app/presenters/idv/usps_presenter.rb
index 8d7807adfd5..9cc3162cfc8 100644
--- a/app/presenters/idv/usps_presenter.rb
+++ b/app/presenters/idv/usps_presenter.rb
@@ -14,7 +14,7 @@ def title
end
def byline
- if usps_mail_bounced?
+ if current_user.decorate.usps_mail_bounced?
I18n.t('idv.messages.usps.new_address')
else
I18n.t('idv.messages.usps.address_on_file')
@@ -25,8 +25,10 @@ def button
letter_already_sent? ? I18n.t('idv.buttons.mail.resend') : I18n.t('idv.buttons.mail.send')
end
- def fallback_back_path
- user_needs_address_otp_verification? ? verify_account_path : idv_phone_path
+ def cancel_path
+ return verify_account_path if user_needs_address_otp_verification?
+
+ idv_cancel_path
end
def usps_mail_bounced?
diff --git a/app/services/agency_seeder.rb b/app/services/agency_seeder.rb
index 5c6259349f2..4dd5cf9e99a 100644
--- a/app/services/agency_seeder.rb
+++ b/app/services/agency_seeder.rb
@@ -13,6 +13,7 @@ def initialize(
def run
agencies.each do |agency_id, config|
agency = Agency.find_by(id: agency_id)
+ config.delete('abbreviation')
if agency
agency.update!(config)
else
diff --git a/app/services/analytics.rb b/app/services/analytics.rb
index 4107e3b1b6b..5a5e2954c4d 100644
--- a/app/services/analytics.rb
+++ b/app/services/analytics.rb
@@ -84,6 +84,7 @@ def browser_attributes
CAPTURE_DOC = 'Capture Doc'.freeze # visited or submitted is appended
DOC_AUTH = 'Doc Auth'.freeze # visited or submitted is appended
DOC_AUTH_ASYNC = 'Doc Auth Async'.freeze
+ IN_PERSON_PROOFING = 'In Person Proofing'.freeze # visited or submitted is appended
EMAIL_AND_PASSWORD_AUTH = 'Email and Password Authentication'.freeze
EMAIL_DELETION_REQUEST = 'Email Deletion Requested'.freeze
EMAIL_LANGUAGE_VISITED = 'Email Language: Visited'.freeze
@@ -95,6 +96,7 @@ def browser_attributes
EXPIRED_LETTERS = 'Expired Letters'.freeze
FORGET_ALL_BROWSERS_SUBMITTED = 'Forget All Browsers Submitted'.freeze
FORGET_ALL_BROWSERS_VISITED = 'Forget All Browsers Visited'.freeze
+ FRONTEND_BROWSER_CAPABILITIES = 'Frontend: Browser capabilities'.freeze
IAL2_RECOVERY = 'IAL2 Recovery'.freeze # visited or submitted is appended
IAL2_RECOVERY_REQUEST = 'IAL2 Recovery Request'.freeze
IAL2_RECOVERY_REQUEST_VISITED = 'IAL2 Recovery Request Visited'.freeze
@@ -108,7 +110,6 @@ def browser_attributes
IDV_COME_BACK_LATER_VISIT = 'IdV: come back later visited'.freeze
IDV_DOC_AUTH_SUBMITTED_IMAGE_UPLOAD_FORM = 'IdV: doc auth image upload form submitted'.freeze
IDV_DOC_AUTH_SUBMITTED_IMAGE_UPLOAD_VENDOR = 'IdV: doc auth image upload vendor submitted'.freeze
- IDV_DOC_AUTH_SUBMITTED_PII_VALIDATION = 'IdV: doc auth image upload vendor pii validation'.freeze
IDV_MAX_ATTEMPTS_EXCEEDED = 'IdV: max attempts exceeded'.freeze
IDV_FINAL = 'IdV: final resolution'.freeze
IDV_FORGOT_PASSWORD = 'IdV: forgot password visited'.freeze
@@ -135,7 +136,6 @@ def browser_attributes
IDV_USPS_ADDRESS_VISITED = 'IdV: USPS address visited'.freeze
IDV_VERIFICATION_ATTEMPT_CANCELLED = 'IdV: verification attempt cancelled'.freeze
INVALID_AUTHENTICITY_TOKEN = 'Invalid Authenticity Token'.freeze
- IN_PERSON_PROOFING = 'In Person Proofing'.freeze # visited or submitted is appended
LAMBDA_RESULT_RESOLUTION_PROOF_RESULT = 'Lambda Resolution Proof Result Received'.freeze
LAMBDA_RESULT_ADDRESS_PROOF_RESULT = 'Lambda Address Proof Result Received'.freeze
LAMBDA_RESULT_DOCUMENT_PROOF_RESULT = 'Lambda Document Proof Result Received'.freeze
diff --git a/app/services/data_requests/write_cloudwatch_logs.rb b/app/services/data_requests/write_cloudwatch_logs.rb
index 801ea944f8e..486d77c8a58 100644
--- a/app/services/data_requests/write_cloudwatch_logs.rb
+++ b/app/services/data_requests/write_cloudwatch_logs.rb
@@ -5,7 +5,6 @@ class WriteCloudwatchLogs
event_name
success
multi_factor_auth_method
- multi_factor_id
service_provider
ip_address
user_agent
@@ -19,17 +18,23 @@ def initialize(cloudwatch_results, output_dir)
end
def call
- CSV.open(File.join(output_dir, 'logs.csv'), 'w') do |csv|
- csv << HEADERS
- cloudwatch_results.each do |row|
- csv << build_row(row)
- end
+ output_file.puts(HEADERS.join(','))
+ cloudwatch_results.each do |row|
+ write_row(row)
end
+ output_file.close
end
private
- def build_row(row)
+ def output_file
+ @output_file ||= begin
+ output_path = File.join(output_dir, 'logs.csv')
+ File.open(output_path, 'w')
+ end
+ end
+
+ def write_row(row)
data = JSON.parse(row.message)
timestamp = data.dig('time')
@@ -38,34 +43,18 @@ def build_row(row)
multi_factor_auth_method = data.dig(
'properties', 'event_properties', 'multi_factor_auth_method'
)
-
- mfa_key = case multi_factor_auth_method
- when 'sms', 'voice'
- 'phone_configuration_id'
- when 'piv_cac'
- 'piv_cac_configuration_id'
- when 'webauthn'
- 'webauthn_configuration_id'
- when 'totp'
- 'auth_app_configuration_id'
- end
-
- row_id = data.dig('properties', 'event_properties', mfa_key)
- multi_factor_id = row_id && "#{mfa_key}:#{row_id}"
service_provider = data.dig('properties', 'service_provider')
ip_address = data.dig('properties', 'user_ip')
user_agent = data.dig('properties', 'user_agent')
- [
- timestamp,
- event_name,
- success,
- multi_factor_auth_method,
- multi_factor_id,
- service_provider,
- ip_address,
- user_agent,
- ]
+ output_file.puts(
+ CSV.generate_line(
+ [
+ timestamp, event_name, success, multi_factor_auth_method,
+ service_provider, ip_address, user_agent
+ ],
+ ),
+ )
end
end
end
diff --git a/app/services/db/sp_cost/add_sp_cost.rb b/app/services/db/sp_cost/add_sp_cost.rb
index bb99808ece3..6d465231122 100644
--- a/app/services/db/sp_cost/add_sp_cost.rb
+++ b/app/services/db/sp_cost/add_sp_cost.rb
@@ -20,20 +20,14 @@ class SpCostTypeError < StandardError; end
voice
].freeze
- def self.call(issuer, ial, token, transaction_id: nil)
+ def self.call(issuer, ial, token)
return if token.blank?
unless TOKEN_WHITELIST.include?(token.to_sym)
NewRelic::Agent.notice_error(SpCostTypeError.new(token.to_s))
return
end
agency_id = (issuer.present? && ServiceProvider.find_by(issuer: issuer)&.agency_id) || 0
- ::SpCost.create(
- issuer: issuer.to_s,
- ial: ial,
- agency_id: agency_id,
- cost_type: token,
- transaction_id: transaction_id,
- )
+ ::SpCost.create(issuer: issuer.to_s, ial: ial, agency_id: agency_id, cost_type: token)
end
end
end
diff --git a/app/services/doc_auth_router.rb b/app/services/doc_auth_router.rb
index 924ad647d96..b51d1e42c63 100644
--- a/app/services/doc_auth_router.rb
+++ b/app/services/doc_auth_router.rb
@@ -219,7 +219,17 @@ def self.notify_exception(exception, custom_params = nil)
end
end
+ #
+ # The `acuant_simulator` config is deprecated. The logic to switch vendors
+ # based on its value can be removed once FORCE_ACUANT_CONFIG_UPGRADE in
+ # acuant_simulator_config_validation.rb has been set to true for at least
+ # a deploy cycle.
+ #
def self.doc_auth_vendor
vendor_from_config = AppConfig.env.doc_auth_vendor
+ if vendor_from_config.blank?
+ return AppConfig.env.acuant_simulator == 'true' ? 'mock' : 'acuant'
+ end
+ vendor_from_config
end
end
diff --git a/app/services/document_capture_session_async_result.rb b/app/services/document_capture_session_async_result.rb
index c7e95648b9f..3f505d2e5d0 100644
--- a/app/services/document_capture_session_async_result.rb
+++ b/app/services/document_capture_session_async_result.rb
@@ -22,8 +22,6 @@ def done?
status == DocumentCaptureSessionAsyncResult::DONE
end
- alias_method :success?, :done?
-
def in_progress?
status == DocumentCaptureSessionAsyncResult::IN_PROGRESS
end
diff --git a/app/services/encryption/multi_region_kms_client.rb b/app/services/encryption/multi_region_kms_client.rb
index 4cf87338bdb..a566c1b96ef 100644
--- a/app/services/encryption/multi_region_kms_client.rb
+++ b/app/services/encryption/multi_region_kms_client.rb
@@ -59,7 +59,7 @@ def encrypt_legacy(key_id, plaintext, encryption_context)
def find_available_region(regions)
regions.each do |region, cipher|
region_client = @aws_clients[region]
- return CipherData.new(region_client, Base64.strict_decode64(cipher)) if region_client
+ return CipherData.new(region_client, cipher) if region_client
end
raise EncryptionError, 'No supported region found in ciphertext'
end
diff --git a/app/services/flow/flow_state_machine.rb b/app/services/flow/flow_state_machine.rb
index 49085955360..40e8ea93ac2 100644
--- a/app/services/flow/flow_state_machine.rb
+++ b/app/services/flow/flow_state_machine.rb
@@ -22,10 +22,7 @@ def update
step = current_step
result = flow.handle(step)
if @analytics_id
- increment_step_name_counts
analytics.track_event(analytics_submitted, result.to_h.merge(analytics_properties))
- # keeping the old event names for backward compatibility
- analytics.track_event(old_analytics_submitted, result.to_h.merge(analytics_properties))
end
register_update_step(step, result)
if flow.json
@@ -47,12 +44,7 @@ def current_step
end
def track_step_visited
- if @analytics_id
- increment_step_name_counts
- analytics.track_event(analytics_visited, analytics_properties)
- # keeping the old event names for backward compatibility
- analytics.track_event(old_analytics_visited, analytics_properties)
- end
+ analytics.track_event(analytics_visited, analytics_properties) if @analytics_id
Funnel::DocAuth::RegisterStep.new(user_id, issuer).call(current_step, :view, true)
register_campaign
end
@@ -124,11 +116,7 @@ def call_optional_show_step(step)
result = optional_show_step.new(@flow).base_call
if @analytics_id
- optional_properties = result.to_h.merge(step: optional_show_step)
-
- analytics.track_event(analytics_optional_step, optional_properties)
- # keeping the old event names for backward compatibility
- analytics.track_event(old_analytics_optional_step, optional_properties)
+ analytics.track_event(analytics_optional_step, result.to_h.merge(step: optional_show_step))
end
if next_step.to_s != step
@@ -156,50 +144,31 @@ def redirect_to_step(step)
end
def analytics_submitted
- 'IdV: ' + "#{@analytics_id} #{current_step} submitted".downcase
- end
-
- def analytics_visited
- 'IdV: ' + "#{@analytics_id} #{current_step} visited".downcase
- end
-
- def analytics_optional_step
- 'IdV: ' + "#{@analytics_id} optional #{current_step} submitted".downcase
- end
-
- def old_analytics_submitted
@analytics_id + ' submitted'
end
- def old_analytics_visited
+ def analytics_visited
@analytics_id + ' visited'
end
- def old_analytics_optional_step
+ def analytics_optional_step
[@analytics_id, 'optional submitted'].join(' ')
end
def analytics_properties
+ current_step_name = "#{current_step.to_s}_#{action_name}"
+ current_flow_step_counts[current_step_name] ||= 0
{
step: current_step,
- step_count: current_flow_step_counts[current_step_name],
+ step_count: current_flow_step_counts[current_step_name] += 1,
}
end
- def current_step_name
- "#{current_step}_#{action_name}"
- end
-
def current_flow_step_counts
current_session["#{@name}_flow_step_counts"] ||= {}
- current_session["#{@name}_flow_step_counts"].default = 0
current_session["#{@name}_flow_step_counts"]
end
- def increment_step_name_counts
- current_flow_step_counts[current_step_name] += 1
- end
-
def next_step
flow.next_step
end
diff --git a/app/services/identity_linker.rb b/app/services/identity_linker.rb
index c95ba7b5dbb..13af39c4771 100644
--- a/app/services/identity_linker.rb
+++ b/app/services/identity_linker.rb
@@ -8,7 +8,6 @@ def initialize(user, provider)
end
def link_identity(**extra_attrs)
- return unless user && provider.present?
process_ial(extra_attrs)
attributes = merged_attributes(extra_attrs)
identity.update!(attributes)
diff --git a/app/services/idv/actions/cancel_link_sent_action.rb b/app/services/idv/actions/cancel_link_sent_action.rb
deleted file mode 100644
index b8ebc0b2e93..00000000000
--- a/app/services/idv/actions/cancel_link_sent_action.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module Idv
- module Actions
- class CancelLinkSentAction < Idv::Steps::DocAuthBaseStep
- def call
- mark_step_incomplete(:send_link)
- end
- end
- end
-end
diff --git a/app/services/idv/actions/cancel_send_link_action.rb b/app/services/idv/actions/cancel_send_link_action.rb
deleted file mode 100644
index 8d9fe50ce29..00000000000
--- a/app/services/idv/actions/cancel_send_link_action.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module Idv
- module Actions
- class CancelSendLinkAction < Idv::Steps::DocAuthBaseStep
- def call
- mark_step_incomplete(:upload)
- end
- end
- end
-end
diff --git a/app/services/idv/actions/verify_document_action.rb b/app/services/idv/actions/verify_document_action.rb
index 3bbdc4ccc77..5443ae189bd 100644
--- a/app/services/idv/actions/verify_document_action.rb
+++ b/app/services/idv/actions/verify_document_action.rb
@@ -30,13 +30,9 @@ def form
end
def enqueue_job
- verify_document_capture_session = if hybrid_flow_mobile?
- document_capture_session
- else
- create_document_capture_session(
- verify_document_capture_session_uuid_key,
- )
- end
+ verify_document_capture_session = create_document_capture_session(
+ verify_document_capture_session_uuid_key,
+ )
verify_document_capture_session.requested_at = Time.zone.now
verify_document_capture_session.create_doc_auth_session
diff --git a/app/services/idv/actions/verify_document_status_action.rb b/app/services/idv/actions/verify_document_status_action.rb
index 69b209c0773..6f8cc8b0770 100644
--- a/app/services/idv/actions/verify_document_status_action.rb
+++ b/app/services/idv/actions/verify_document_status_action.rb
@@ -61,13 +61,9 @@ def process_result(result)
def verify_document_capture_session
return @verify_document_capture_session if defined?(@verify_document_capture_session)
- @verify_document_capture_session = if hybrid_flow_mobile?
- document_capture_session
- else
- DocumentCaptureSession.find_by(
- uuid: flow_session[verify_document_capture_session_uuid_key],
- )
- end
+ @verify_document_capture_session = DocumentCaptureSession.find_by(
+ uuid: flow_session[verify_document_capture_session_uuid_key],
+ )
end
def async_state
diff --git a/app/services/idv/flows/cac_flow.rb b/app/services/idv/flows/cac_flow.rb
index 9a1a8217c13..f4eb6c15f2e 100644
--- a/app/services/idv/flows/cac_flow.rb
+++ b/app/services/idv/flows/cac_flow.rb
@@ -8,6 +8,7 @@ class CacFlow < Flow::BaseFlow
enter_info: Idv::Steps::Cac::EnterInfoStep,
verify: Idv::Steps::Cac::VerifyStep,
verify_wait: Idv::Steps::Cac::VerifyWaitStep,
+ success: Idv::Steps::Cac::SuccessStep,
}.freeze
OPTIONAL_SHOW_STEPS = {
diff --git a/app/services/idv/flows/capture_doc_flow.rb b/app/services/idv/flows/capture_doc_flow.rb
index 680d4747a88..401946b0468 100644
--- a/app/services/idv/flows/capture_doc_flow.rb
+++ b/app/services/idv/flows/capture_doc_flow.rb
@@ -8,8 +8,6 @@ class CaptureDocFlow < Flow::BaseFlow
ACTIONS = {
reset: Idv::Actions::ResetAction,
- verify_document: Idv::Actions::VerifyDocumentAction,
- verify_document_status: Idv::Actions::VerifyDocumentStatusAction,
}.freeze
def initialize(controller, session, _name)
diff --git a/app/services/idv/flows/doc_auth_flow.rb b/app/services/idv/flows/doc_auth_flow.rb
index 8711b4e5784..82fce9e343a 100644
--- a/app/services/idv/flows/doc_auth_flow.rb
+++ b/app/services/idv/flows/doc_auth_flow.rb
@@ -17,8 +17,6 @@ class DocAuthFlow < Flow::BaseFlow
}.freeze
ACTIONS = {
- cancel_send_link: Idv::Actions::CancelSendLinkAction,
- cancel_link_sent: Idv::Actions::CancelLinkSentAction,
reset: Idv::Actions::ResetAction,
redo_ssn: Idv::Actions::RedoSsnAction,
verify_document: Idv::Actions::VerifyDocumentAction,
diff --git a/app/services/idv/steps/cac/success_step.rb b/app/services/idv/steps/cac/success_step.rb
new file mode 100644
index 00000000000..5361d311a42
--- /dev/null
+++ b/app/services/idv/steps/cac/success_step.rb
@@ -0,0 +1,9 @@
+module Idv
+ module Steps
+ module Cac
+ class SuccessStep < DocAuthBaseStep
+ def call; end
+ end
+ end
+ end
+end
diff --git a/app/services/idv/steps/doc_auth_base_step.rb b/app/services/idv/steps/doc_auth_base_step.rb
index c55a1e68c87..f21be9308d6 100644
--- a/app/services/idv/steps/doc_auth_base_step.rb
+++ b/app/services/idv/steps/doc_auth_base_step.rb
@@ -50,10 +50,6 @@ def user_id_from_token
flow_session[:doc_capture_user_id]
end
- def hybrid_flow_mobile?
- user_id_from_token.present?
- end
-
def throttled_response
redirect_to throttled_url
IdentityDocAuth::Response.new(
@@ -75,9 +71,9 @@ def user_id
current_user ? current_user.id : user_id_from_token
end
- def add_cost(token, transaction_id: nil)
+ def add_cost(token)
issuer = sp_session[:issuer].to_s
- Db::SpCost::AddSpCost.call(issuer, 2, token, transaction_id: transaction_id)
+ Db::SpCost::AddSpCost.call(issuer, 2, token)
Db::ProofingCost::AddUserProofingCost.call(user_id, token)
end
diff --git a/app/services/idv/steps/link_sent_step.rb b/app/services/idv/steps/link_sent_step.rb
index 47ac432a929..06b607d1363 100644
--- a/app/services/idv/steps/link_sent_step.rb
+++ b/app/services/idv/steps/link_sent_step.rb
@@ -31,10 +31,7 @@ def take_photo_with_phone_successful?
end
def document_capture_session_result
- @document_capture_session_result ||= (
- document_capture_session&.load_result ||
- document_capture_session&.load_doc_auth_async_result
- )
+ @document_capture_session_result ||= document_capture_session&.load_result
end
def mark_steps_complete
diff --git a/app/services/idv/steps/verify_base_step.rb b/app/services/idv/steps/verify_base_step.rb
index 29283fe78d2..8aa9f5fffa4 100644
--- a/app/services/idv/steps/verify_base_step.rb
+++ b/app/services/idv/steps/verify_base_step.rb
@@ -54,14 +54,8 @@ def idv_result_to_form_response(idv_result)
def add_proofing_costs(results)
vendors = results[:context][:stages]
vendors.each do |hash|
- if hash[:state_id]
- # transaction_id comes from TransactionLocatorId
- add_cost(:aamva, transaction_id: hash[:transaction_id])
- end
- if hash[:resolution]
- # transaction_id comes from ConversationId
- add_cost(:lexis_nexis_resolution, transaction_id: hash[:transaction_id])
- end
+ add_cost(:aamva) if hash[:state_id]
+ add_cost(:lexis_nexis_resolution) if hash[:resolution]
end
end
diff --git a/app/services/reports/monthly_usps_letter_requests_report.rb b/app/services/reports/monthly_usps_letter_requests_report.rb
deleted file mode 100644
index 29acfe0cce4..00000000000
--- a/app/services/reports/monthly_usps_letter_requests_report.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'login_gov/hostdata'
-
-module Reports
- class MonthlyUspsLetterRequestsReport < BaseReport
- REPORT_NAME = 'monthly-usps-letter-requests-report'.freeze
-
- def call
- daily_results = transaction_with_timeout do
- ::LetterRequestsToUspsFtpLog.where(ftp_at: first_of_this_month..end_of_today)
- end
- totals = calculate_totals(daily_results)
- save_report(REPORT_NAME, {total_letter_requests: totals,
- daily_letter_requests: daily_results}.to_json)
- end
-
- private
-
- def calculate_totals(daily_results)
- daily_results.inject(0) {|sum, rec| sum + rec['letter_requests_count'].to_i }
- end
- end
-end
diff --git a/app/services/sp_handoff_bounce.rb b/app/services/sp_handoff_bounce.rb
deleted file mode 100644
index ffcf919bab0..00000000000
--- a/app/services/sp_handoff_bounce.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class SpHandoffBounce
- def self.is_bounced?(session)
- start_time = session[:sp_handoff_start_time]
- return if start_time.blank?
- tz = Time.zone
- start_time = tz.parse(start_time) if start_time.class == String
- tz.now <= (start_time + AppConfig.env.sp_handoff_bounce_max_seconds.to_i.seconds)
- end
-
- def self.add_handoff_time_to_session(session)
- session[:sp_handoff_start_time] = Time.zone.now
- end
-end
diff --git a/app/services/sp_handoff_bounce/add_handoff_time_to_session.rb b/app/services/sp_handoff_bounce/add_handoff_time_to_session.rb
new file mode 100644
index 00000000000..feaa37377eb
--- /dev/null
+++ b/app/services/sp_handoff_bounce/add_handoff_time_to_session.rb
@@ -0,0 +1,7 @@
+module SpHandoffBounce
+ class AddHandoffTimeToSession
+ def self.call(session)
+ session[:sp_handoff_start_time] = Time.zone.now
+ end
+ end
+end
diff --git a/app/services/sp_handoff_bounce/is_bounced.rb b/app/services/sp_handoff_bounce/is_bounced.rb
new file mode 100644
index 00000000000..a0673c48804
--- /dev/null
+++ b/app/services/sp_handoff_bounce/is_bounced.rb
@@ -0,0 +1,11 @@
+module SpHandoffBounce
+ class IsBounced
+ def self.call(session)
+ start_time = session[:sp_handoff_start_time]
+ return if start_time.blank?
+ tz = Time.zone
+ start_time = tz.parse(start_time) if start_time.class == String
+ tz.now <= (start_time + AppConfig.env.sp_handoff_bounce_max_seconds.to_i.seconds)
+ end
+ end
+end
diff --git a/app/services/store_sp_metadata_in_session.rb b/app/services/store_sp_metadata_in_session.rb
index e5f6865a673..38454c71a3a 100644
--- a/app/services/store_sp_metadata_in_session.rb
+++ b/app/services/store_sp_metadata_in_session.rb
@@ -35,7 +35,6 @@ def sp_request
def update_session
session[:sp] = {
issuer: sp_request.issuer,
- ial: ial_context.ial,
ial2: ial_context.ial2_requested?,
ial2_strict: ial_context.ial2_strict_requested?,
ialmax: ial_context.ialmax_requested?,
diff --git a/app/services/usps_confirmation_uploader.rb b/app/services/usps_confirmation_uploader.rb
index c2e60709dec..2878bccce9f 100644
--- a/app/services/usps_confirmation_uploader.rb
+++ b/app/services/usps_confirmation_uploader.rb
@@ -1,14 +1,9 @@
class UspsConfirmationUploader
- def initialize
- @now = Time.zone.now
- end
-
def run
confirmations = UspsConfirmation.all
export = generate_export(confirmations)
upload_export(export)
clear_confirmations(confirmations)
- LetterRequestsToUspsFtpLog.create(ftp_at: @now, letter_requests_count: confirmations.count)
rescue StandardError => error
NewRelic::Agent.notice_error(error)
end
@@ -32,7 +27,7 @@ def clear_confirmations(confirmations)
end
def remote_path
- timestamp = @now.strftime('%Y%m%d')
+ timestamp = Time.zone.now.strftime('%Y%m%d')
File.join(env.usps_upload_sftp_directory, "batch#{timestamp}.psv")
end
diff --git a/app/views/account_reset/confirm_delete_account/show.html.erb b/app/views/account_reset/confirm_delete_account/show.html.erb
index e1a255e8410..f57931ea938 100644
--- a/app/views/account_reset/confirm_delete_account/show.html.erb
+++ b/app/views/account_reset/confirm_delete_account/show.html.erb
@@ -5,7 +5,7 @@
alt: '',
class: 'absolute top-n24 left-0 right-0 margin-x-auto') %>
<%= t('account_reset.confirm_delete_account.title') %>
- <%= t('account_reset.confirm_delete_account.info_html', app: APP_NAME, email: email) %>
+ <%= t('account_reset.confirm_delete_account.info_html', email: email) %>
<%= t('account_reset.confirm_delete_account.cta_html',
link: link_to(t('account_reset.confirm_delete_account.link_text'),
sign_up_email_path)) %>
diff --git a/app/views/account_reset/delete_account/show.html.erb b/app/views/account_reset/delete_account/show.html.erb
index 24119796876..eb1d6b24275 100644
--- a/app/views/account_reset/delete_account/show.html.erb
+++ b/app/views/account_reset/delete_account/show.html.erb
@@ -4,7 +4,7 @@
<%= t('account_reset.delete_account.title') %>
- <%= t('account_reset.delete_account.info', app: APP_NAME) %>
+ <%= t('account_reset.delete_account.info') %>
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb
index 02d433fb4b7..fef025acf80 100644
--- a/app/views/devise/sessions/new.html.erb
+++ b/app/views/devise/sessions/new.html.erb
@@ -39,7 +39,7 @@
) %>
<% end %>
-<% if @ial && desktop_device? %>
+<% if FeatureManagement.allow_piv_cac_login? && @ial && desktop_device? %>
<%= link_to(
t('account.login.piv_cac'),
diff --git a/app/views/idv/address/new.html.erb b/app/views/idv/address/new.html.erb
index 3f058c20891..acf16805944 100644
--- a/app/views/idv/address/new.html.erb
+++ b/app/views/idv/address/new.html.erb
@@ -37,4 +37,6 @@
<% end %>
-<%= render 'idv/doc_auth/back', step: 'verify' %>
+
+ <%= link_to t('links.cancel'), idv_cancel_path, class: 'h5' %>
+
diff --git a/app/views/idv/cac/success.html.erb b/app/views/idv/cac/success.html.erb
new file mode 100644
index 00000000000..269df24d8d5
--- /dev/null
+++ b/app/views/idv/cac/success.html.erb
@@ -0,0 +1,22 @@
+<% title t('cac_proofing.titles.cac_proofing') %>
+
+ <%= t('cac_proofing.step', step: 2) %>
+
+
+<%= image_tag(asset_url('state-id-confirm@3x.png'), width: 210) %>
+
+
+ <%= t('cac_proofing.headings.success') %>
+
+
+
+
+
+ <%= button_to(t('forms.buttons.continue'), url_for, method: :put,
+ class: 'btn btn-primary btn-wide sm-col-6 col-12') %>
+
+
+<%= validated_form_for('', url: url_for, method: 'PUT',
+ html: { autocomplete: 'off', role: 'form', class: 'margin-top-2' }) do |f| %>
+<% end %>
+<%= render 'idv/cac/start_over_or_cancel' %>
diff --git a/app/views/idv/doc_auth/_back.html.erb b/app/views/idv/doc_auth/_back.html.erb
deleted file mode 100644
index 0bef687810e..00000000000
--- a/app/views/idv/doc_auth/_back.html.erb
+++ /dev/null
@@ -1,31 +0,0 @@
-<%#
-Renders a "Back" link to return to a previous step, given by one of action or step local variables.
-If neither are passed, redirects to the previous screen using HTTP referer. An optional fallback
-path can be passed in case the HTTP header is not specified or is invalid. If none of the above
-yield a useable URL, nothing will be rendered.
-
-locals:
-* action: (Optional) Flow action to call to return to the previous step.
-* step: (Optional) Name of step to which user should be returned.
-* fallback_path: (Optional) Path to redirect absent action, step, and HTTP referer.
-%>
-<%
-text = '‹ ' + t('forms.buttons.back')
-step = local_assigns[:action] || local_assigns[:step]
-path = step ? idv_doc_auth_step_path(step: step) : go_back_path
-path ||= local_assigns[:fallback_path]
-%>
-<% if path %>
-
- <% if local_assigns[:action] %>
- <%= button_to(
- text,
- path,
- method: :put,
- class: 'btn btn-link'
- ) %>
- <% else %>
- <%= link_to(text, path) %>
- <% end %>
-
-<% end %>
diff --git a/app/views/idv/doc_auth/_spinner.html.erb b/app/views/idv/doc_auth/_spinner.html.erb
new file mode 100644
index 00000000000..3e832ffd5dd
--- /dev/null
+++ b/app/views/idv/doc_auth/_spinner.html.erb
@@ -0,0 +1,11 @@
+
+
+ <%= image_tag(
+ asset_url('wait.gif'),
+ srcset: asset_url('wait.gif'),
+ height: 50,
+ width: 50,
+ alt: t('image_description.spinner'))
+ %>
+
+
diff --git a/app/views/idv/doc_auth/_submit_with_spinner.html.erb b/app/views/idv/doc_auth/_submit_with_spinner.html.erb
new file mode 100644
index 00000000000..ff80876cf8e
--- /dev/null
+++ b/app/views/idv/doc_auth/_submit_with_spinner.html.erb
@@ -0,0 +1,6 @@
+
+ <%= t('forms.buttons.continue') %>
+
+<%= render 'idv/doc_auth/spinner' %>
+
+<%= javascript_packs_tag_once 'submit-with-spinner' %>
diff --git a/app/views/idv/doc_auth/link_sent.html.erb b/app/views/idv/doc_auth/link_sent.html.erb
index 374357fc5df..2c5ae586e09 100644
--- a/app/views/idv/doc_auth/link_sent.html.erb
+++ b/app/views/idv/doc_auth/link_sent.html.erb
@@ -38,7 +38,7 @@
%>
-<%= render 'idv/doc_auth/back', action: 'cancel_link_sent' %>
+<%= render 'idv/doc_auth/start_over_or_cancel' %>
<% if FeatureManagement.doc_capture_polling_enabled? %>
<%= javascript_packs_tag_once 'doc_capture_polling' %>
diff --git a/app/views/idv/doc_auth/send_link.html.erb b/app/views/idv/doc_auth/send_link.html.erb
index 6fc5f489a0f..0fade994cb0 100644
--- a/app/views/idv/doc_auth/send_link.html.erb
+++ b/app/views/idv/doc_auth/send_link.html.erb
@@ -39,4 +39,4 @@
<% end %>
-<%= render 'idv/doc_auth/back', action: 'cancel_send_link' %>
+<%= render 'idv/doc_auth/start_over_or_cancel' %>
diff --git a/app/views/idv/doc_auth/upload.html.erb b/app/views/idv/doc_auth/upload.html.erb
index 4bf187bec2c..74976737b4b 100644
--- a/app/views/idv/doc_auth/upload.html.erb
+++ b/app/views/idv/doc_auth/upload.html.erb
@@ -36,7 +36,7 @@
<% end %>
-<% if desktop_device? %>
+<% if AppConfig.env.cac_proofing_enabled == 'true' && desktop_device? %>
<%= t('doc_auth.info.use_cac') %>
<%= link_to(t('doc_auth.info.use_cac_link'), idv_cac_step_path(step: :choose_method)) %>
diff --git a/app/views/idv/doc_auth/welcome.html.erb b/app/views/idv/doc_auth/welcome.html.erb
index bd4a478c32f..d578aa2d5b8 100644
--- a/app/views/idv/doc_auth/welcome.html.erb
+++ b/app/views/idv/doc_auth/welcome.html.erb
@@ -102,8 +102,7 @@
<%= new_window_link_to t('doc_auth.instructions.learn_more'), 'https://login.gov/policy/' %>
- <%= f.button :button, t('doc_auth.buttons.continue'), type: :submit,
- class: 'btn btn-primary btn-wide sm-col-6 col-6' %>
+ <%= f.button :submit, t('doc_auth.buttons.continue'), class: 'btn btn-primary btn-wide sm-col-6 col-6' %>
<% end %>
diff --git a/app/views/idv/shared/_document_capture.html.erb b/app/views/idv/shared/_document_capture.html.erb
index 0075f9c2ad7..1d7eb3f7291 100644
--- a/app/views/idv/shared/_document_capture.html.erb
+++ b/app/views/idv/shared/_document_capture.html.erb
@@ -18,10 +18,10 @@
mock_client: (DocAuthRouter.doc_auth_vendor == 'mock').presence,
document_capture_session_uuid: flow_session[:document_capture_session_uuid],
endpoint: FeatureManagement.document_capture_async_uploads_enabled? ?
- send(@step_url, step: :verify_document) :
+ idv_doc_auth_step_path(step: :verify_document) :
api_verify_images_url,
status_endpoint: FeatureManagement.document_capture_async_uploads_enabled? ?
- send(@step_url, step: :verify_document_status) :
+ idv_doc_auth_step_path(step: :verify_document_status) :
nil,
status_poll_interval_ms: AppConfig.env.poll_rate_for_verify_in_seconds.to_i * 1000,
sp_name: sp_name,
@@ -133,10 +133,7 @@
<%# ---- Submit ----- %>
-
- <%= t('forms.buttons.continue') %>
-
-
+ <%= render 'idv/doc_auth/submit_with_spinner' %>
<% end %> <%# end validated_form_for %>
diff --git a/app/views/idv/usps/index.html.erb b/app/views/idv/usps/index.html.erb
index 29c87f89157..3f3db6e1a30 100644
--- a/app/views/idv/usps/index.html.erb
+++ b/app/views/idv/usps/index.html.erb
@@ -16,4 +16,7 @@
<% end %>
-<%= render 'idv/doc_auth/back', fallback_path: @presenter.fallback_back_path %>
+
+ <%= button_to(t('idv.messages.clear_and_start_over'), idv_session_path, method: :delete, class: 'btn btn-link margin-bottom-1') %>
+ <%= link_to(t('links.cancel'), @presenter.cancel_path, class: 'h5') %>
+
diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb
index 992ffb65a5b..d3c08c16388 100644
--- a/app/views/layouts/base.html.erb
+++ b/app/views/layouts/base.html.erb
@@ -73,26 +73,18 @@
<%= render 'shared/footer_lite' %>
- <% if current_user # Render the JS snipped that collects platform authenticator analytics %>
-
- <%= render partial: 'session_timeout/ping',
- locals: {
- timeout_url: timeout_url,
- warning: session_timeout_warning,
- start: session_timeout_start,
- frequency: session_timeout_frequency,
- modal: session_modal,
- } %>
- <% elsif !@skip_session_expiration %>
- <%= render partial: 'session_timeout/expire_session',
- locals: {
- session_timeout_in: Devise.timeout_in,
- } %>
- <% end %>
+
<%= javascript_packs_tag_once 'application', prepend: true %>
<%= render_javascript_pack_once_tags %>
+ <% if current_user # Render the JS snipped that collects platform authenticator analytics %>
+
+ <%= auto_session_timeout_js %>
+ <% else %>
+ <%= auto_session_expired_js %>
+ <% end %>
+
<%= render 'shared/dap_analytics' if AppConfig.env.participate_in_dap == 'true' && !session_with_trust? %>