diff --git a/app/assets/stylesheets/components/_i18n-dropdown.scss b/app/assets/stylesheets/components/_i18n-dropdown.scss deleted file mode 100644 index 649079631e8..00000000000 --- a/app/assets/stylesheets/components/_i18n-dropdown.scss +++ /dev/null @@ -1,51 +0,0 @@ -.i18n-mobile-toggle button, -.i18n-desktop-toggle button { - @include u-line-height('body', $theme-body-line-height); - cursor: pointer; - - &:hover { - text-decoration: underline; - } -} - -.i18n-mobile-toggle, -.i18n-desktop-toggle { - &.focused .caret { - transform: rotateX(180deg) translateY(-1px); - } -} - -.i18n-mobile-dropdown { - background-color: color('primary-lighter'); - bottom: 100%; - left: 0; - position: absolute; - right: 0; -} - -.i18n-desktop-toggle { - position: relative; - - &.focused { - background-color: color('primary'); - border-radius: 0; - margin-bottom: 0; - margin-top: 0; - } -} - -.i18n-desktop-dropdown { - bottom: 100%; - left: -1px; - position: absolute; - width: 194px; -} - -.language-desktop-button { - background-color: transparent; -} - -.language-mobile-button { - background-color: color('primary-lighter'); - border: 0; -} diff --git a/app/assets/stylesheets/components/_language-picker.scss b/app/assets/stylesheets/components/_language-picker.scss new file mode 100644 index 00000000000..d514f6e9119 --- /dev/null +++ b/app/assets/stylesheets/components/_language-picker.scss @@ -0,0 +1,100 @@ +.language-picker { + position: relative; + width: auto; + + .usa-accordion__content { + @include u-bg('primary'); + @include u-border(1px, 'primary-darker'); + margin: 0.25rem 0 0; + overflow: visible; + padding: 0; + position: absolute; + text-align: center; + width: 100%; + z-index: 10; + bottom: 100%; + } +} + +.language-picker__label { + align-items: center; + display: flex; + background-position: right units(1.5) center; + background-position-y: calc(50% + 2px); + padding: units(0.5); + padding-left: units(1); + padding-right: units(1); + border-color: transparent; + + @include at-media-max('tablet') { + justify-content: center; + border-radius: 0; + } + + @include at-media('tablet') { + border-color: color('primary'); + + &, + &:hover { + color: color('white'); + } + } + + span { + margin: 0 units(1); + } + + &::after { + content: ''; + display: block; + width: 0.8125rem; + height: 0.8125rem; + background-size: 0.8125rem; + } + + &.usa-accordion__button[aria-expanded='false'], + &.usa-accordion__button[aria-expanded='true'] { + background-image: none; + } + + &.usa-accordion__button[aria-expanded='false'] { + &:hover { + background-color: transparent; + } + + &::after { + background-image: url(identity-style-guide/dist/assets/img/angle-arrow-up.svg); + + @include at-media('tablet') { + background-image: url(identity-style-guide/dist/assets/img/angle-arrow-up-white.svg); + } + } + } + + &.usa-accordion__button[aria-expanded='true'] { + @include u-bg('primary'); + color: color('white'); + + &::after { + background-image: url(identity-style-guide/dist/assets/img/angle-arrow-down-white.svg); + } + } +} + +.language-picker__list { + @include list-reset; + + a { + @include u-padding-y(1.5); + display: block; + color: color('white'); + + &:focus { + outline-offset: units(2px); + } + } + + li + li { + border-top: 1px solid color('primary-darker'); + } +} diff --git a/app/assets/stylesheets/components/all.scss b/app/assets/stylesheets/components/all.scss index 1499f5ad128..bca27b6eb45 100644 --- a/app/assets/stylesheets/components/all.scss +++ b/app/assets/stylesheets/components/all.scss @@ -12,6 +12,7 @@ @import 'full-screen'; @import 'hr'; @import 'icon'; +@import 'language-picker'; @import 'list'; @import 'modal'; @import 'nav'; @@ -26,6 +27,5 @@ @import 'step-indicator'; @import 'troubleshooting-options'; @import 'validated-checkbox'; -@import 'i18n-dropdown'; @import 'location-collection-item'; @import 'memorable-date'; diff --git a/app/assets/stylesheets/utilities/_typography.scss b/app/assets/stylesheets/utilities/_typography.scss index 5117f2d2454..476a2cddcf8 100644 --- a/app/assets/stylesheets/utilities/_typography.scss +++ b/app/assets/stylesheets/utilities/_typography.scss @@ -9,9 +9,6 @@ body { .fs-12p { font-size: 12px; } -.fs-13p { - font-size: 13px; -} .fs-20p { font-size: 20px; } diff --git a/app/components/language_picker_component.html.erb b/app/components/language_picker_component.html.erb new file mode 100644 index 00000000000..f1779715852 --- /dev/null +++ b/app/components/language_picker_component.html.erb @@ -0,0 +1,32 @@ +<%= content_tag(:div, **tag_options, class: css_class) do %> + <%= content_tag( + :button, + class: 'usa-accordion__button language-picker__label', + aria: { + controls: "language-picker-#{unique_id}", + expanded: false, + }, + ) do %> + <%= image_tag(asset_url('globe-blue.svg'), width: 12, height: 12, alt: '', class: 'tablet:display-none') %> + <%= image_tag(asset_url('globe-white.svg'), width: 12, height: 12, alt: '', class: 'display-none tablet:display-inline') %> + + <%= t('i18n.language') %> + + <% end %> + +<% end %> diff --git a/app/components/language_picker_component.rb b/app/components/language_picker_component.rb new file mode 100644 index 00000000000..1088006c5dd --- /dev/null +++ b/app/components/language_picker_component.rb @@ -0,0 +1,16 @@ +class LanguagePickerComponent < BaseComponent + attr_reader :url_generator, :tag_options + + def initialize(url_generator: method(:url_for), **tag_options) + @url_generator = url_generator + @tag_options = tag_options + end + + def css_class + ['language-picker', 'usa-accordion', *tag_options[:class]] + end + + def sanitized_request_params + request.query_parameters.slice(:request_id) + end +end diff --git a/app/controllers/api/verify/document_capture_controller.rb b/app/controllers/api/verify/document_capture_controller.rb index cd3b5ad66ac..b1fa88429cf 100644 --- a/app/controllers/api/verify/document_capture_controller.rb +++ b/app/controllers/api/verify/document_capture_controller.rb @@ -7,7 +7,6 @@ class DocumentCaptureController < BaseController def create result = Idv::ApiDocumentVerificationForm.new( verify_params, - liveness_checking_enabled: false, analytics: analytics, irs_attempts_api_tracker: irs_attempts_api_tracker, flow_path: params[:flow_path], @@ -37,7 +36,6 @@ def enqueue_job } Idv::Agent.new(applicant).proof_document( verify_document_capture_session, - liveness_checking_enabled: false, trace_id: amzn_trace_id, image_metadata: image_metadata, analytics_data: { diff --git a/app/controllers/concerns/verify_profile_concern.rb b/app/controllers/concerns/verify_profile_concern.rb index 107aa91506e..96c957f0ea0 100644 --- a/app/controllers/concerns/verify_profile_concern.rb +++ b/app/controllers/concerns/verify_profile_concern.rb @@ -24,8 +24,6 @@ def user_last_signed_in_more_than_5_months_ago? def profile_needs_verification? return false if current_user.blank? - return false if sp_session[:ial2_strict] && - !IdentityConfig.store.gpo_allowed_for_strict_ial2 current_user.decorate.pending_profile_requires_verification? || user_needs_to_reactivate_account? end diff --git a/app/controllers/idv/capture_doc_controller.rb b/app/controllers/idv/capture_doc_controller.rb index 0fd1efca22d..700787c90b3 100644 --- a/app/controllers/idv/capture_doc_controller.rb +++ b/app/controllers/idv/capture_doc_controller.rb @@ -15,7 +15,7 @@ class CaptureDocController < ApplicationController step_url: :idv_capture_doc_step_url, final_url: :root_url, flow: Idv::Flows::CaptureDocFlow, - analytics_id: Analytics::DOC_AUTH, + analytics_id: 'Doc Auth', }.freeze def return_to_sp diff --git a/app/controllers/idv/doc_auth_controller.rb b/app/controllers/idv/doc_auth_controller.rb index 7d225b4ab30..2ad72caa386 100644 --- a/app/controllers/idv/doc_auth_controller.rb +++ b/app/controllers/idv/doc_auth_controller.rb @@ -23,7 +23,7 @@ class DocAuthController < ApplicationController step_url: :idv_doc_auth_step_url, final_url: :idv_review_url, flow: Idv::Flows::DocAuthFlow, - analytics_id: Analytics::DOC_AUTH, + analytics_id: 'Doc Auth', }.freeze def return_to_sp @@ -31,8 +31,6 @@ def return_to_sp end def redirect_if_pending_profile - return if sp_session[:ial2_strict] && - !IdentityConfig.store.gpo_allowed_for_strict_ial2 redirect_to idv_gpo_verify_url if current_user.decorate.pending_profile_requires_verification? end diff --git a/app/controllers/idv/gpo_controller.rb b/app/controllers/idv/gpo_controller.rb index dbb41fbec35..1c4594094ca 100644 --- a/app/controllers/idv/gpo_controller.rb +++ b/app/controllers/idv/gpo_controller.rb @@ -7,7 +7,6 @@ class GpoController < ApplicationController before_action :confirm_idv_needed before_action :confirm_user_completed_idv_profile_step before_action :confirm_mail_not_spammed - before_action :confirm_gpo_allowed_if_strict_ial2 def index @presenter = GpoPresenter.new(current_user, url_options) @@ -57,12 +56,6 @@ def resend_requested? current_user.decorate.pending_profile_requires_verification? end - def confirm_gpo_allowed_if_strict_ial2 - return unless sp_session[:ial2_strict] - return if IdentityConfig.store.gpo_allowed_for_strict_ial2 - redirect_to idv_phone_url - end - def confirm_mail_not_spammed redirect_to idv_review_url if idv_session.address_mechanism_chosen? && gpo_mail_service.mail_spammed? diff --git a/app/controllers/idv/image_uploads_controller.rb b/app/controllers/idv/image_uploads_controller.rb index 5f1a9303c3b..30d0af89889 100644 --- a/app/controllers/idv/image_uploads_controller.rb +++ b/app/controllers/idv/image_uploads_controller.rb @@ -20,7 +20,6 @@ def create def image_upload_form @image_upload_form ||= Idv::ApiImageUploadForm.new( params, - liveness_checking_enabled: false, service_provider: current_sp, analytics: analytics, uuid_prefix: current_sp&.app_id, diff --git a/app/controllers/idv/inherited_proofing_controller.rb b/app/controllers/idv/inherited_proofing_controller.rb index e16d55545f9..ce4b3235f60 100644 --- a/app/controllers/idv/inherited_proofing_controller.rb +++ b/app/controllers/idv/inherited_proofing_controller.rb @@ -11,7 +11,7 @@ class InheritedProofingController < ApplicationController step_url: :idv_inherited_proofing_step_url, final_url: :idv_phone_url, flow: Idv::Flows::InheritedProofingFlow, - analytics_id: nil, + analytics_id: 'Inherited Proofing', }.freeze def return_to_sp diff --git a/app/controllers/idv/otp_delivery_method_controller.rb b/app/controllers/idv/otp_delivery_method_controller.rb index dae6b4d1a1c..51cbbbcd48b 100644 --- a/app/controllers/idv/otp_delivery_method_controller.rb +++ b/app/controllers/idv/otp_delivery_method_controller.rb @@ -115,9 +115,7 @@ def otp_delivery_selection_form def gpo_letter_available return @gpo_letter_available if defined?(@gpo_letter_available) @gpo_letter_available ||= FeatureManagement.enable_gpo_verification? && - !Idv::GpoMail.new(current_user).mail_spammed? && - !(sp_session[:ial2_strict] && - !IdentityConfig.store.gpo_allowed_for_strict_ial2) + !Idv::GpoMail.new(current_user).mail_spammed? end end end diff --git a/app/controllers/idv/phone_controller.rb b/app/controllers/idv/phone_controller.rb index 3af426ccf82..b6791bb5b6c 100644 --- a/app/controllers/idv/phone_controller.rb +++ b/app/controllers/idv/phone_controller.rb @@ -146,9 +146,7 @@ def new_phone_added? def gpo_letter_available return @gpo_letter_available if defined?(@gpo_letter_available) @gpo_letter_available ||= FeatureManagement.enable_gpo_verification? && - !Idv::GpoMail.new(current_user).mail_spammed? && - !(sp_session[:ial2_strict] && - !IdentityConfig.store.gpo_allowed_for_strict_ial2) + !Idv::GpoMail.new(current_user).mail_spammed? end end end diff --git a/app/controllers/idv/phone_errors_controller.rb b/app/controllers/idv/phone_errors_controller.rb index 1975f1ca19b..f059122fdb9 100644 --- a/app/controllers/idv/phone_errors_controller.rb +++ b/app/controllers/idv/phone_errors_controller.rb @@ -51,9 +51,7 @@ def track_event(type:) def set_gpo_letter_available return @gpo_letter_available if defined?(@gpo_letter_available) @gpo_letter_available ||= FeatureManagement.enable_gpo_verification? && - !Idv::GpoMail.new(current_user).mail_spammed? && - !(sp_session[:ial2_strict] && - !IdentityConfig.store.gpo_allowed_for_strict_ial2) + !Idv::GpoMail.new(current_user).mail_spammed? end # rubocop:enable Naming/MemoizedInstanceVariableName end diff --git a/app/controllers/openid_connect/authorization_controller.rb b/app/controllers/openid_connect/authorization_controller.rb index 8a203fe3d70..1c405a0047f 100644 --- a/app/controllers/openid_connect/authorization_controller.rb +++ b/app/controllers/openid_connect/authorization_controller.rb @@ -97,15 +97,10 @@ def track_authorize_analytics(result) end def identity_needs_verification? - ((@authorize_form.ial2_requested? || @authorize_form.ial2_strict_requested?) && + (@authorize_form.ial2_requested? && (current_user.decorate.identity_not_verified? || decorated_session.requested_more_recent_verification?)) || - current_user.decorate.reproof_for_irs?(service_provider: current_sp) || - identity_needs_strict_ial2_verification? - end - - def identity_needs_strict_ial2_verification? - @authorize_form.ial2_strict_requested? && !current_user.active_profile&.strict_ial2_proofed? + current_user.decorate.reproof_for_irs?(service_provider: current_sp) end def build_authorize_form_from_params diff --git a/app/forms/idv/api_document_verification_form.rb b/app/forms/idv/api_document_verification_form.rb index a37ab2faf95..cea36a88b5d 100644 --- a/app/forms/idv/api_document_verification_form.rb +++ b/app/forms/idv/api_document_verification_form.rb @@ -8,19 +8,16 @@ class ApiDocumentVerificationForm validates_presence_of :document_capture_session validates_presence_of :front_image_iv validates_presence_of :back_image_iv - validates_presence_of :selfie_image_iv, if: :liveness_checking_enabled? validate :throttle_if_rate_limited def initialize( params, - liveness_checking_enabled:, analytics:, irs_attempts_api_tracker:, flow_path: nil ) @params = params - @liveness_checking_enabled = liveness_checking_enabled @analytics = analytics @irs_attempts_api_tracker = irs_attempts_api_tracker @flow_path = flow_path @@ -50,10 +47,6 @@ def remaining_attempts throttle.remaining_count end - def liveness_checking_enabled? - @liveness_checking_enabled - end - def document_capture_session_uuid params[:document_capture_session_uuid] end @@ -80,10 +73,6 @@ def back_image_iv params[:back_image_iv] end - def selfie_image_iv - params[:selfie_image_iv] - end - def valid_url?(key) uri = params[key] parsed_uri = URI.parse(uri) @@ -124,13 +113,6 @@ def validate_image_urls type: :invalid_link ) end - return if valid_url?(:selfie_image_url) - if liveness_checking_enabled? - errors.add( - :selfie_image_url, invalid_link, - type: :invalid_link - ) - end end def invalid_link diff --git a/app/forms/idv/api_image_upload_form.rb b/app/forms/idv/api_image_upload_form.rb index d7e49856cbd..d3140475f06 100644 --- a/app/forms/idv/api_image_upload_form.rb +++ b/app/forms/idv/api_image_upload_form.rb @@ -5,16 +5,14 @@ class ApiImageUploadForm validates_presence_of :front validates_presence_of :back - validates_presence_of :selfie, if: :liveness_checking_enabled? validates_presence_of :document_capture_session validate :validate_images validate :throttle_if_rate_limited - def initialize(params, liveness_checking_enabled:, service_provider:, analytics: nil, + def initialize(params, service_provider:, analytics: nil, uuid_prefix: nil, irs_attempts_api_tracker: nil) @params = params - @liveness_checking_enabled = liveness_checking_enabled @service_provider = service_provider @analytics = analytics @readable = {} @@ -68,8 +66,8 @@ def post_images_to_client response = doc_auth_client.post_images( front_image: front.read, back_image: back.read, - selfie_image: selfie&.read, - liveness_checking_enabled: liveness_checking_enabled?, + selfie_image: nil, + liveness_checking_enabled: false, image_source: image_source, user_uuid: user_uuid, uuid_prefix: uuid_prefix, @@ -125,10 +123,6 @@ def determine_response(form_response:, client_response:, doc_pii_response:) client_response end - def liveness_checking_enabled? - @liveness_checking_enabled - end - def image_source if acuant_sdk_capture? DocAuth::ImageSources::ACUANT_SDK @@ -145,10 +139,6 @@ def back as_readable(:back) end - def selfie - as_readable(:selfie) - end - def document_capture_session @document_capture_session ||= DocumentCaptureSession.find_by( uuid: document_capture_session_uuid, @@ -168,12 +158,6 @@ def validate_images type: :not_a_file ) end - if selfie.is_a? DataUrlImage::InvalidUrlFormatError - errors.add( - :selfie, t('doc_auth.errors.not_a_file'), - type: :not_a_file - ) - end end def throttle_if_rate_limited @@ -272,13 +256,12 @@ def add_costs(response) Db::AddDocumentVerificationAndSelfieCosts. new(user_id: user_id, service_provider: service_provider, - liveness_checking_enabled: liveness_checking_enabled?). + liveness_checking_enabled: false). call(response) end def update_funnel(client_response) steps = %i[front_image back_image] - steps << :selfie if liveness_checking_enabled? steps.each do |step| Funnel::DocAuth::RegisterStep.new(user_id, service_provider&.issuer). call(step.to_s, :update, client_response.success?) diff --git a/app/forms/openid_connect_authorize_form.rb b/app/forms/openid_connect_authorize_form.rb index 6b540df4fd6..732d20264dd 100644 --- a/app/forms/openid_connect_authorize_form.rb +++ b/app/forms/openid_connect_authorize_form.rb @@ -41,7 +41,6 @@ class OpenidConnectAuthorizeForm validate :validate_prompt validate :validate_verified_within_format validate :validate_verified_within_duration - validate :validate_liveness_checking_enabled_if_ial2_strict_requested def initialize(params) @acr_values = parse_to_values(params[:acr_values], Saml::Idp::Constants::VALID_AUTHN_CONTEXTS) @@ -109,8 +108,7 @@ def ial def_delegators :ial_context, :ial2_or_greater?, - :ial2_requested?, - :ial2_strict_requested? + :ial2_requested? private @@ -249,12 +247,4 @@ def validate_privileges ) end end - - def validate_liveness_checking_enabled_if_ial2_strict_requested - return if !ial2_strict_requested? || FeatureManagement.liveness_checking_enabled? - errors.add( - :acr_values, t('openid_connect.authorization.errors.liveness_checking_disabled'), - type: :liveness_checking_disabled - ) - end end diff --git a/app/javascript/app/i18n-dropdown.js b/app/javascript/app/i18n-dropdown.js deleted file mode 100644 index 27f647b1ae8..00000000000 --- a/app/javascript/app/i18n-dropdown.js +++ /dev/null @@ -1,36 +0,0 @@ -const mobileLink = document.querySelector('.i18n-mobile-toggle > button'); -const mobileDropdown = document.querySelector('.i18n-mobile-dropdown'); -const desktopLink = document.querySelector('.i18n-desktop-toggle > button'); -const desktopDropdown = document.querySelector('.i18n-desktop-dropdown'); - -function addListenerMulti(el, s, fn) { - s.split(' ').forEach((e) => el.addEventListener(e, fn, false)); -} - -function toggleAriaExpanded(element) { - if (element.getAttribute('aria-expanded') === 'true') { - element.setAttribute('aria-expanded', 'false'); - } else { - element.setAttribute('aria-expanded', 'true'); - } -} - -function languagePicker(trigger, dropdown) { - addListenerMulti(trigger, 'click keypress', function (event) { - const eventType = event.type; - - event.preventDefault(); - if (eventType === 'click' || (eventType === 'keypress' && event.which === 13)) { - this.parentNode.classList.toggle('focused'); - dropdown.classList.toggle('display-none'); - toggleAriaExpanded(this); - } - }); -} - -if (desktopLink) { - languagePicker(desktopLink, desktopDropdown); -} -if (mobileLink) { - languagePicker(mobileLink, mobileDropdown); -} diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js deleted file mode 100644 index 357341aa427..00000000000 --- a/app/javascript/packs/application.js +++ /dev/null @@ -1,2 +0,0 @@ -require('../app/components/index'); -require('../app/i18n-dropdown'); diff --git a/app/javascript/app/components/index.js b/app/javascript/packs/application.ts similarity index 100% rename from app/javascript/app/components/index.js rename to app/javascript/packs/application.ts diff --git a/app/jobs/document_proofing_job.rb b/app/jobs/document_proofing_job.rb index bba37766167..3d578d4e16f 100644 --- a/app/jobs/document_proofing_job.rb +++ b/app/jobs/document_proofing_job.rb @@ -5,14 +5,15 @@ class DocumentProofingJob < ApplicationJob discard_on JobHelpers::StaleJobHelper::StaleJobError + # rubocop:disable Lint/UnusedMethodArgument def perform( result_id:, encrypted_arguments:, trace_id:, - liveness_checking_enabled:, image_metadata:, analytics_data:, - flow_path: + flow_path:, + liveness_checking_enabled: nil ) timer = JobHelpers::Timer.new @@ -32,10 +33,8 @@ def perform( encryption_key = Base64.decode64(document_args[:encryption_key].to_s) front_image_iv = Base64.decode64(document_args[:front_image_iv].to_s) back_image_iv = Base64.decode64(document_args[:back_image_iv].to_s) - selfie_image_iv = Base64.decode64(document_args[:selfie_image_iv].to_s) front_image_url = document_args[:front_image_url] back_image_url = document_args[:back_image_url] - selfie_image_url = document_args[:selfie_image_url] front_image = decrypt_image_from_s3( timer: timer, name: :front, url: front_image_url, iv: front_image_iv, key: encryption_key, @@ -43,12 +42,6 @@ def perform( back_image = decrypt_image_from_s3( timer: timer, name: :back, url: back_image_url, iv: back_image_iv, key: encryption_key, ) - if liveness_checking_enabled - selfie_image = decrypt_image_from_s3( - timer: timer, name: :selfie, url: selfie_image_url, iv: selfie_image_iv, - key: encryption_key - ) - end analytics = build_analytics(dcs) doc_auth_client = build_doc_auth_client(analytics, dcs) @@ -57,9 +50,9 @@ def perform( doc_auth_client.post_images( front_image: front_image, back_image: back_image, - selfie_image: selfie_image || '', + selfie_image: nil, image_source: image_source(image_metadata), - liveness_checking_enabled: liveness_checking_enabled, + liveness_checking_enabled: false, user_uuid: user_uuid, uuid_prefix: uuid_prefix, ) @@ -94,6 +87,7 @@ def perform( }.to_json, ) end + # rubocop:enable Lint/UnusedMethodArgument private diff --git a/app/jobs/get_usps_proofing_results_job.rb b/app/jobs/get_usps_proofing_results_job.rb index 208c0aab54f..e8a8c5197fd 100644 --- a/app/jobs/get_usps_proofing_results_job.rb +++ b/app/jobs/get_usps_proofing_results_job.rb @@ -103,25 +103,31 @@ def check_enrollments(enrollments) status_check_attempted_at = Time.zone.now enrollment_outcomes[:enrollments_checked] += 1 response = nil - errored = true begin response = proofer.request_proofing_results( enrollment.unique_id, enrollment.enrollment_code ) - errored = false rescue Faraday::BadRequestError => err + # 400 status code. This is used for some status updates and some common client errors handle_bad_request_error(err, enrollment) + rescue Faraday::ClientError, Faraday::ServerError => err + # 4xx or 5xx status code. These are unexpected but will have some sort of + # response body that we can try to log data from + handle_client_or_server_error(err, enrollment) + rescue Faraday::Error => err + # Timeouts, failed connections, parsing errors, and other HTTP errors. These + # generally won't have a response body + handle_faraday_error(err, enrollment) rescue StandardError => err - NewRelic::Agent.notice_error(err) handle_standard_error(err, enrollment) + else + process_enrollment_response(enrollment, response) + ensure + # Record the attempt to update the enrollment + enrollment.update(status_check_attempted_at: status_check_attempted_at) end - process_enrollment_response(enrollment, response) unless errored - - # Record the attempt to update the enrollment - enrollment.update(status_check_attempted_at: status_check_attempted_at) - # Sleep for a while before we attempt to make another call to USPS sleep request_delay_in_seconds if idx < enrollments.length - 1 end @@ -132,7 +138,8 @@ def analytics(user: AnonymousUser.new) end def handle_bad_request_error(err, enrollment) - case err.response&.[](:body)&.[]('responseMessage') + response = err.response_body + case response&.[]('responseMessage') when IPP_INCOMPLETE_ERROR_MESSAGE # Customer has not been to post office for IPP enrollment_outcomes[:enrollments_in_progress] += 1 @@ -141,29 +148,54 @@ def handle_bad_request_error(err, enrollment) else analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_exception( **enrollment_analytics_attributes(enrollment, complete: false), - **response_analytics_attributes(err.response), - reason: 'Request exception', + **response_analytics_attributes(response), exception_class: err.class.to_s, exception_message: err.message, + reason: 'Request exception', + response_status_code: err.response_status, ) enrollment_outcomes[:enrollments_errored] += 1 end end - def handle_standard_error(err, enrollment) - response_attributes = if err.respond_to?(:response) - response_analytics_attributes(err.response) - else - response_analytics_attributes(nil) - end + def handle_client_or_server_error(err, enrollment) + NewRelic::Agent.notice_error(err) + analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_exception( + **enrollment_analytics_attributes(enrollment, complete: false), + **response_analytics_attributes(err.response_body), + exception_class: err.class.to_s, + exception_message: err.message, + reason: 'Request exception', + response_status_code: err.response_status, + ) + enrollment_outcomes[:enrollments_errored] += 1 + end + def handle_faraday_error(err, enrollment) + NewRelic::Agent.notice_error(err) + analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_exception( + **enrollment_analytics_attributes(enrollment, complete: false), + # There probably isn't a response body or status for these types of errors but we try to log + # them in case there is + **response_analytics_attributes(err.response_body), + response_status_code: err.response_status, + exception_class: err.class.to_s, + exception_message: err.message, + reason: 'Request exception', + ) + enrollment_outcomes[:enrollments_errored] += 1 + end + + def handle_standard_error(err, enrollment) + NewRelic::Agent.notice_error(err) + response_attributes = response_analytics_attributes(nil) enrollment_outcomes[:enrollments_errored] += 1 analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_exception( **enrollment_analytics_attributes(enrollment, complete: false), **response_attributes, - reason: 'Request exception', exception_class: err.class.to_s, exception_message: err.message, + reason: 'Request exception', ) end @@ -238,7 +270,7 @@ def handle_successful_status_update(enrollment, response) enrollment_outcomes[:enrollments_passed] += 1 analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_enrollment_updated( **enrollment_analytics_attributes(enrollment, complete: true), - **response_analytics_attributes(**response), + **response_analytics_attributes(response), fraud_suspected: response['fraudSuspected'], passed: true, reason: 'Successful status update', diff --git a/app/models/profile.rb b/app/models/profile.rb index 10b496b228c..2ffc54c38d5 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -102,9 +102,7 @@ def includes_phone_check? def strict_ial2_proofed? return false unless active - return false unless includes_liveness_check? - return true if IdentityConfig.store.gpo_allowed_for_strict_ial2 - includes_phone_check? + includes_liveness_check? end def has_proofed_before? diff --git a/app/services/analytics.rb b/app/services/analytics.rb index fee5bf48573..394206f9c47 100644 --- a/app/services/analytics.rb +++ b/app/services/analytics.rb @@ -135,6 +135,4 @@ def session_started_at return value unless value.is_a?(String) Time.zone.parse(value) end - - DOC_AUTH = 'Doc Auth' # visited or submitted is appended end diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index 3e1935e0bae..032954f73b5 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -565,6 +565,22 @@ def idv_verify_in_person_troubleshooting_option_clicked(flow_path:, **extra) ) end + def idv_inherited_proofing_agreement_submitted(**extra) + track_event('Idv: inherited proofing agreement submitted', **extra) + end + + def idv_inherited_proofing_agreement_visited(**extra) + track_event('Idv: inherited proofing agreement visited', **extra) + end + + def idv_inherited_proofing_get_started_submitted(**extra) + track_event('Idv: inherited proofing get_started submitted', **extra) + end + + def idv_inherited_proofing_get_started_visited(**extra) + track_event('Idv: inherited proofing get_started visited', **extra) + end + # @param [String] flow_path Document capture path ("hybrid" or "standard") # The user visited the in person proofing location step def idv_in_person_location_visited(flow_path:, **extra) @@ -595,6 +611,34 @@ def idv_in_person_prepare_submitted(flow_path:, **extra) track_event('IdV: in person proofing prepare submitted', flow_path: flow_path, **extra) end + def idv_in_person_proofing_address_submitted(**extra) + track_event('IdV: in person proofing address submitted', **extra) + end + + def idv_in_person_proofing_address_visited(**extra) + track_event('IdV: in person proofing address visited', **extra) + end + + def idv_in_person_proofing_cancel_update_address(**extra) + track_event('IdV: in person proofing cancel_update_address submitted', **extra) + end + + def idv_in_person_proofing_cancel_update_state_id(**extra) + track_event('IdV: in person proofing cancel_update_state_id submitted', **extra) + end + + def idv_in_person_proofing_redo_state_id_submitted(**extra) + track_event('IdV: in person proofing redo_state_id submitted', **extra) + end + + def idv_in_person_proofing_state_id_submitted(**extra) + track_event('IdV: in person proofing state_id submitted', **extra) + end + + def idv_in_person_proofing_state_id_visited(**extra) + track_event('IdV: in person proofing state_id visited', **extra) + end + # @param [String] flow_path Document capture path ("hybrid" or "standard") # The user visited the in person proofing switch_back step def idv_in_person_switch_back_visited(flow_path:, **extra) @@ -617,6 +661,43 @@ def idv_in_person_ready_to_verify_visit(proofing_components: nil, **extra) ) end + def idv_doc_auth_agreement_submitted(**extra) + track_event('IdV: doc auth agreement submitted', **extra) + end + + def idv_doc_auth_agreement_visited(**extra) + track_event('IdV: doc auth agreement visited', **extra) + end + + def idv_doc_auth_cancel_link_sent_submitted(**extra) + track_event('IdV: doc auth cancel_link_sent submitted', **extra) + end + + def idv_doc_auth_cancel_send_link_submitted(**extra) + track_event('IdV: doc auth cancel_send_link submitted', **extra) + end + + # @identity.idp.previous_event_name IdV: in person proofing cancel_update_ssn submitted + def idv_doc_auth_cancel_update_ssn_submitted(**extra) + track_event('IdV: doc auth cancel_update_ssn submitted', **extra) + end + + def idv_doc_auth_capture_complete_visited(**extra) + track_event('IdV: doc auth capture_complete visited', **extra) + end + + def idv_doc_auth_document_capture_visited(**extra) + track_event('IdV: doc auth document_capture visited', **extra) + end + + def idv_doc_auth_document_capture_submitted(**extra) + track_event('IdV: doc auth document_capture submitted', **extra) + end + + def idv_doc_auth_email_sent_visited(**extra) + track_event('IdV: doc auth email_sent visited', **extra) + end + # @param [String] step_name which step the user was on # @param [Integer] remaining_attempts how many attempts the user has left before we throttle them # The user visited an error page due to an encountering an exception talking to a proofing vendor @@ -629,6 +710,50 @@ def idv_doc_auth_exception_visited(step_name:, remaining_attempts:, **extra) ) end + def idv_doc_auth_link_sent_submitted(**extra) + track_event('IdV: doc auth send_link submitted', **extra) + end + + def idv_doc_auth_link_sent_visited(**extra) + track_event('IdV: doc auth link_sent visited', **extra) + end + + # @identity.idp.previous_event_name IdV: in person proofing optional verify_wait submitted + def idv_doc_auth_optional_verify_wait_submitted(**extra) + track_event('IdV: doc auth optional verify_wait submitted', **extra) + end + + def idv_doc_auth_redo_document_capture_submitted(**extra) + track_event('IdV: doc auth redo_document_capture submitted', **extra) + end + + def idv_doc_auth_send_link_visited(**extra) + track_event('IdV: doc auth send_link visited', **extra) + end + + def idv_doc_auth_send_link_submitted(**extra) + track_event('IdV: doc auth send_link submitted', **extra) + end + + # @identity.idp.previous_event_name IdV: in person proofing ssn submitted + def idv_doc_auth_ssn_submitted(**extra) + track_event('IdV: doc auth ssn submitted', **extra) + end + + # @identity.idp.previous_event_name IdV: in person proofing ssn visited + def idv_doc_auth_ssn_visited(**extra) + track_event('IdV: doc auth ssn visited', **extra) + end + + # @identity.idp.previous_event_name IdV: in person proofing redo_address submitted + def idv_doc_auth_redo_address_submitted(**extra) + track_event('IdV: doc auth redo_address submitted', **extra) + end + + def idv_doc_auth_redo_ssn_submitted(**extra) + track_event('IdV: doc auth redo_ssn submitted', **extra) + end + # @param [Boolean] success # @param [Hash] errors # @param [Integer] attempts @@ -737,6 +862,33 @@ def idv_doc_auth_submitted_pii_validation( ) end + def idv_doc_auth_upload_submitted(**extra) + track_event('IdV: doc auth upload submitted', **extra) + end + + def idv_doc_auth_upload_visited(**extra) + track_event('IdV: doc auth upload visited', **extra) + end + + def idv_doc_auth_verify_document_status_submitted(**extra) + track_event('IdV: doc auth verify_document_status submitted', **extra) + end + + # @identity.idp.previous_event_name IdV: in person proofing verify submitted + def idv_doc_auth_verify_submitted(**extra) + track_event('IdV: doc auth verify submitted', **extra) + end + + # @identity.idp.previous_event_name IdV: in person proofing verify visited + def idv_doc_auth_verify_visited(**extra) + track_event('IdV: doc auth verify visited', **extra) + end + + # @identity.idp.previous_event_name IdV: in person proofing verify_wait visited + def idv_doc_auth_verify_wait_step_visited(**extra) + track_event('IdV: doc auth verify_wait visited', **extra) + end + # @param [String] step_name # @param [Integer] remaining_attempts # The user was sent to a warning page during the IDV flow @@ -753,6 +905,14 @@ def idv_doc_auth_warning_visited( ) end + def idv_doc_auth_welcome_submitted(**extra) + track_event('IdV: doc auth welcome submitted', **extra) + end + + def idv_doc_auth_welcome_visited(**extra) + track_event('IdV: doc auth welcome visited', **extra) + end + # @param [Idv::ProofingComponentsLogging] proofing_components User's current proofing components # User visited forgot password page def idv_forgot_password(proofing_components: nil, **extra) @@ -2834,6 +2994,7 @@ def idv_in_person_usps_proofing_results_job_completed( # @param [String] proofing_state # @param [String] scan_count # @param [String] response_message + # @param [Integer] response_status_code def idv_in_person_usps_proofing_results_job_exception( reason:, enrollment_id:, @@ -2856,6 +3017,7 @@ def idv_in_person_usps_proofing_results_job_exception( proofing_state: nil, scan_count: nil, response_message: nil, + response_status_code: nil, **extra ) track_event( @@ -2881,6 +3043,7 @@ def idv_in_person_usps_proofing_results_job_exception( proofing_state: proofing_state, scan_count: scan_count, response_message: response_message, + response_status_code: response_status_code, **extra, ) end diff --git a/app/services/arcgis_api/geocoder.rb b/app/services/arcgis_api/geocoder.rb index 7b14b5775a3..dfc80c56a9c 100644 --- a/app/services/arcgis_api/geocoder.rb +++ b/app/services/arcgis_api/geocoder.rb @@ -1,8 +1,23 @@ module ArcgisApi class Geocoder Suggestion = Struct.new(:text, :magic_key, keyword_init: true) + AddressCandidate = Struct.new( + :address, :location, :street_address, :city, :state, :zip_code, + keyword_init: true + ) + Location = Struct.new(:latitude, :longitude, keyword_init: true) - # Makes HTTP request to get potential address matches + # These are option URL params that tend to apply to multiple endpoints + # https://developers.arcgis.com/rest/geocode/api-reference/geocoding-find-address-candidates.htm#ESRI_SECTION2_38613C3FCB12462CAADD55B2905140BF + COMMON_DEFAULT_PARAMETERS = { + f: 'json', + countryCode: 'USA', + category: 'address', + }.freeze + + # Makes an HTTP request to quickly find potential address matches. Each match that is found + # will include an associated magic_key value which can later be used to get more details about + # the address using the #find_address_candidates method # Requests text input and will only match possible addresses # A maximum of 5 suggestions are included in the suggestions array. # @param text [String] @@ -11,9 +26,7 @@ def suggest(text) url = "#{root_url}/suggest" params = { text: text, - category: 'address', - countryCode: 'USA', - f: 'json', + **COMMON_DEFAULT_PARAMETERS, } parse_suggestions( @@ -23,6 +36,24 @@ def suggest(text) ) end + # Makes HTTP request to find an exact address using magic_key + # @param magic_key [String] a magic key value from a previous call to the #suggest method + # @return [Array] AddressCandidates + def find_address_candidates(magic_key) + url = "#{root_url}/findAddressCandidates" + params = { + magicKey: magic_key, + outFields: 'StAddr,City,RegionAbbr,Postal', + **COMMON_DEFAULT_PARAMETERS, + } + + parse_address_candidates( + faraday.get(url, params) do |req| + req.options.context = { service_name: 'arcgis_geocoder_find_address_candidates' } + end.body, + ) + end + private def root_url @@ -48,6 +79,39 @@ def request_headers end def parse_suggestions(response_body) + handle_api_errors(response_body) + + response_body['suggestions'].map do |suggestion| + Suggestion.new( + text: suggestion['text'], + magic_key: suggestion['magicKey'], + ) + end + end + + def parse_address_candidates(response_body) + handle_api_errors(response_body) + + response_body['candidates'].map do |candidate| + AddressCandidate.new( + address: candidate['address'], + location: Location.new( + longitude: candidate.dig('location', 'x'), + latitude: candidate.dig( + 'location', 'y' + ), + ), + street_address: candidate.dig('attributes', 'StAddr'), + city: candidate.dig('attributes', 'City'), + state: candidate.dig('attributes', 'RegionAbbr'), + zip_code: candidate.dig('attributes', 'Postal'), + ) + end + end + + # handles API error state when returned as a status of 200 + # @param response_body [Hash] + def handle_api_errors(response_body) if response_body['error'] error_code = response_body.dig('error', 'code') @@ -56,13 +120,6 @@ def parse_suggestions(response_body) response_body, ) end - - response_body['suggestions'].map do |suggestion| - Suggestion.new( - text: suggestion['text'], - magic_key: suggestion['magicKey'], - ) - end end end end diff --git a/app/services/flow/flow_state_machine.rb b/app/services/flow/flow_state_machine.rb index 256fcc1adf1..cc0e06f7c14 100644 --- a/app/services/flow/flow_state_machine.rb +++ b/app/services/flow/flow_state_machine.rb @@ -21,10 +21,12 @@ def show 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)) - end + + increment_step_name_counts + analytics.public_send( + flow.step_handler(step).analytics_submitted_event, + **result.to_h.merge(analytics_properties), + ) register_update_step(step, result) if flow.json @@ -46,10 +48,12 @@ def current_step end def track_step_visited - if @analytics_id - increment_step_name_counts - analytics.track_event(analytics_visited, analytics_properties) - end + increment_step_name_counts + analytics.public_send( + flow.step_handler(current_step).analytics_visited_event, + **analytics_properties, + ) + Funnel::DocAuth::RegisterStep.new(user_id, issuer).call(current_step, :view, true) end @@ -121,12 +125,16 @@ def call_optional_show_step(optional_step) return unless optional_show_step result = optional_show_step.new(@flow).base_call - if @analytics_id - optional_show_step_name = optional_show_step.to_s.demodulize.underscore - optional_properties = result.to_h.merge(step: optional_show_step_name) + optional_show_step_name = optional_show_step.to_s.demodulize.underscore + optional_properties = result.to_h.merge( + step: optional_show_step_name, + analytics_id: @analytics_id, + ) - analytics.track_event(analytics_optional_step, optional_properties) - end + analytics.public_send( + optional_show_step.analytics_optional_step_event, + **optional_properties, + ) if next_step.to_s != optional_step if next_step_is_url @@ -162,23 +170,12 @@ def redirect_to_step(step) redirect_to send(@step_url, 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 analytics_properties { flow_path: @flow.flow_path, step: current_step, step_count: current_flow_step_counts[current_step_name], + analytics_id: @analytics_id, } end diff --git a/app/services/idv/actions/cancel_link_sent_action.rb b/app/services/idv/actions/cancel_link_sent_action.rb index b8ebc0b2e93..5d5d51d8bca 100644 --- a/app/services/idv/actions/cancel_link_sent_action.rb +++ b/app/services/idv/actions/cancel_link_sent_action.rb @@ -1,6 +1,10 @@ module Idv module Actions class CancelLinkSentAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_doc_auth_cancel_link_sent_submitted + end + def call mark_step_incomplete(:send_link) end diff --git a/app/services/idv/actions/cancel_send_link_action.rb b/app/services/idv/actions/cancel_send_link_action.rb index 8d9fe50ce29..1bf64fefef9 100644 --- a/app/services/idv/actions/cancel_send_link_action.rb +++ b/app/services/idv/actions/cancel_send_link_action.rb @@ -1,6 +1,10 @@ module Idv module Actions class CancelSendLinkAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_doc_auth_cancel_send_link_submitted + end + def call mark_step_incomplete(:upload) end diff --git a/app/services/idv/actions/cancel_update_ssn_action.rb b/app/services/idv/actions/cancel_update_ssn_action.rb index 06341459f09..d8b7b52b82d 100644 --- a/app/services/idv/actions/cancel_update_ssn_action.rb +++ b/app/services/idv/actions/cancel_update_ssn_action.rb @@ -1,6 +1,10 @@ module Idv module Actions class CancelUpdateSsnAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_doc_auth_cancel_update_ssn_submitted + end + def call mark_step_complete(:ssn) if flow_session.dig(:pii_from_doc, :ssn) end diff --git a/app/services/idv/actions/in_person/cancel_update_address_action.rb b/app/services/idv/actions/in_person/cancel_update_address_action.rb index 5732f833814..bbb687dee38 100644 --- a/app/services/idv/actions/in_person/cancel_update_address_action.rb +++ b/app/services/idv/actions/in_person/cancel_update_address_action.rb @@ -2,6 +2,10 @@ module Idv module Actions module InPerson class CancelUpdateAddressAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_in_person_proofing_cancel_update_address + end + def call mark_step_complete(:address) if flow_session.dig(:pii_from_user, :address1) end diff --git a/app/services/idv/actions/in_person/cancel_update_ssn_action.rb b/app/services/idv/actions/in_person/cancel_update_ssn_action.rb index c2219ae47af..b4320ca4ee0 100644 --- a/app/services/idv/actions/in_person/cancel_update_ssn_action.rb +++ b/app/services/idv/actions/in_person/cancel_update_ssn_action.rb @@ -2,6 +2,10 @@ module Idv module Actions module InPerson class CancelUpdateSsnAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_doc_auth_cancel_update_ssn_submitted + end + def call mark_step_complete(:ssn) if flow_session.dig(:pii_from_user, :ssn) end diff --git a/app/services/idv/actions/in_person/cancel_update_state_id_action.rb b/app/services/idv/actions/in_person/cancel_update_state_id_action.rb index a98a6a37ef7..5ec79a7b0f1 100644 --- a/app/services/idv/actions/in_person/cancel_update_state_id_action.rb +++ b/app/services/idv/actions/in_person/cancel_update_state_id_action.rb @@ -2,6 +2,10 @@ module Idv module Actions module InPerson class CancelUpdateStateIdAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_in_person_proofing_cancel_update_state_id + end + def call mark_step_complete(:state_id) if flow_session.dig(:pii_from_user, :first_name) end diff --git a/app/services/idv/actions/in_person/redo_address_action.rb b/app/services/idv/actions/in_person/redo_address_action.rb index d37321e4f98..dc88870c023 100644 --- a/app/services/idv/actions/in_person/redo_address_action.rb +++ b/app/services/idv/actions/in_person/redo_address_action.rb @@ -2,6 +2,10 @@ module Idv module Actions module InPerson class RedoAddressAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_doc_auth_redo_address_submitted + end + def call mark_step_incomplete(:address) end diff --git a/app/services/idv/actions/in_person/redo_state_id_action.rb b/app/services/idv/actions/in_person/redo_state_id_action.rb index dba901b8211..dd7025865e7 100644 --- a/app/services/idv/actions/in_person/redo_state_id_action.rb +++ b/app/services/idv/actions/in_person/redo_state_id_action.rb @@ -2,6 +2,10 @@ module Idv module Actions module InPerson class RedoStateIdAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_in_person_proofing_redo_state_id_submitted + end + def call mark_step_incomplete(:state_id) end diff --git a/app/services/idv/actions/redo_address_action.rb b/app/services/idv/actions/redo_address_action.rb index a67f6c29ecd..ce9b404cc8b 100644 --- a/app/services/idv/actions/redo_address_action.rb +++ b/app/services/idv/actions/redo_address_action.rb @@ -1,6 +1,10 @@ module Idv module Actions class RedoAddressAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_doc_auth_redo_address_submitted + end + def call redirect_to idv_address_url end diff --git a/app/services/idv/actions/redo_document_capture_action.rb b/app/services/idv/actions/redo_document_capture_action.rb index 0b86b50b4ff..2e0fa2a7fd9 100644 --- a/app/services/idv/actions/redo_document_capture_action.rb +++ b/app/services/idv/actions/redo_document_capture_action.rb @@ -1,6 +1,10 @@ module Idv module Actions class RedoDocumentCaptureAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_doc_auth_redo_document_capture_submitted + end + def call mark_step_incomplete(:document_capture) unless flow_session[:skip_upload_step] diff --git a/app/services/idv/actions/redo_ssn_action.rb b/app/services/idv/actions/redo_ssn_action.rb index 2d85686f527..0c0f69c9db9 100644 --- a/app/services/idv/actions/redo_ssn_action.rb +++ b/app/services/idv/actions/redo_ssn_action.rb @@ -1,6 +1,10 @@ module Idv module Actions class RedoSsnAction < Idv::Steps::DocAuthBaseStep + def self.analytics_submitted_event + :idv_doc_auth_redo_ssn_submitted + end + def call mark_step_incomplete(:ssn) end diff --git a/app/services/idv/actions/verify_document_status_action.rb b/app/services/idv/actions/verify_document_status_action.rb index 83f45c80ebc..0acc60cc377 100644 --- a/app/services/idv/actions/verify_document_status_action.rb +++ b/app/services/idv/actions/verify_document_status_action.rb @@ -5,6 +5,10 @@ def call process_async_state(async_state) end + def self.analytics_submitted_event + :idv_doc_auth_verify_document_status_submitted + end + private def process_async_state(current_async_state) diff --git a/app/services/idv/agent.rb b/app/services/idv/agent.rb index e0356c89ffe..4887733d883 100644 --- a/app/services/idv/agent.rb +++ b/app/services/idv/agent.rb @@ -61,7 +61,6 @@ def proof_address(document_capture_session, user_id:, issuer:, trace_id:) def proof_document( document_capture_session, - liveness_checking_enabled:, trace_id:, image_metadata:, analytics_data:, @@ -73,7 +72,6 @@ def proof_document( DocumentProofingJob.perform_later( encrypted_arguments: encrypted_arguments, - liveness_checking_enabled: liveness_checking_enabled, result_id: document_capture_session.result_id, trace_id: trace_id, image_metadata: image_metadata, diff --git a/app/services/idv/steps/agreement_step.rb b/app/services/idv/steps/agreement_step.rb index f65657dd5cf..44171846b07 100644 --- a/app/services/idv/steps/agreement_step.rb +++ b/app/services/idv/steps/agreement_step.rb @@ -3,6 +3,14 @@ module Steps class AgreementStep < DocAuthBaseStep STEP_INDICATOR_STEP = :getting_started + def self.analytics_visited_event + :idv_doc_auth_agreement_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_agreement_submitted + end + def call end diff --git a/app/services/idv/steps/capture_complete_step.rb b/app/services/idv/steps/capture_complete_step.rb index b6fb435cb88..b5e30cf6f6c 100644 --- a/app/services/idv/steps/capture_complete_step.rb +++ b/app/services/idv/steps/capture_complete_step.rb @@ -3,6 +3,10 @@ module Steps class CaptureCompleteStep < DocAuthBaseStep STEP_INDICATOR_STEP = :verify_id + def self.analytics_visited_event + :idv_doc_auth_capture_complete_visited + end + def call; end end end diff --git a/app/services/idv/steps/document_capture_step.rb b/app/services/idv/steps/document_capture_step.rb index 35cc4de2905..12d34952bad 100644 --- a/app/services/idv/steps/document_capture_step.rb +++ b/app/services/idv/steps/document_capture_step.rb @@ -5,6 +5,14 @@ class DocumentCaptureStep < DocAuthBaseStep front_image back_image selfie_image ].freeze + def self.analytics_visited_event + :idv_doc_auth_document_capture_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_document_capture_submitted + end + def call handle_stored_result if !FeatureManagement.document_capture_async_uploads_enabled? end diff --git a/app/services/idv/steps/email_sent_step.rb b/app/services/idv/steps/email_sent_step.rb index 94a71b5b034..c5b75c8c43e 100644 --- a/app/services/idv/steps/email_sent_step.rb +++ b/app/services/idv/steps/email_sent_step.rb @@ -3,6 +3,10 @@ module Steps class EmailSentStep < DocAuthBaseStep STEP_INDICATOR_STEP = :verify_id + def self.analytics_visited_event + :idv_doc_auth_email_sent_visited + end + def call; end end end diff --git a/app/services/idv/steps/in_person/address_step.rb b/app/services/idv/steps/in_person/address_step.rb index 8a0ae5aa5d8..43c58c72e87 100644 --- a/app/services/idv/steps/in_person/address_step.rb +++ b/app/services/idv/steps/in_person/address_step.rb @@ -4,6 +4,14 @@ module InPerson class AddressStep < DocAuthBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_visited_event + :idv_in_person_proofing_address_visited + end + + def self.analytics_submitted_event + :idv_in_person_proofing_address_submitted + end + def call Idv::InPerson::AddressForm::ATTRIBUTES.each do |attr| flow_session[:pii_from_user][attr] = flow_params[attr] diff --git a/app/services/idv/steps/in_person/ssn_step.rb b/app/services/idv/steps/in_person/ssn_step.rb index cb2f3491032..afd168ae626 100644 --- a/app/services/idv/steps/in_person/ssn_step.rb +++ b/app/services/idv/steps/in_person/ssn_step.rb @@ -6,6 +6,14 @@ class SsnStep < DocAuthBaseStep include ThreatMetrixStepHelper + def self.analytics_visited_event + :idv_doc_auth_ssn_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_ssn_submitted + end + def call flow_session[:pii_from_user][:ssn] = ssn diff --git a/app/services/idv/steps/in_person/state_id_step.rb b/app/services/idv/steps/in_person/state_id_step.rb index c90d8383f62..3afeb3f0d4c 100644 --- a/app/services/idv/steps/in_person/state_id_step.rb +++ b/app/services/idv/steps/in_person/state_id_step.rb @@ -4,6 +4,14 @@ module InPerson class StateIdStep < DocAuthBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_visited_event + :idv_in_person_proofing_state_id_visited + end + + def self.analytics_submitted_event + :idv_in_person_proofing_state_id_submitted + end + def call Idv::StateIdForm::ATTRIBUTES.each do |attr| flow_session[:pii_from_user][attr] = flow_params[attr] diff --git a/app/services/idv/steps/in_person/verify_step.rb b/app/services/idv/steps/in_person/verify_step.rb index 5d5c837cc4e..3203dd4846d 100644 --- a/app/services/idv/steps/in_person/verify_step.rb +++ b/app/services/idv/steps/in_person/verify_step.rb @@ -4,6 +4,14 @@ module InPerson class VerifyStep < VerifyBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_visited_event + :idv_doc_auth_verify_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_verify_submitted + end + def call pii[:state_id_type] = 'drivers_license' unless invalid_state? add_proofing_component diff --git a/app/services/idv/steps/in_person/verify_wait_step.rb b/app/services/idv/steps/in_person/verify_wait_step.rb index 297ee837099..ee0ee168d54 100644 --- a/app/services/idv/steps/in_person/verify_wait_step.rb +++ b/app/services/idv/steps/in_person/verify_wait_step.rb @@ -4,6 +4,10 @@ module InPerson class VerifyWaitStep < VerifyBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_visited_event + :idv_doc_auth_verify_wait_step_visited + end + def call; end end end diff --git a/app/services/idv/steps/in_person/verify_wait_step_show.rb b/app/services/idv/steps/in_person/verify_wait_step_show.rb index b3ef39b7fbe..d16c14304be 100644 --- a/app/services/idv/steps/in_person/verify_wait_step_show.rb +++ b/app/services/idv/steps/in_person/verify_wait_step_show.rb @@ -4,6 +4,10 @@ module InPerson class VerifyWaitStepShow < VerifyBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_optional_step_event + :idv_doc_auth_optional_verify_wait_submitted + end + def call poll_with_meta_refresh(IdentityConfig.store.poll_rate_for_verify_in_seconds) diff --git a/app/services/idv/steps/inherited_proofing/agreement_step.rb b/app/services/idv/steps/inherited_proofing/agreement_step.rb index 301112f93fc..c3b125b24c0 100644 --- a/app/services/idv/steps/inherited_proofing/agreement_step.rb +++ b/app/services/idv/steps/inherited_proofing/agreement_step.rb @@ -5,6 +5,14 @@ class AgreementStep < VerifyBaseStep delegate :controller, :idv_session, to: :@flow STEP_INDICATOR_STEP = :getting_started + def self.analytics_visited_event + :idv_inherited_proofing_agreement_visited + end + + def self.analytics_submitted_event + :idv_inherited_proofing_agreement_submitted + end + def call enqueue_job end @@ -24,7 +32,7 @@ def enqueue_job inherited_proofing_verify_step_document_capture_session_uuid_key, ) - doc_capture_session.create_doc_auth_session + doc_capture_session.create_proofing_session InheritedProofingJob.perform_later( controller.inherited_proofing_service_provider, diff --git a/app/services/idv/steps/inherited_proofing/get_started_step.rb b/app/services/idv/steps/inherited_proofing/get_started_step.rb index af5c7489a2e..7afedc41f9b 100644 --- a/app/services/idv/steps/inherited_proofing/get_started_step.rb +++ b/app/services/idv/steps/inherited_proofing/get_started_step.rb @@ -4,6 +4,14 @@ module InheritedProofing class GetStartedStep < InheritedProofingBaseStep STEP_INDICATOR_STEP = :getting_started + def self.analytics_visited_event + :idv_inherited_proofing_get_started_visited + end + + def self.analytics_submitted_event + :idv_inherited_proofing_get_started_submitted + end + def call end end diff --git a/app/services/idv/steps/inherited_proofing/verify_info_step.rb b/app/services/idv/steps/inherited_proofing/verify_info_step.rb index 02ddfda63d6..b54f4e26e91 100644 --- a/app/services/idv/steps/inherited_proofing/verify_info_step.rb +++ b/app/services/idv/steps/inherited_proofing/verify_info_step.rb @@ -4,6 +4,14 @@ module InheritedProofing class VerifyInfoStep < InheritedProofingBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_visited_event + :idv_doc_auth_verify_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_verify_submitted + end + def call end diff --git a/app/services/idv/steps/inherited_proofing/verify_wait_step.rb b/app/services/idv/steps/inherited_proofing/verify_wait_step.rb index 3dfac80bbd4..856d20a55e7 100644 --- a/app/services/idv/steps/inherited_proofing/verify_wait_step.rb +++ b/app/services/idv/steps/inherited_proofing/verify_wait_step.rb @@ -4,6 +4,10 @@ module InheritedProofing class VerifyWaitStep < InheritedProofingBaseStep STEP_INDICATOR_STEP = :getting_started + def self.analytics_visited_event + :idv_doc_auth_verify_wait_step_visited + end + def call; end end end diff --git a/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb b/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb index 231c1e7014f..f66490c971e 100644 --- a/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb +++ b/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb @@ -8,6 +8,10 @@ class VerifyWaitStepShow < VerifyBaseStep STEP_INDICATOR_STEP = :getting_started + def self.analytics_optional_step_event + :idv_doc_auth_optional_verify_wait_submitted + end + def call poll_with_meta_refresh(IdentityConfig.store.poll_rate_for_verify_in_seconds) diff --git a/app/services/idv/steps/link_sent_step.rb b/app/services/idv/steps/link_sent_step.rb index a7b8bb3a8fa..3d93ca64799 100644 --- a/app/services/idv/steps/link_sent_step.rb +++ b/app/services/idv/steps/link_sent_step.rb @@ -5,6 +5,14 @@ class LinkSentStep < DocAuthBaseStep HYBRID_FLOW_STEPS = %i[upload send_link link_sent email_sent document_capture] + def self.analytics_visited_event + :idv_doc_auth_link_sent_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_link_sent_submitted + end + def call return render_document_capture_cancelled if document_capture_session&.cancelled_at return render_step_incomplete_error unless take_photo_with_phone_successful? diff --git a/app/services/idv/steps/send_link_step.rb b/app/services/idv/steps/send_link_step.rb index 9d2eadf42a9..2b5d2515a43 100644 --- a/app/services/idv/steps/send_link_step.rb +++ b/app/services/idv/steps/send_link_step.rb @@ -5,6 +5,14 @@ class SendLinkStep < DocAuthBaseStep STEP_INDICATOR_STEP = :verify_id + def self.analytics_visited_event + :idv_doc_auth_send_link_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_send_link_submitted + end + def call return throttled_failure if throttle.throttled_else_increment? telephony_result = send_link diff --git a/app/services/idv/steps/ssn_step.rb b/app/services/idv/steps/ssn_step.rb index 454bdd075ef..081c272a7d4 100644 --- a/app/services/idv/steps/ssn_step.rb +++ b/app/services/idv/steps/ssn_step.rb @@ -5,6 +5,14 @@ class SsnStep < DocAuthBaseStep include ThreatMetrixStepHelper + def self.analytics_visited_event + :idv_doc_auth_ssn_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_ssn_submitted + end + def call return invalid_state_response if invalid_state? diff --git a/app/services/idv/steps/upload_step.rb b/app/services/idv/steps/upload_step.rb index 039b91aebe8..938878121a8 100644 --- a/app/services/idv/steps/upload_step.rb +++ b/app/services/idv/steps/upload_step.rb @@ -3,6 +3,14 @@ module Steps class UploadStep < DocAuthBaseStep STEP_INDICATOR_STEP = :verify_id + def self.analytics_visited_event + :idv_doc_auth_upload_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_upload_submitted + end + def call @flow.irs_attempts_api_tracker.idv_document_upload_method_selected( upload_method: params[:type], diff --git a/app/services/idv/steps/verify_step.rb b/app/services/idv/steps/verify_step.rb index da16f242e65..ef3fa383bc0 100644 --- a/app/services/idv/steps/verify_step.rb +++ b/app/services/idv/steps/verify_step.rb @@ -3,6 +3,14 @@ module Steps class VerifyStep < VerifyBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_visited_event + :idv_doc_auth_verify_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_verify_submitted + end + def call enqueue_job end diff --git a/app/services/idv/steps/verify_wait_step.rb b/app/services/idv/steps/verify_wait_step.rb index 01068d2c3f4..ee4f43d5326 100644 --- a/app/services/idv/steps/verify_wait_step.rb +++ b/app/services/idv/steps/verify_wait_step.rb @@ -3,6 +3,10 @@ module Steps class VerifyWaitStep < VerifyBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_visited_event + :idv_doc_auth_verify_wait_step_visited + end + def call; end end end diff --git a/app/services/idv/steps/verify_wait_step_show.rb b/app/services/idv/steps/verify_wait_step_show.rb index 262358d5289..2292b7261d0 100644 --- a/app/services/idv/steps/verify_wait_step_show.rb +++ b/app/services/idv/steps/verify_wait_step_show.rb @@ -3,6 +3,10 @@ module Steps class VerifyWaitStepShow < VerifyBaseStep STEP_INDICATOR_STEP = :verify_info + def self.analytics_optional_step_event + :idv_doc_auth_optional_verify_wait_submitted + end + def call poll_with_meta_refresh(IdentityConfig.store.poll_rate_for_verify_in_seconds) diff --git a/app/services/idv/steps/welcome_step.rb b/app/services/idv/steps/welcome_step.rb index 92ff02bf433..1a5744a5e94 100644 --- a/app/services/idv/steps/welcome_step.rb +++ b/app/services/idv/steps/welcome_step.rb @@ -3,6 +3,14 @@ module Steps class WelcomeStep < DocAuthBaseStep STEP_INDICATOR_STEP = :getting_started + def self.analytics_visited_event + :idv_doc_auth_welcome_visited + end + + def self.analytics_submitted_event + :idv_doc_auth_welcome_submitted + end + def call return no_camera_redirect if params[:no_camera] create_document_capture_session(document_capture_session_uuid_key) diff --git a/app/services/usps_in_person_proofing/mock/fixtures.rb b/app/services/usps_in_person_proofing/mock/fixtures.rb index 515ee89451e..8a508d6e128 100644 --- a/app/services/usps_in_person_proofing/mock/fixtures.rb +++ b/app/services/usps_in_person_proofing/mock/fixtures.rb @@ -1,6 +1,10 @@ module UspsInPersonProofing module Mock class Fixtures + def self.internal_server_error_response + load_response_fixture('internal_server_error_response.json') + end + def self.request_token_response load_response_fixture('request_token_response.json') end @@ -25,10 +29,6 @@ def self.request_enroll_bad_request_response load_response_fixture('request_enroll_failed_response.json') end - def self.request_enroll_internal_failure_response - load_response_fixture('request_enroll_internal_failure_response.json') - end - def self.request_enroll_invalid_response load_response_fixture('request_enroll_invalid_response.json') end diff --git a/app/services/usps_in_person_proofing/mock/proofer.rb b/app/services/usps_in_person_proofing/mock/proofer.rb index 8005697a173..b4688eb1363 100644 --- a/app/services/usps_in_person_proofing/mock/proofer.rb +++ b/app/services/usps_in_person_proofing/mock/proofer.rb @@ -13,7 +13,7 @@ def request_enroll(applicant) raise Faraday::BadRequestError.new('Bad request error', response) when 'usps server error' # usps 500 response - body = JSON.parse(Fixtures.request_enroll_internal_failure_response) + body = JSON.parse(Fixtures.internal_server_error_response) response = { body: body, status: 500 } raise Faraday::ServerError.new('Internal server error', response) when 'usps invalid response' diff --git a/app/services/usps_in_person_proofing/mock/responses/request_enroll_internal_failure_response.json b/app/services/usps_in_person_proofing/mock/responses/internal_server_error_response.json similarity index 100% rename from app/services/usps_in_person_proofing/mock/responses/request_enroll_internal_failure_response.json rename to app/services/usps_in_person_proofing/mock/responses/internal_server_error_response.json diff --git a/app/views/layouts/component_preview.html.erb b/app/views/layouts/component_preview.html.erb index c94ab975617..1e027b3c237 100644 --- a/app/views/layouts/component_preview.html.erb +++ b/app/views/layouts/component_preview.html.erb @@ -4,8 +4,8 @@ Component Preview <%= stylesheet_link_tag 'application', media: 'all' %> - - <% if params[:lookbook][:display][:form] == true %> + + <% if params.dig(:lookbook, :display, :form) == true %>
<%= yield %> <%= render SubmitButtonComponent.new(class: 'margin-top-5') do %> diff --git a/app/views/shared/_footer_lite.html.erb b/app/views/shared/_footer_lite.html.erb index 5f501f1e045..1e925e21424 100644 --- a/app/views/shared/_footer_lite.html.erb +++ b/app/views/shared/_footer_lite.html.erb @@ -1,29 +1,6 @@ -<% show_language_dropdown = I18n.available_locales.count > 1 - sanitized_requested_url = request.query_parameters.slice(:request_id) %> -