From 25be96c716c581ece334faef569c7d6d0cdb1e9a Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Fri, 3 Mar 2023 10:20:33 -0500 Subject: [PATCH 1/3] LG-8580 Remove unsupported inheritted proofing code We built out the inheritted proofing experience, but it is not currently enabled or supported. This commit removes it. changelog: Improvement, Inheritted proofing, The code for inheritted proofing was removed. --- .../images/inherited_proofing/switch.png | Bin 998 -> 0 bytes .../concerns/allowlisted_flow_step_concern.rb | 37 -- .../inherited_proofing_404_concern.rb | 13 - .../concerns/inherited_proofing_concern.rb | 47 --- .../inherited_proofing_presenter_concern.rb | 15 - ...rited_proofing_cancellations_controller.rb | 77 ----- .../idv/inherited_proofing_controller.rb | 22 -- .../inherited_proofing_errors_controller.rb | 13 - app/controllers/idv/sessions_controller.rb | 1 - app/controllers/idv_controller.rb | 2 - .../authorization_controller.rb | 1 - app/forms/idv/inherited_proofing/base_form.rb | 120 ------- app/forms/idv/inherited_proofing/va/form.rb | 68 ---- app/jobs/inherited_proofing_job.rb | 21 -- .../inherited_proofing_presenter.rb | 29 -- app/services/analytics_events.rb | 62 ---- .../redo_retrieve_user_info_action.rb | 19 -- .../idv/flows/inherited_proofing_flow.rb | 42 --- .../service_provider_forms.rb | 13 - .../service_provider_services.rb | 24 -- .../inherited_proofing/service_providers.rb | 11 - .../inherited_proofing/va/mocks/service.rb | 59 ---- .../idv/inherited_proofing/va/service.rb | 111 ------ app/services/idv/steps/doc_auth_base_step.rb | 4 - .../inherited_proofing/agreement_step.rb | 32 -- .../inherited_proofing/get_started_step.rb | 20 -- .../user_pii_job_initiator.rb | 35 -- .../inherited_proofing/user_pii_managable.rb | 33 -- .../user_pii_retrievable.rb | 39 --- .../inherited_proofing/verify_info_step.rb | 31 -- .../inherited_proofing/verify_wait_step.rb | 15 - .../verify_wait_step_show.rb | 114 ------- .../idv/steps/inherited_proofing_base_step.rb | 17 - app/services/throttle.rb | 4 - .../idv/inherited_proofing/_cancel.html.erb | 7 - .../idv/inherited_proofing/_verify.html.erb | 70 ---- .../idv/inherited_proofing/agreement.html.erb | 42 --- .../inherited_proofing/get_started.html.erb | 58 ---- .../inherited_proofing/verify_info.html.erb | 26 -- .../inherited_proofing/verify_wait.html.erb | 17 - .../destroy.html.erb | 8 - .../new.html.erb | 54 --- .../failure.html.erb | 29 -- .../warning.html.erb | 27 -- config/application.yml.default | 9 - config/locales/errors/en.yml | 3 - config/locales/errors/es.yml | 2 - config/locales/errors/fr.yml | 2 - config/locales/inherited_proofing/en.yml | 71 ---- config/locales/inherited_proofing/es.yml | 76 ----- config/locales/inherited_proofing/fr.yml | 76 ----- config/locales/titles/en.yml | 3 - config/locales/titles/es.yml | 3 - config/locales/titles/fr.yml | 3 - config/routes.rb | 16 - lib/identity_config.rb | 5 - lib/session_encryptor.rb | 1 - scripts/inherited_proofing/errorable.rb | 23 -- .../va/lexis_nexis/phone_finder.rb | 28 -- .../va/lexis_nexis/test_script.rb | 70 ---- .../va/user_attributes/test_script.rb | 38 --- .../va/user_attributes/test_server.rb | 88 ----- .../inherited_proofing_concern_spec.rb | 92 ----- ..._proofing_cancellations_controller_spec.rb | 245 -------------- .../idv/inherited_proofing_controller_spec.rb | 83 ----- .../idv/sessions_controller_spec.rb | 5 - spec/controllers/idv_controller_spec.rb | 7 - .../authorization_controller_spec.rb | 22 -- .../inherited_proofing/agreement_step_spec.rb | 78 ----- .../idv/inherited_proofing/analytics_spec.rb | 49 --- .../get_started_step_spec.rb | 51 --- .../inherited_proofing_cancel_spec.rb | 151 --------- .../verify_info_step_spec.rb | 64 ---- .../verify_wait_step_spec.rb | 73 ---- .../va/mocks/service_spec.rb | 16 - .../idv/inherited_proofing/base_form_spec.rb | 182 ---------- .../idv/inherited_proofing/va/form_spec.rb | 317 ------------------ spec/jobs/inherited_proofing_job_spec.rb | 34 -- .../service_provider_forms_spec.rb | 37 -- .../service_provider_services_spec.rb | 101 ------ .../va/mocks/service_spec.rb | 28 -- .../idv/inherited_proofing/va/service_spec.rb | 124 ------- spec/support/features/idv_helper.rb | 24 -- .../features/inherited_proofing_helper.rb | 62 ---- ...d_proofing_with_service_provider_helper.rb | 55 --- .../encrypted_user_attributes.json | 1 - .../inherited_proofing/va_api_context.rb | 15 - .../inherited_proofing/va_user_context.rb | 18 - .../agreement.html.erb_spec.rb | 45 --- .../get_started.html.erb_spec.rb | 55 --- .../retrieval.html.erb_spec.rb | 19 -- 91 files changed, 4059 deletions(-) delete mode 100644 app/assets/images/inherited_proofing/switch.png delete mode 100644 app/controllers/concerns/allowlisted_flow_step_concern.rb delete mode 100644 app/controllers/concerns/inherited_proofing_404_concern.rb delete mode 100644 app/controllers/concerns/inherited_proofing_concern.rb delete mode 100644 app/controllers/concerns/inherited_proofing_presenter_concern.rb delete mode 100644 app/controllers/idv/inherited_proofing_cancellations_controller.rb delete mode 100644 app/controllers/idv/inherited_proofing_controller.rb delete mode 100644 app/controllers/idv/inherited_proofing_errors_controller.rb delete mode 100644 app/forms/idv/inherited_proofing/base_form.rb delete mode 100644 app/forms/idv/inherited_proofing/va/form.rb delete mode 100644 app/jobs/inherited_proofing_job.rb delete mode 100644 app/presenters/idv/inherited_proofing/inherited_proofing_presenter.rb delete mode 100644 app/services/idv/actions/inherited_proofing/redo_retrieve_user_info_action.rb delete mode 100644 app/services/idv/flows/inherited_proofing_flow.rb delete mode 100644 app/services/idv/inherited_proofing/service_provider_forms.rb delete mode 100644 app/services/idv/inherited_proofing/service_provider_services.rb delete mode 100644 app/services/idv/inherited_proofing/service_providers.rb delete mode 100644 app/services/idv/inherited_proofing/va/mocks/service.rb delete mode 100644 app/services/idv/inherited_proofing/va/service.rb delete mode 100644 app/services/idv/steps/inherited_proofing/agreement_step.rb delete mode 100644 app/services/idv/steps/inherited_proofing/get_started_step.rb delete mode 100644 app/services/idv/steps/inherited_proofing/user_pii_job_initiator.rb delete mode 100644 app/services/idv/steps/inherited_proofing/user_pii_managable.rb delete mode 100644 app/services/idv/steps/inherited_proofing/user_pii_retrievable.rb delete mode 100644 app/services/idv/steps/inherited_proofing/verify_info_step.rb delete mode 100644 app/services/idv/steps/inherited_proofing/verify_wait_step.rb delete mode 100644 app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb delete mode 100644 app/services/idv/steps/inherited_proofing_base_step.rb delete mode 100644 app/views/idv/inherited_proofing/_cancel.html.erb delete mode 100644 app/views/idv/inherited_proofing/_verify.html.erb delete mode 100644 app/views/idv/inherited_proofing/agreement.html.erb delete mode 100644 app/views/idv/inherited_proofing/get_started.html.erb delete mode 100644 app/views/idv/inherited_proofing/verify_info.html.erb delete mode 100644 app/views/idv/inherited_proofing/verify_wait.html.erb delete mode 100644 app/views/idv/inherited_proofing_cancellations/destroy.html.erb delete mode 100644 app/views/idv/inherited_proofing_cancellations/new.html.erb delete mode 100644 app/views/idv/inherited_proofing_errors/failure.html.erb delete mode 100644 app/views/idv/inherited_proofing_errors/warning.html.erb delete mode 100644 config/locales/inherited_proofing/en.yml delete mode 100644 config/locales/inherited_proofing/es.yml delete mode 100644 config/locales/inherited_proofing/fr.yml delete mode 100644 scripts/inherited_proofing/errorable.rb delete mode 100644 scripts/inherited_proofing/va/lexis_nexis/phone_finder.rb delete mode 100644 scripts/inherited_proofing/va/lexis_nexis/test_script.rb delete mode 100644 scripts/inherited_proofing/va/user_attributes/test_script.rb delete mode 100644 scripts/inherited_proofing/va/user_attributes/test_server.rb delete mode 100644 spec/controllers/concerns/inherited_proofing_concern_spec.rb delete mode 100644 spec/controllers/idv/inherited_proofing_cancellations_controller_spec.rb delete mode 100644 spec/controllers/idv/inherited_proofing_controller_spec.rb delete mode 100644 spec/features/idv/inherited_proofing/agreement_step_spec.rb delete mode 100644 spec/features/idv/inherited_proofing/analytics_spec.rb delete mode 100644 spec/features/idv/inherited_proofing/get_started_step_spec.rb delete mode 100644 spec/features/idv/inherited_proofing/inherited_proofing_cancel_spec.rb delete mode 100644 spec/features/idv/inherited_proofing/verify_info_step_spec.rb delete mode 100644 spec/features/idv/inherited_proofing/verify_wait_step_spec.rb delete mode 100644 spec/features/services/idv/inherited_proofing/va/mocks/service_spec.rb delete mode 100644 spec/forms/idv/inherited_proofing/base_form_spec.rb delete mode 100644 spec/forms/idv/inherited_proofing/va/form_spec.rb delete mode 100644 spec/jobs/inherited_proofing_job_spec.rb delete mode 100644 spec/services/idv/inherited_proofing/service_provider_forms_spec.rb delete mode 100644 spec/services/idv/inherited_proofing/service_provider_services_spec.rb delete mode 100644 spec/services/idv/inherited_proofing/va/mocks/service_spec.rb delete mode 100644 spec/services/idv/inherited_proofing/va/service_spec.rb delete mode 100644 spec/support/features/inherited_proofing_helper.rb delete mode 100644 spec/support/features/inherited_proofing_with_service_provider_helper.rb delete mode 100644 spec/support/shared_contexts/inherited_proofing/encrypted_user_attributes.json delete mode 100644 spec/support/shared_contexts/inherited_proofing/va_api_context.rb delete mode 100644 spec/support/shared_contexts/inherited_proofing/va_user_context.rb delete mode 100644 spec/views/idv/inherited_proofing/agreement.html.erb_spec.rb delete mode 100644 spec/views/idv/inherited_proofing/get_started.html.erb_spec.rb delete mode 100644 spec/views/idv/inherited_proofing/retrieval.html.erb_spec.rb diff --git a/app/assets/images/inherited_proofing/switch.png b/app/assets/images/inherited_proofing/switch.png deleted file mode 100644 index 315b1e56868c7f2ea44be27162df9b18cb2292ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 998 zcmV{rvp=`~3X*{rdI%_x1et^!)Yq_xJYp_x1Mn@A~oc^YrTY?eX#Q@bU5P@9^&L z@9pmI>FVp~>FVg{>gMO^&hOOW;^g7tmT`;Ha)y2iA&yRfsjud=qTv9_(Sw4<`VaMFZt(SvHwexs+WqNb~&rK+K& zs$tD{o}#B*%W|8aq?(?inVh1SoS}}Kr%%UcO2uQ3lbMc^m_x%{Lc&{xlAVi>mWq#+ zijI{%!B{-OR)de4iH(yxz*d5enTU*&IlohZhK+!QjDUoTeuIj6gpPiKiF|>Gdw_>} ze};H{g>`y?aeIYxcz|zod~S1lX>WIEZ+U2Lc4lmJW@~h1Yjb64b7E?9VP|k*W^Z3* zZeC<)cE7W7|htBg4Udi$uJ{Dt)F~%5UjLAjY(Z*NIwDF<- zJ(82PZ=s~NSn{y+3)H+WN)Gy==%nb|2u(lQL|qSn@s|&0-jnx8bcni30FISaTnDg1 z)Lj9-m38a{uril|Ph}n3QVY5oV`wtg=%Oj;96_p)PL_f?GSpcLhLPbjO93)jffY=@ z;8ZH6f^sS=umUUa6fBrSUa;oD?Fx6nVdoxKs0+H?L;`z3lE7Y&B(N7G3G4+)0$0J@ zt-B^&biWd)3eLDDNdi-WbEygJ1+K5cUf}u`vKP2j>;9l53?joIOF=I(^s*F`29Ro?#8M#b)!Nf0wQ4)fgcSdj znpnYqIP1tiZ(7xz`CTIFHbB$&g6OM5(Fw^x$1v2qDo7qyzk!llizFY#BQG@m!+Eqr zLQotIe6`rpxuL4Rf6^oURNb(^+1kcf3I}>LThIa%o1aaF=o1c0&HOg UKraE_f&c&j07*qoM6N<$f?InVTL1t6 diff --git a/app/controllers/concerns/allowlisted_flow_step_concern.rb b/app/controllers/concerns/allowlisted_flow_step_concern.rb deleted file mode 100644 index 7a2d4ba1657..00000000000 --- a/app/controllers/concerns/allowlisted_flow_step_concern.rb +++ /dev/null @@ -1,37 +0,0 @@ -# This Concern satisfies the brakeman gem "Dynamic Render Path" violation -# that is raised when rendering dynamic content in views and partials -# that come directly from params. In the below example, idv_inherited_proofing_cancel_path -# would render "/verify/inherited_proofing/cancel?step=" where -# == the value of params[:step], which could potentially be dangerous: -# <%= render ButtonComponent.new(action: ->(...) do -# button_to(idv_inherited_proofing_cancel_path(step: params[:step]), ...) ... -# end -# %> -module AllowlistedFlowStepConcern - extend ActiveSupport::Concern - - included do - before_action :flow_step! - end - - private - - def flow_step! - flow_step = flow_step_param - unless flow_step_allowlist.include? flow_step - Rails.logger.warn "Flow step param \"#{flow_step})\" was not whitelisted!" - render_not_found and return - end - - @flow_step = flow_step - end - - # Override this method for flow step params other than params[:step] - def flow_step_param - params[:step] - end - - def flow_step_allowlist - raise NotImplementedError, '#flow_step_allowlist must be overridden' - end -end diff --git a/app/controllers/concerns/inherited_proofing_404_concern.rb b/app/controllers/concerns/inherited_proofing_404_concern.rb deleted file mode 100644 index 51abb1e6cb2..00000000000 --- a/app/controllers/concerns/inherited_proofing_404_concern.rb +++ /dev/null @@ -1,13 +0,0 @@ -module InheritedProofing404Concern - extend ActiveSupport::Concern - - included do - before_action :render_404_if_disabled - end - - private - - def render_404_if_disabled - render_not_found unless IdentityConfig.store.inherited_proofing_enabled - end -end diff --git a/app/controllers/concerns/inherited_proofing_concern.rb b/app/controllers/concerns/inherited_proofing_concern.rb deleted file mode 100644 index 3b26d60826b..00000000000 --- a/app/controllers/concerns/inherited_proofing_concern.rb +++ /dev/null @@ -1,47 +0,0 @@ -# Methods to aid in handling incoming requests from 3rd-party -# inherited proofing service providers. Exclusively, methods -# to handle and help manage incoming requests to create a -# Login.gov account. -module InheritedProofingConcern - extend ActiveSupport::Concern - - # Returns true if Inherited Proofing is currently underway. - def inherited_proofing? - inherited_proofing_service_provider.present? - end - - def inherited_proofing_service_provider - return :va if va_inherited_proofing? - end - - # Department of Veterans Affairs (VA) methods. - # https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/products/identity/Inherited%20Proofing/MHV%20Inherited%20Proofing/inherited-proofing-interface.md - - # Returns true if the incoming request has been identified as a - # request to create a Login.gov account via inherited proofing - # from the VA. - def va_inherited_proofing? - va_inherited_proofing_auth_code.present? - end - - # The VA calls Login.gov to initiate inherited proofing of their - # users. An authorization code is passed as a query param that needs to - # be used in subsequent requests; this method returns this authorization - # code. - def va_inherited_proofing_auth_code - @va_inherited_proofing_auth_code ||= - decorated_session.request_url_params[va_inherited_proofing_auth_code_params_key] - end - - def va_inherited_proofing_auth_code_params_key - 'inherited_proofing_auth' - end - - def inherited_proofing_service_provider_data - if inherited_proofing_service_provider == :va - { auth_code: va_inherited_proofing_auth_code } - else - {} - end - end -end diff --git a/app/controllers/concerns/inherited_proofing_presenter_concern.rb b/app/controllers/concerns/inherited_proofing_presenter_concern.rb deleted file mode 100644 index 993589dda99..00000000000 --- a/app/controllers/concerns/inherited_proofing_presenter_concern.rb +++ /dev/null @@ -1,15 +0,0 @@ -module InheritedProofingPresenterConcern - extend ActiveSupport::Concern - - included do - before_action :init_presenter - end - - private - - def init_presenter - @presenter = Idv::InheritedProofing::InheritedProofingPresenter.new( - service_provider: inherited_proofing_service_provider, - ) - end -end diff --git a/app/controllers/idv/inherited_proofing_cancellations_controller.rb b/app/controllers/idv/inherited_proofing_cancellations_controller.rb deleted file mode 100644 index e14d7048d61..00000000000 --- a/app/controllers/idv/inherited_proofing_cancellations_controller.rb +++ /dev/null @@ -1,77 +0,0 @@ -module Idv - class InheritedProofingCancellationsController < ApplicationController - include IdvSession - include GoBackHelper - include InheritedProofing404Concern - include AllowlistedFlowStepConcern - - before_action :confirm_idv_needed - - def new - analytics.idv_cancellation_visited(step: params[:step], **analytics_properties) - self.session_go_back_path = go_back_path || idv_inherited_proofing_path - @presenter = CancellationsPresenter.new( - sp_name: decorated_session.sp_name, - url_options: url_options, - ) - end - - def update - analytics.idv_cancellation_go_back(step: params[:step], **analytics_properties) - redirect_to session_go_back_path || idv_inherited_proofing_path - end - - def destroy - analytics.idv_cancellation_confirmed(step: params[:step], **analytics_properties) - cancel_session - render json: { redirect_url: cancelled_redirect_path } - end - - private - - def cancel_session - cancel_idv_session - cancel_user_session - end - - def cancel_idv_session - idv_session = user_session[:idv] - idv_session&.clear - end - - def cancel_user_session - user_session['idv'] = {} - end - - def cancelled_redirect_path - return return_to_sp_failure_to_proof_path(location_params) if decorated_session.sp_name - - account_path - end - - def location_params - params.permit(:step, :location).to_h.symbolize_keys - end - - def session_go_back_path=(path) - idv_session.go_back_path = path - end - - def session_go_back_path - idv_session.go_back_path - end - - def flow_step_allowlist - @flow_step_allowlist ||= Idv::Flows::InheritedProofingFlow::STEPS.keys.map(&:to_s) - end - - def effective_user_id - current_user&.id - end - - def analytics_properties - route_properties = ParseControllerFromReferer.new(request.referer).call - route_properties.merge({ analytics_id: @analytics_id }) - end - end -end diff --git a/app/controllers/idv/inherited_proofing_controller.rb b/app/controllers/idv/inherited_proofing_controller.rb deleted file mode 100644 index d434751b33a..00000000000 --- a/app/controllers/idv/inherited_proofing_controller.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Idv - class InheritedProofingController < ApplicationController - before_action :confirm_two_factor_authenticated - - include Flow::FlowStateMachine - include IdvSession - include InheritedProofing404Concern - include InheritedProofingConcern - include InheritedProofingPresenterConcern - - FLOW_STATE_MACHINE_SETTINGS = { - step_url: :idv_inherited_proofing_step_url, - final_url: :idv_phone_url, - flow: Idv::Flows::InheritedProofingFlow, - analytics_id: 'Inherited Proofing', - }.freeze - - def return_to_sp - redirect_to return_to_sp_failure_to_proof_url(step: next_step, location: params[:location]) - end - end -end diff --git a/app/controllers/idv/inherited_proofing_errors_controller.rb b/app/controllers/idv/inherited_proofing_errors_controller.rb deleted file mode 100644 index b7cdf021f72..00000000000 --- a/app/controllers/idv/inherited_proofing_errors_controller.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Idv - class InheritedProofingErrorsController < ApplicationController - include IdvSession - include InheritedProofingConcern - include InheritedProofingPresenterConcern - - def warning - end - - def failure - end - end -end diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index 9f93c28aa36..0021a4f9fa1 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -57,7 +57,6 @@ def cancel_in_person_enrollment_if_exists def clear_session user_session['idv/doc_auth'] = {} user_session['idv/in_person'] = {} - user_session['idv/inherited_proofing'] = {} idv_session.clear Pii::Cacher.new(current_user, user_session).delete end diff --git a/app/controllers/idv_controller.rb b/app/controllers/idv_controller.rb index 1968d8c0156..905043cbd51 100644 --- a/app/controllers/idv_controller.rb +++ b/app/controllers/idv_controller.rb @@ -1,7 +1,6 @@ class IdvController < ApplicationController include IdvSession include AccountReactivationConcern - include InheritedProofingConcern include FraudReviewConcern before_action :confirm_two_factor_authenticated @@ -34,7 +33,6 @@ def activated def verify_identity analytics.idv_intro_visit - return redirect_to idv_inherited_proofing_url if inherited_proofing? redirect_to idv_doc_auth_url end diff --git a/app/controllers/openid_connect/authorization_controller.rb b/app/controllers/openid_connect/authorization_controller.rb index 05ecba3247f..4a1e52f4cbe 100644 --- a/app/controllers/openid_connect/authorization_controller.rb +++ b/app/controllers/openid_connect/authorization_controller.rb @@ -6,7 +6,6 @@ class AuthorizationController < ApplicationController include SecureHeadersConcern include AuthorizationCountConcern include BillableEventTrackable - include InheritedProofingConcern include FraudReviewConcern before_action :build_authorize_form_from_params, only: [:index] diff --git a/app/forms/idv/inherited_proofing/base_form.rb b/app/forms/idv/inherited_proofing/base_form.rb deleted file mode 100644 index 16e144690ef..00000000000 --- a/app/forms/idv/inherited_proofing/base_form.rb +++ /dev/null @@ -1,120 +0,0 @@ -module Idv - module InheritedProofing - class BaseForm - include ActiveModel::Model - - class << self - def model_name - ActiveModel::Name.new(self, nil, namespaced_model_name) - end - - def namespaced_model_name - self.to_s.gsub('::', '') - end - end - - private_class_method :namespaced_model_name - - attr_reader :payload_hash - - def initialize(payload_hash:) - raise ArgumentError, 'payload_hash is blank?' if payload_hash.blank? - raise ArgumentError, 'payload_hash is not a Hash' unless payload_hash.is_a? Hash - - @payload_hash = payload_hash.dup - - populate_field_data - end - - def submit - FormResponse.new( - success: valid?, - errors: errors, - extra: {}, - ) - end - - # Perhaps overkill, but a mapper service of some kind, not bound to this class, - # that takes into consideration context, may be more suitable. In the meantime, - # simply return a Hash suitable to place into flow_session[:pii_from_user] in - # our inherited proofing flow steps. - def user_pii - raise NotImplementedError, 'Override this method and return a user PII Hash' - end - - private - - attr_writer :payload_hash - - # Populates our field data from the payload hash. - def populate_field_data - payload_field_info.each do |field_name, field_info| - # Ignore fields we're not interested in. - next unless respond_to? field_name - - value = payload_hash.dig( - *[field_info[:namespace], - field_info[:field_name]].flatten.compact, - ) - public_send("#{field_name}=", value) - end - end - - def payload_field_info - @payload_field_info ||= field_name_info_from payload_hash: payload_hash - end - - # This method simply navigates the payload hash received and creates qualified - # hash key names that can be used to verify/map to our field names in this model. - # This can be used to qualify nested hash fields and saves us some headaches - # if there are nested field names with the same name: - # - # given: - # - # payload_hash = { - # first_name: 'first_name', - # ... - # address: { - # street: '', - # ... - # } - # } - # - # field_name_info_from(payload_hash: payload_hash) #=> - # - # { - # :first_name=>{:field_name=>:first_name, :namespace=>[]}, - # ... - # :address_street=>{:field_name=>:street, :namespace=>[:address]}, - # ... - # } - # - # The generated, qualified field names expected to map to our model, because we named - # them as such. - # - # :field_name is the actual, unqualified field name found in the payload hash sent. - # :namespace is the hash key by which :field_name can be found in the payload hash - # if need be. - def field_name_info_from(payload_hash:, namespace: [], field_name_info: {}) - payload_hash.each do |key, value| - if value.is_a? Hash - field_name_info_from payload_hash: value, namespace: namespace << key, - field_name_info: field_name_info - namespace.pop - next - end - - namespace = namespace.dup - if namespace.blank? - field_name_info[key] = { field_name: key, namespace: namespace } - else - field_name_info["#{namespace.split.join('_')}_#{key}".to_sym] = - { field_name: key, namespace: namespace } - end - end - - field_name_info - end - end - end -end diff --git a/app/forms/idv/inherited_proofing/va/form.rb b/app/forms/idv/inherited_proofing/va/form.rb deleted file mode 100644 index 97878154d4a..00000000000 --- a/app/forms/idv/inherited_proofing/va/form.rb +++ /dev/null @@ -1,68 +0,0 @@ -module Idv - module InheritedProofing - module Va - class Form < Idv::InheritedProofing::BaseForm - REQUIRED_FIELDS = %i[first_name - last_name - birth_date - ssn - address_street - address_zip].freeze - OPTIONAL_FIELDS = %i[phone - address_street2 - address_city - address_state - address_country - service_error].freeze - FIELDS = (REQUIRED_FIELDS + OPTIONAL_FIELDS).freeze - - attr_accessor(*FIELDS) - validate :add_service_error, if: :service_error? - validates(*REQUIRED_FIELDS, presence: true, unless: :service_error?) - - def submit - extra = {} - extra = { service_error: service_error } if service_error? - - FormResponse.new( - success: validate, - errors: errors, - extra: extra, - ) - end - - def user_pii - raise 'User PII is invalid' unless valid? - - user_pii = {} - user_pii[:first_name] = first_name - user_pii[:last_name] = last_name - user_pii[:dob] = birth_date - user_pii[:ssn] = ssn - user_pii[:phone] = phone - user_pii[:address1] = address_street - user_pii[:city] = address_city - user_pii[:state] = address_state - user_pii[:zipcode] = address_zip - user_pii - end - - def service_error? - service_error.present? - end - - private - - def add_service_error - errors.add( - :service_provider, - # Use a "safe" error message for the model in case it's displayed - # to the user at any point. - I18n.t('inherited_proofing.errors.service_provider.communication'), - type: :service_error, - ) - end - end - end - end -end diff --git a/app/jobs/inherited_proofing_job.rb b/app/jobs/inherited_proofing_job.rb deleted file mode 100644 index c4f8d5f79e9..00000000000 --- a/app/jobs/inherited_proofing_job.rb +++ /dev/null @@ -1,21 +0,0 @@ -class InheritedProofingJob < ApplicationJob - include Idv::InheritedProofing::ServiceProviderServices - include JobHelpers::StaleJobHelper - - queue_as :default - - discard_on JobHelpers::StaleJobHelper::StaleJobError - - def perform(service_provider, service_provider_data, uuid) - document_capture_session = DocumentCaptureSession.find_by(uuid: uuid) - - payload_hash = inherited_proofing_service_for( - service_provider, - service_provider_data: service_provider_data, - ).execute - - raise_stale_job! if stale_job?(enqueued_at) - - document_capture_session.store_proofing_result(payload_hash) - end -end diff --git a/app/presenters/idv/inherited_proofing/inherited_proofing_presenter.rb b/app/presenters/idv/inherited_proofing/inherited_proofing_presenter.rb deleted file mode 100644 index cc74d37ba1c..00000000000 --- a/app/presenters/idv/inherited_proofing/inherited_proofing_presenter.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Idv - module InheritedProofing - class InheritedProofingPresenter - attr_reader :service_provider - - def initialize(service_provider:) - @service_provider = service_provider - end - - def learn_more_phone_or_mail_url - 'https://www.va.gov/resources/managing-your-vagov-profile/' if va_inherited_proofing? - end - - def get_help_url - 'https://www.va.gov/resources/managing-your-vagov-profile/' if va_inherited_proofing? - end - - def contact_support_url - 'https://www.va.gov/resources/managing-your-vagov-profile/' if va_inherited_proofing? - end - - private - - def va_inherited_proofing? - service_provider == :va - end - end - end -end diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index 802ba0e2ad7..83fff0f245f 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -567,68 +567,6 @@ def idv_verify_in_person_troubleshooting_option_clicked(flow_path:, in_person_ct ) end - # @param [Boolean] success - # @param [Hash] errors - # @param [String] flow_path Document capture path ("hybrid" or "standard") - # @param [String] step Document step user is on - # The user agrees to allow us to access their data via api call - def idv_inherited_proofing_agreement_submitted(success:, errors:, flow_path:, step:, **extra) - track_event( - 'IdV: inherited proofing agreement submitted', - success: success, - errors: errors, - flow_path: flow_path, - step: step, - **extra, - ) - end - - # @param [String] flow_path Document capture path ("hybrid" or "standard") - # @param [String] step Document step user is on - # The user visited the inherited proofing agreement page - def idv_inherited_proofing_agreement_visited(flow_path:, step:, **extra) - track_event( - 'IdV: inherited proofing agreement visited', - flow_path: flow_path, - step: step, - **extra, - ) - end - - # @param [Boolean] success - # @param [Hash] errors - # @param [String] flow_path Document capture path ("hybrid" or "standard") - # @param [String] step Document step user is on - # The user chooses to begin the inherited proofing process - def idv_inherited_proofing_get_started_submitted(success:, errors:, flow_path:, step:, **extra) - track_event( - 'IdV: inherited proofing get started submitted', - success: success, - errors: errors, - flow_path: flow_path, - step: step, - **extra, - ) - end - - # @param [String] flow_path Document capture path ("hybrid" or "standard") - # @param [String] step Document step user is on - # The user visited the inherited proofing get started step - def idv_inherited_proofing_get_started_visited(flow_path:, step:, **extra) - track_event( - 'IdV: inherited proofing get started visited', - flow_path: flow_path, - step: step, - **extra, - ) - end - - # Retry retrieving the user PII in the case where the first attempt fails - # in the agreement step, and the user initiates a "retry". - def idv_inherited_proofing_redo_retrieve_user_info_submitted(**extra) - track_event('IdV: inherited proofing retry retrieve user information submitted', **extra) - end - # @param [String] flow_path Document capture path ("hybrid" or "standard") # @param [String] in_person_cta_variant Variant testing bucket label # The user visited the in person proofing location step diff --git a/app/services/idv/actions/inherited_proofing/redo_retrieve_user_info_action.rb b/app/services/idv/actions/inherited_proofing/redo_retrieve_user_info_action.rb deleted file mode 100644 index a9fd7ed2c2e..00000000000 --- a/app/services/idv/actions/inherited_proofing/redo_retrieve_user_info_action.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Idv - module Actions - module InheritedProofing - class RedoRetrieveUserInfoAction < Idv::Steps::InheritedProofing::VerifyWaitStepShow - class << self - def analytics_submitted_event - :idv_inherited_proofing_redo_retrieve_user_info_submitted - end - end - - def call - enqueue_job unless api_call_already_in_progress? - - super - end - end - end - end -end diff --git a/app/services/idv/flows/inherited_proofing_flow.rb b/app/services/idv/flows/inherited_proofing_flow.rb deleted file mode 100644 index 2fc56d71103..00000000000 --- a/app/services/idv/flows/inherited_proofing_flow.rb +++ /dev/null @@ -1,42 +0,0 @@ -module Idv - module Flows - class InheritedProofingFlow < Flow::BaseFlow - STEPS = { - get_started: Idv::Steps::InheritedProofing::GetStartedStep, - agreement: Idv::Steps::InheritedProofing::AgreementStep, - verify_wait: Idv::Steps::InheritedProofing::VerifyWaitStep, - verify_info: Idv::Steps::InheritedProofing::VerifyInfoStep, - }.freeze - - OPTIONAL_SHOW_STEPS = { - verify_wait: Idv::Steps::InheritedProofing::VerifyWaitStepShow, - }.freeze - - STEP_INDICATOR_STEPS = [ - { name: :getting_started }, - { name: :verify_info }, - { name: :secure_account }, - ].freeze - - ACTIONS = { - redo_retrieve_user_info: Idv::Actions::InheritedProofing::RedoRetrieveUserInfoAction, - }.freeze - - attr_reader :idv_session - - def initialize(controller, session, name) - @idv_session = self.class.session_idv(session) - super(controller, STEPS, ACTIONS, session[name]) - - @flow_session ||= {} - @flow_session[:pii_from_user] ||= { uuid: current_user.uuid } - applicant = @idv_session['applicant'] || {} - @flow_session[:pii_from_user] = @flow_session[:pii_from_user].to_h.merge(applicant) - end - - def self.session_idv(session) - session[:idv] ||= {} - end - end - end -end diff --git a/app/services/idv/inherited_proofing/service_provider_forms.rb b/app/services/idv/inherited_proofing/service_provider_forms.rb deleted file mode 100644 index 51740b47ba3..00000000000 --- a/app/services/idv/inherited_proofing/service_provider_forms.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Idv - module InheritedProofing - module ServiceProviderForms - def inherited_proofing_form_for(service_provider, payload_hash:) - if service_provider == :va - return Idv::InheritedProofing::Va::Form.new payload_hash: payload_hash - end - - raise 'Inherited proofing form could not be identified' - end - end - end -end diff --git a/app/services/idv/inherited_proofing/service_provider_services.rb b/app/services/idv/inherited_proofing/service_provider_services.rb deleted file mode 100644 index 0dfadedc88b..00000000000 --- a/app/services/idv/inherited_proofing/service_provider_services.rb +++ /dev/null @@ -1,24 +0,0 @@ -module Idv - module InheritedProofing - module ServiceProviderServices - def inherited_proofing_service_for(service_provider, service_provider_data:) - inherited_proofing_service_class_for(service_provider).new(service_provider_data) - end - - def inherited_proofing_service_class_for(service_provider) - unless IdentityConfig.store.inherited_proofing_enabled - raise 'Inherited Proofing is not enabled' - end - - if service_provider == :va - if IdentityConfig.store.va_inherited_proofing_mock_enabled - return Idv::InheritedProofing::Va::Mocks::Service - end - return Idv::InheritedProofing::Va::Service - end - - raise 'Inherited proofing service class could not be identified' - end - end - end -end diff --git a/app/services/idv/inherited_proofing/service_providers.rb b/app/services/idv/inherited_proofing/service_providers.rb deleted file mode 100644 index 7bb6b6ae8e9..00000000000 --- a/app/services/idv/inherited_proofing/service_providers.rb +++ /dev/null @@ -1,11 +0,0 @@ -module Idv - module InheritedProofing - # This module is temporary until InheritedProofing has a viable way - # of identifying/communicating identifying Service Providers - # modules - module ServiceProviders - VA = :va - SERVICE_PROVIDERS = %i[VA] - end - end -end diff --git a/app/services/idv/inherited_proofing/va/mocks/service.rb b/app/services/idv/inherited_proofing/va/mocks/service.rb deleted file mode 100644 index e1150a9528d..00000000000 --- a/app/services/idv/inherited_proofing/va/mocks/service.rb +++ /dev/null @@ -1,59 +0,0 @@ -module Idv - module InheritedProofing - module Va - module Mocks - class Service - VALID_AUTH_CODE = 'mocked-auth-code-for-testing'.freeze - - attr_reader :auth_code - - PAYLOAD_HASH = { - first_name: 'Fakey', - last_name: 'Fakerson', - address: { - street: '123 Fake St', - street2: 'Apt 235', - city: 'Faketown', - state: 'WA', - country: nil, - zip: '98037', - }, - phone: '2063119187', - birth_date: '2022-1-31', - ssn: '123456789', - mhv_data: { - mhvId: 99999999, - identityProofedMethod: 'IPA', - identityDocumentExist: true, - identityProofingDate: '2020-12-14', - identityDocumentInfo: { - primaryIdentityDocumentNumber: '88888888', - primaryIdentityDocumentType: 'StateIssuedId', - primaryIdentityDocumentCountry: 'United States', - primaryIdentityDocumentExpirationDate: '2222-03-30', - }, - }, - }.freeze - - ERROR_HASH = { - service_error: 'the server responded with status 401', - }.freeze - - def initialize(service_provider_data) - @auth_code = service_provider_data[:auth_code] - end - - def execute - invalid_auth_code ? ERROR_HASH : PAYLOAD_HASH - end - - private - - def invalid_auth_code - @auth_code != VALID_AUTH_CODE - end - end - end - end - end -end diff --git a/app/services/idv/inherited_proofing/va/service.rb b/app/services/idv/inherited_proofing/va/service.rb deleted file mode 100644 index 7e7c76a7e28..00000000000 --- a/app/services/idv/inherited_proofing/va/service.rb +++ /dev/null @@ -1,111 +0,0 @@ -module Idv - module InheritedProofing - module Va - # Encapsulates request, response, error handling, validation, etc. for calling - # the VA service to gain PII for a particular user that will be subsequently - # used to proof the user using inherited proofing. - class Service - BASE_URI = IdentityConfig.store.inherited_proofing_va_base_url - - attr_reader :auth_code - - def initialize(service_provider_data) - @auth_code = service_provider_data[:auth_code] - end - - # Calls the endpoint and returns the decrypted response. - def execute - raise 'The provided auth_code is blank?' if auth_code.blank? - - begin - response = request - return payload_to_hash decrypt_payload(response) if response.status == 200 - - service_error(not_200_service_error(response.status)) - rescue => error - service_error(error.message) - end - end - - private - - def service_error(message) - { service_error: message } - end - - def not_200_service_error(http_status) - # Under certain circumstances, Faraday may return a nil http status. - # https://lostisland.github.io/faraday/middleware/raise-error - if http_status.blank? - http_status = 'unavailable' - http_status_description = 'unavailable' - else - http_status_description = Rack::Utils::HTTP_STATUS_CODES[http_status] - end - "The service provider API returned an http status other than 200: " \ - "#{http_status} (#{http_status_description})" - end - - def request - connection.get(request_uri) { |req| req.headers = request_headers } - end - - def connection - Faraday.new do |conn| - conn.options.timeout = request_timeout - conn.options.read_timeout = request_timeout - conn.options.open_timeout = request_timeout - conn.options.write_timeout = request_timeout - conn.request :instrumentation, name: 'inherited_proofing.va' - - # raises errors on 4XX or 5XX responses - conn.response :raise_error - end - end - - def request_timeout - @request_timeout ||= IdentityConfig.store.doc_auth_s3_request_timeout - end - - def request_uri - @request_uri ||= "#{ URI(BASE_URI) }/inherited_proofing/user_attributes" - end - - def request_headers - { Authorization: "Bearer #{jwt_token}" } - end - - def jwt_token - JWT.encode(jwt_payload, private_key, jwt_encryption) - end - - def jwt_payload - { inherited_proofing_auth: auth_code, exp: jwt_expires } - end - - def private_key - @private_key ||= AppArtifacts.store.oidc_private_key - end - - def jwt_encryption - 'RS256' - end - - def jwt_expires - 1.day.from_now.to_i - end - - def decrypt_payload(response) - payload = JSON.parse(response.body)['data'] - JWE.decrypt(payload, private_key) if payload - end - - def payload_to_hash(decrypted_payload, default: nil) - return default unless decrypted_payload.present? - - JSON.parse(decrypted_payload, symbolize_names: true) - 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 bbc63bf9e7d..4c4a68c9b86 100644 --- a/app/services/idv/steps/doc_auth_base_step.rb +++ b/app/services/idv/steps/doc_auth_base_step.rb @@ -109,10 +109,6 @@ def document_capture_session_uuid_key :document_capture_session_uuid end - def inherited_proofing_verify_step_document_capture_session_uuid_key - :inherited_proofing_verify_step_document_capture_session_uuid - end - def verify_step_document_capture_session_uuid_key :idv_verify_step_document_capture_session_uuid end diff --git a/app/services/idv/steps/inherited_proofing/agreement_step.rb b/app/services/idv/steps/inherited_proofing/agreement_step.rb deleted file mode 100644 index b49e3d7ec7d..00000000000 --- a/app/services/idv/steps/inherited_proofing/agreement_step.rb +++ /dev/null @@ -1,32 +0,0 @@ -module Idv - module Steps - module InheritedProofing - class AgreementStep < VerifyBaseStep - include UserPiiJobInitiator - - 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 - - def form_submit - Idv::ConsentForm.new.submit(consent_form_params) - end - - def consent_form_params - params.require(:inherited_proofing).permit(:ial2_consent_given) - end - end - end - end -end diff --git a/app/services/idv/steps/inherited_proofing/get_started_step.rb b/app/services/idv/steps/inherited_proofing/get_started_step.rb deleted file mode 100644 index 7afedc41f9b..00000000000 --- a/app/services/idv/steps/inherited_proofing/get_started_step.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Idv - module Steps - 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 - end - end -end diff --git a/app/services/idv/steps/inherited_proofing/user_pii_job_initiator.rb b/app/services/idv/steps/inherited_proofing/user_pii_job_initiator.rb deleted file mode 100644 index 3d39f3b0599..00000000000 --- a/app/services/idv/steps/inherited_proofing/user_pii_job_initiator.rb +++ /dev/null @@ -1,35 +0,0 @@ -module Idv - module Steps - module InheritedProofing - module UserPiiJobInitiator - private - - def enqueue_job - return if api_call_already_in_progress? - - create_document_capture_session( - inherited_proofing_verify_step_document_capture_session_uuid_key, - ).tap do |doc_capture_session| - doc_capture_session.create_proofing_session - - InheritedProofingJob.perform_later( - controller.inherited_proofing_service_provider, - controller.inherited_proofing_service_provider_data, - doc_capture_session.uuid, - ) - end - end - - def api_call_already_in_progress? - DocumentCaptureSession.find_by( - uuid: flow_session[inherited_proofing_verify_step_document_capture_session_uuid_key], - ).present? - end - - def delete_async - flow_session.delete(inherited_proofing_verify_step_document_capture_session_uuid_key) - end - end - end - end -end diff --git a/app/services/idv/steps/inherited_proofing/user_pii_managable.rb b/app/services/idv/steps/inherited_proofing/user_pii_managable.rb deleted file mode 100644 index 08521d7cbc3..00000000000 --- a/app/services/idv/steps/inherited_proofing/user_pii_managable.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Idv - module Steps - module InheritedProofing - module UserPiiManagable - def inherited_proofing_save_user_pii_to_session!(user_pii) - inherited_proofing_save_session!(user_pii) - inherited_proofing_skip_steps! - end - - private - - def inherited_proofing_save_session!(user_pii) - flow_session[:pii_from_user] = - flow_session[:pii_from_user].to_h.merge(user_pii) - # This is unnecessary, but added for completeness. Any subsequent FLOWS we - # might splice into will pull from idv_session['applicant'] and merge into - # flow_session[:pii_from_user] anyhow in their #initialize(r); any subsequent - # STEP FLOWS we might splice into will populate idv_session['applicant'] and - # ultimately get merged in to flow_session[:pii_from_user] as well. - idv_session['applicant'] = flow_session[:pii_from_user] - end - - def inherited_proofing_skip_steps! - idv_session['profile_confirmation'] = true - idv_session['vendor_phone_confirmation'] = false - idv_session['user_phone_confirmation'] = false - idv_session['address_verification_mechanism'] = 'phone' - idv_session['resolution_successful'] = 'phone' - end - end - end - end -end diff --git a/app/services/idv/steps/inherited_proofing/user_pii_retrievable.rb b/app/services/idv/steps/inherited_proofing/user_pii_retrievable.rb deleted file mode 100644 index 36323660088..00000000000 --- a/app/services/idv/steps/inherited_proofing/user_pii_retrievable.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Idv - module Steps - module InheritedProofing - module UserPiiRetrievable - def inherited_proofing_user_pii - inherited_proofing_info[0] - end - - def inherited_proofing_form_response - inherited_proofing_info[1] - end - - private - - # This needs error handling. - def inherited_proofing_info - return @inherited_proofing_info if defined? @inherited_proofing_info - - payload_hash = inherited_proofing_service.execute.dup - form = inherited_proofing_form(payload_hash) - form_response = form.submit - - user_pii = {} - user_pii = form.user_pii if form_response.success? - - @inherited_proofing_info = [user_pii, form_response] - end - - def inherited_proofing_service - controller.inherited_proofing_service - end - - def inherited_proofing_form(payload_hash) - controller.inherited_proofing_form payload_hash - end - end - end - 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 deleted file mode 100644 index b54f4e26e91..00000000000 --- a/app/services/idv/steps/inherited_proofing/verify_info_step.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Idv - module Steps - 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 - - def extra_view_variables - { - pii: pii, - step_url: method(:idv_inherited_proofing_step_url), - } - end - - def pii - flow_session[:pii_from_user] - end - end - end - end -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 deleted file mode 100644 index 856d20a55e7..00000000000 --- a/app/services/idv/steps/inherited_proofing/verify_wait_step.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Idv - module Steps - 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 - 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 deleted file mode 100644 index 611c8d8731d..00000000000 --- a/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb +++ /dev/null @@ -1,114 +0,0 @@ -module Idv - module Steps - module InheritedProofing - class VerifyWaitStepShow < VerifyBaseStep - include UserPiiJobInitiator - include UserPiiManagable - include Idv::InheritedProofing::ServiceProviderForms - delegate :controller, :idv_session, to: :@flow - - 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) - - process_async_state(async_state) - end - - private - - def process_async_state(current_async_state) - return if current_async_state.in_progress? - - if current_async_state.none? - mark_step_incomplete(:agreement) - elsif current_async_state.missing? - flash[:error] = I18n.t('idv.failure.timeout') - delete_async - mark_step_incomplete(:agreement) - @flow.analytics.idv_proofing_resolution_result_missing - elsif current_async_state.done? - async_state_done(current_async_state) - end - end - - def async_state - return ProofingSessionAsyncResult.none if dcs_uuid.nil? - return ProofingSessionAsyncResult.missing if document_capture_session.nil? - return ProofingSessionAsyncResult.missing if api_job_result.nil? - - api_job_result - end - - def async_state_done(_current_async_state) - service_provider = controller.inherited_proofing_service_provider - - form = inherited_proofing_form_for( - service_provider, - payload_hash: api_job_result[:result], - ) - form_response = form.submit - - delete_async - - if form_response.success? - inherited_proofing_save_user_pii_to_session!(form.user_pii) - mark_step_complete(:verify_wait) - elsif throttle.throttled? - idv_failure(form_response) - else - mark_step_complete(:agreement) - idv_failure(form_response) - end - - form_response - end - - def dcs_uuid - @dcs_uuid ||= - flow_session[inherited_proofing_verify_step_document_capture_session_uuid_key] - end - - def document_capture_session - @document_capture_session ||= DocumentCaptureSession.find_by(uuid: dcs_uuid) - end - - def api_job_result - document_capture_session.load_proofing_result - end - - # Base class overrides - - def throttle - @throttle ||= Throttle.new( - user: current_user, - throttle_type: :inherited_proofing, - ) - end - - def idv_failure_log_throttled - @flow.analytics.throttler_rate_limit_triggered( - throttle_type: throttle.throttle_type, - step_name: self.class.name, - ) - end - - def throttled_url - idv_inherited_proofing_errors_failure_url(flow: :inherited_proofing) - end - - def exception_url - idv_inherited_proofing_errors_failure_url(flow: :inherited_proofing) - end - - def warning_url - idv_inherited_proofing_errors_no_information_url(flow: :inherited_proofing) - end - end - end - end -end diff --git a/app/services/idv/steps/inherited_proofing_base_step.rb b/app/services/idv/steps/inherited_proofing_base_step.rb deleted file mode 100644 index 43c18f90889..00000000000 --- a/app/services/idv/steps/inherited_proofing_base_step.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Idv - module Steps - class InheritedProofingBaseStep < Flow::BaseStep - delegate :controller, :idv_session, to: :@flow - - def initialize(flow) - super(flow, :inherited_proofing) - end - - private - - def sp_session - session.fetch(:sp, {}) - end - end - end -end diff --git a/app/services/throttle.rb b/app/services/throttle.rb index 04adb68310d..b5c4a992c78 100644 --- a/app/services/throttle.rb +++ b/app/services/throttle.rb @@ -211,10 +211,6 @@ def self.load_throttle_config max_attempts: IdentityConfig.store.phone_confirmation_max_attempts, attempt_window: IdentityConfig.store.phone_confirmation_max_attempt_window_in_minutes, }, - inherited_proofing: { - max_attempts: IdentityConfig.store.inherited_proofing_max_attempts, - attempt_window: IdentityConfig.store.inherited_proofing_max_attempt_window_in_minutes, - }, phone_otp: { max_attempts: IdentityConfig.store.otp_delivery_blocklist_maxretry + 1, attempt_window: IdentityConfig.store.otp_delivery_blocklist_findtime, diff --git a/app/views/idv/inherited_proofing/_cancel.html.erb b/app/views/idv/inherited_proofing/_cancel.html.erb deleted file mode 100644 index 52947a558bc..00000000000 --- a/app/views/idv/inherited_proofing/_cancel.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<%# -locals: -* step: Current step, used in analytics logging. -%> -<%= render PageFooterComponent.new do %> - <%= link_to cancel_link_text, idv_inherited_proofing_cancel_path(step: local_assigns[:step]) %> -<% end %> diff --git a/app/views/idv/inherited_proofing/_verify.html.erb b/app/views/idv/inherited_proofing/_verify.html.erb deleted file mode 100644 index 3efa83cbd3b..00000000000 --- a/app/views/idv/inherited_proofing/_verify.html.erb +++ /dev/null @@ -1,70 +0,0 @@ -<%# -locals: - pii - user's information - step_url - generator for step URLs -%> -<% title t('inherited_proofing.headings.verify_information') %> - -<%= render PageHeadingComponent.new.with_content(t('titles.idv.verify_info')) %> -
-
-
-
-
<%= t('idv.form.first_name') %>:
-
<%= pii[:first_name] %>
-
-
-
<%= t('idv.form.last_name') %>:
-
<%= pii[:last_name] %>
-
-
-
<%= t('idv.form.dob') %>:
-
<%= pii[:dob] %>
-
-
-
-
-
-
-
<%= t('idv.form.address1') %>:
-
<%= pii[:address1] %>
-
- <% if pii[:address2].present? %> -
-
<%= t('idv.form.address2') %>:
-
<%= pii[:address2] %>
-
- <% end %> -
-
<%= t('idv.form.city') %>:
-
<%= pii[:city] %>
-
-
-
<%= t('idv.form.state') %>:
-
<%= pii[:state] %>
-
-
-
<%= t('idv.form.zipcode') %>:
-
<%= pii[:zipcode] %>
-
-
-
-
-
- <%= t('idv.form.ssn') %>: - <%= render( - 'shared/masked_text', - text: SsnFormatter.format(pii[:ssn]), - masked_text: SsnFormatter.format_masked(pii[:ssn]), - accessible_masked_text: t( - 'idv.accessible_labels.masked_ssn', - first_number: pii[:ssn][0], - last_number: pii[:ssn][-1], - ), - toggle_label: t('forms.ssn.show'), - ) %> -
-
-
- -<% javascript_packs_tag_once 'form-steps-wait' %> diff --git a/app/views/idv/inherited_proofing/agreement.html.erb b/app/views/idv/inherited_proofing/agreement.html.erb deleted file mode 100644 index e74f11a9206..00000000000 --- a/app/views/idv/inherited_proofing/agreement.html.erb +++ /dev/null @@ -1,42 +0,0 @@ -<% title t('inherited_proofing.headings.lets_go') %> - -<%= render AlertComponent.new( - type: :error, - class: [ - 'js-consent-form-alert', - 'margin-bottom-4', - flow_session[:error_message].blank? && 'display-none', - ].select(&:present?), - message: flow_session[:error_message].presence || t('errors.inherited_proofing.consent_form'), - ) %> - -<%= render PageHeadingComponent.new.with_content(t('inherited_proofing.headings.lets_go')) %> -

<%= t('inherited_proofing.info.lets_go') %>

-

<%= t('inherited_proofing.headings.verify_identity') %>

-

<%= t('inherited_proofing.info.verify_identity') %>

-

<%= t('inherited_proofing.headings.secure_account') %>

-

<%= t('inherited_proofing.info.secure_account') %>

- -<%= simple_form_for( - :inherited_proofing, - url: url_for, - method: 'put', - html: { autocomplete: 'off', class: 'margin-top-2 margin-bottom-5 js-consent-continue-form' }, - ) do |f| %> - <%= render ValidatedFieldComponent.new( - form: f, - name: :ial2_consent_given, - as: :boolean, - label: capture do %> - <%= t('inherited_proofing.instructions.consent', app_name: APP_NAME) %> - <%= new_window_link_to( - t('inherited_proofing.instructions.learn_more'), - MarketingSite.security_and_privacy_practices_url, - ) %> - <% end, - required: true, - ) %> - <%= f.submit t('inherited_proofing.buttons.continue'), class: 'margin-top-4' %> -<% end %> - -<%= render 'idv/inherited_proofing/cancel', step: 'agreement' %> diff --git a/app/views/idv/inherited_proofing/get_started.html.erb b/app/views/idv/inherited_proofing/get_started.html.erb deleted file mode 100644 index 93bd0b9552f..00000000000 --- a/app/views/idv/inherited_proofing/get_started.html.erb +++ /dev/null @@ -1,58 +0,0 @@ -<% title t('inherited_proofing.headings.welcome') %> - -<%= render JavascriptRequiredComponent.new( - header: t('idv.welcome.no_js_header'), - intro: t('idv.welcome.no_js_intro', sp_name: decorated_session.sp_name || t('inherited_proofing.info.no_sp_name')), - ) do %> - <%= render PageHeadingComponent.new.with_content(t('inherited_proofing.headings.welcome')) %> -

- <%= t('inherited_proofing.info.welcome_html', sp_name: decorated_session.sp_name || t('inherited_proofing.info.no_sp_name')) %> -

- -

- <%= t('inherited_proofing.instructions.verify_requirements') %> - <%= new_window_link_to(t('inherited_proofing.troubleshooting.options.learn_more_phone_or_mail'), 'https://www.va.gov/resources/managing-your-vagov-profile/') %> -

- - <%= simple_form_for :inherited_proofing, - url: url_for, - method: 'put', - html: { autocomplete: 'off', class: 'margin-y-5' } do |f| %> - <%= f.submit t('inherited_proofing.buttons.continue') %> - <% end %> - - <%= render( - 'shared/troubleshooting_options', - heading_tag: :h3, - heading: t('inherited_proofing.troubleshooting.headings.missing_required_items'), - options: [ - { - url: @presenter.learn_more_phone_or_mail_url, - text: t('inherited_proofing.troubleshooting.options.learn_more_phone_or_mail'), - new_tab: true, - }, - { - url: @presenter.get_help_url, - text: t( - 'inherited_proofing.troubleshooting.options.get_help', - sp_name: decorated_session.sp_name, - ), - new_tab: true, - }, - ].select(&:present?), - ) %> - -

<%= t('inherited_proofing.instructions.privacy') %>

-

- <%= t( - 'inherited_proofing.info.privacy_html', - app_name: APP_NAME, - link: new_window_link_to( - t('inherited_proofing.instructions.learn_more'), - MarketingSite.security_and_privacy_practices_url, - ), - ) %> -

- - <%= render 'shared/cancel', link: idv_inherited_proofing_cancel_path(step: 'get_started') %> -<% end %> diff --git a/app/views/idv/inherited_proofing/verify_info.html.erb b/app/views/idv/inherited_proofing/verify_info.html.erb deleted file mode 100644 index ee7321025aa..00000000000 --- a/app/views/idv/inherited_proofing/verify_info.html.erb +++ /dev/null @@ -1,26 +0,0 @@ -<%= render 'verify', pii: pii, step_url: step_url %> - -<%= simple_form_for :inherited_proofing, - url: url_for, - method: 'put', - html: { autocomplete: 'off', class: 'margin-y-5' } do |f| %> - <%= f.submit t('inherited_proofing.buttons.continue') %> -<% end %> - -<%= render( - 'shared/troubleshooting_options', - heading_tag: :h3, - heading: t('inherited_proofing.troubleshooting.headings.need_help_updating'), - options: [ - { - url: @presenter.get_help_url, - text: t( - 'inherited_proofing.troubleshooting.options.get_help', - sp_name: decorated_session.sp_name, - ), - new_tab: true, - }, - ].select(&:present?), - ) %> - -<%= render 'idv/inherited_proofing/cancel', step: 'verify_info' %> diff --git a/app/views/idv/inherited_proofing/verify_wait.html.erb b/app/views/idv/inherited_proofing/verify_wait.html.erb deleted file mode 100644 index 2936142e739..00000000000 --- a/app/views/idv/inherited_proofing/verify_wait.html.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%= content_for(:meta_refresh) { @meta_refresh.to_s } %> -<% title t('inherited_proofing.headings.retrieval') %> - -<%= render PageHeadingComponent.new.with_content(t('inherited_proofing.headings.retrieval')) %> - -
- <%= image_tag( - asset_url('shield-spinner.gif'), - alt: '', - width: 120, - height: 120, - ) %> -
- -

<%= t('inherited_proofing.info.retrieval_time') %>

-

<%= t('inherited_proofing.info.retrieval_thanks') %>

-<%= render 'idv/inherited_proofing/cancel', step: 'verify_info' %> diff --git a/app/views/idv/inherited_proofing_cancellations/destroy.html.erb b/app/views/idv/inherited_proofing_cancellations/destroy.html.erb deleted file mode 100644 index 116524f15b5..00000000000 --- a/app/views/idv/inherited_proofing_cancellations/destroy.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -<% title t('titles.inherited_proofing.cancelled') %> - -<%= render StatusPageComponent.new(status: :error) do |c| %> - <% c.header { t('inherited_proofing.cancel.headings.confirmation.hybrid') } %> - -

<%= t('inherited_proofing.cancel.instructions.switch_back') %>

- <%= image_tag(asset_url('inherited_proofing/switch.png'), width: 193, height: 109, alt: t('inherited_proofing.cancel.instructions.switch_back_image')) %> -<% end %> diff --git a/app/views/idv/inherited_proofing_cancellations/new.html.erb b/app/views/idv/inherited_proofing_cancellations/new.html.erb deleted file mode 100644 index 159f8363027..00000000000 --- a/app/views/idv/inherited_proofing_cancellations/new.html.erb +++ /dev/null @@ -1,54 +0,0 @@ -<% title t('titles.inherited_proofing.cancellation_prompt') %> - -<%= render StatusPageComponent.new(status: :warning) do |c| %> - <% c.header { t('inherited_proofing.cancel.headings.prompt.standard') } %> - -

<%= t('inherited_proofing.cancel.headings.start_over') %>

- -

<%= t('inherited_proofing.cancel.description.start_over') %>

- -
- <%= render ButtonComponent.new( - action: ->(**tag_options, &block) do - button_to(idv_inherited_proofing_session_path(step: @flow_step), **tag_options, &block) - end, - method: :delete, - big: true, - wide: true, - ).with_content(t('inherited_proofing.cancel.actions.start_over')) %> -
- <%= render ButtonComponent.new( - action: ->(**tag_options, &block) do - button_to(idv_inherited_proofing_cancel_path(step: @flow_step), **tag_options, &block) - end, - method: :put, - big: true, - wide: true, - outline: true, - ).with_content(t('inherited_proofing.cancel.actions.keep_going')) %> -
-
- -
- -

<%= @presenter.exit_heading %>

- - <% @presenter.exit_description.each do |p_content| %> -

<%= p_content %>

- <% end %> - -
- <%= render SpinnerButtonComponent.new( - action: ->(**tag_options, &block) do - button_to(idv_inherited_proofing_cancel_path(step: @flow_step, location: 'cancel'), **tag_options, &block) - end, - method: :delete, - big: true, - wide: true, - outline: true, - form: { data: { form_steps_wait: '' } }, - ).with_content(@presenter.exit_action_text) %> -
-<% end %> - -<% javascript_packs_tag_once 'form-steps-wait' %> diff --git a/app/views/idv/inherited_proofing_errors/failure.html.erb b/app/views/idv/inherited_proofing_errors/failure.html.erb deleted file mode 100644 index 1fc683429f7..00000000000 --- a/app/views/idv/inherited_proofing_errors/failure.html.erb +++ /dev/null @@ -1,29 +0,0 @@ -<%= render( - 'idv/shared/error', - title: t('inherited_proofing.errors.cannot_retrieve.title'), - heading: t('inherited_proofing.errors.cannot_retrieve.heading'), - ) do %> -

- <%= t('inherited_proofing.errors.cannot_retrieve.failure_info') %> -

- - <%= render( - 'shared/troubleshooting_options', - heading: t('inherited_proofing.troubleshooting.headings.need_assistance'), - options: [ - { - url: @presenter.get_help_url, - text: t( - 'inherited_proofing.troubleshooting.options.get_help', - sp_name: decorated_session.sp_name, - ), - new_tab: true, - }, - { - url: @presenter.contact_support_url, - text: t('idv.troubleshooting.options.contact_support', app_name: APP_NAME), - new_tab: true, - }, - ], - ) %> -<% end %> diff --git a/app/views/idv/inherited_proofing_errors/warning.html.erb b/app/views/idv/inherited_proofing_errors/warning.html.erb deleted file mode 100644 index 70448fbd81e..00000000000 --- a/app/views/idv/inherited_proofing_errors/warning.html.erb +++ /dev/null @@ -1,27 +0,0 @@ -<%= render( - 'idv/shared/error', - type: :warning, - title: t('inherited_proofing.errors.cannot_retrieve.title'), - heading: t('inherited_proofing.errors.cannot_retrieve.heading'), - ) do %> -

- <%= t('inherited_proofing.errors.cannot_retrieve.info') %> -

- - <%= button_to t('inherited_proofing.buttons.try_again'), idv_inherited_proofing_step_path(step: :redo_retrieve_user_info), method: :put, class: 'usa-button usa-button--big usa-button--wide' %> - - <%= render( - 'shared/troubleshooting_options', - heading: t('components.troubleshooting_options.default_heading'), - options: [ - { - url: @presenter.get_help_url, - text: t( - 'inherited_proofing.troubleshooting.options.get_help', - sp_name: decorated_session.sp_name, - ), - new_tab: true, - }, - ], - ) %> -<% end %> diff --git a/config/application.yml.default b/config/application.yml.default index 788586fcf0a..4c0b5ee2cbd 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -143,11 +143,6 @@ in_person_results_delay_in_hours: 1 in_person_completion_survey_url: 'https://login.gov' in_person_verify_info_controller_enabled: false include_slo_in_saml_metadata: false -inherited_proofing_enabled: false -inherited_proofing_va_base_url: 'https://staging-api.va.gov' -inherited_proofing_max_attempts: 2 -inherited_proofing_max_attempt_window_in_minutes: 1 -va_inherited_proofing_mock_enabled: false irs_attempt_api_audience: 'https://irs.gov' irs_attempt_api_auth_tokens: '' irs_attempt_api_csp_id: 'LOGIN.gov' @@ -373,8 +368,6 @@ development: hmac_fingerprinter_key_queue: '["11111111111111111111111111111111", "22222222222222222222222222222222"]' identity_pki_local_dev: true in_person_proofing_enabled: true - inherited_proofing_enabled: true - va_inherited_proofing_mock_enabled: true irs_attempt_api_public_key: MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyut9Uio5XxsIUVrXARqCoHvcMVYT0p6WyU1BnbhxLRW4Q60p+4Bn32vVOt9nzeih7qvauYM5M0PZdKEmwOHflqPP+ABfKhL+6jxBhykN5P5UY375wTFBJZ20Fx8jOJbRhJD02oUQ49YKlDu3MG5Y0ApyD4ER4WKgxuB2OdyQKd9vg2ZZa+P2pw1HkFPEin0h8KBUFBeLGDZni8PIJdHBP6dA+xbayGBxSM/8xQC0JIg6KlGTcLql37QJIhP2oSv0nAJNb6idFPAz0uMCQDQWKKWV5FUDCsFVH7VuQz8xUCwnPn/SdaratB+29bwUpVhgHXrHdJ0i8vjBEX7smD7pI8CcFHuVgACt86NMlBnNCVkwumQgZNAAxe2mJoYcotEWOnhCuMc6MwSj985bj8XEdFlbf4ny9QO9rETd5aYcwXBiV/T6vd637uvHb0KenghNmlb1Tv9LMj2b9ZwNc9C6oeCnbN2YAfxSDrb8Ik+yq4hRewOvIK7f0CcpZYDXK25aHXnHm306Uu53KIwMGf1mha5T5LWTNaYy5XFoMWHJ9E+AnU/MUJSrwCAITH/S0JFcna5Oatn70aTE9pISATsqB5Iz1c46MvdrxD8hPoDjT7x6/EO316DZrxQfJhjbWsCB+R0QxYLkXPHczhB2Z0HPna9xB6RbJHzph7ifDizhZoMCAwEAAQ== irs_attempt_api_public_key_id: key1 irs_attempt_api_enabled: true @@ -523,8 +516,6 @@ test: hmac_fingerprinter_key: a2c813d4dca919340866ba58063e4072adc459b767a74cf2666d5c1eef3861db26708e7437abde1755eb24f4034386b0fea1850a1cb7e56bff8fae3cc6ade96c hmac_fingerprinter_key_queue: '["old-key-one", "old-key-two"]' identity_pki_disabled: true - inherited_proofing_enabled: true - va_inherited_proofing_mock_enabled: false irs_attempt_api_auth_tokens: 'test-token-1,test-token-2' irs_attempt_api_public_key: MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyut9Uio5XxsIUVrXARqCoHvcMVYT0p6WyU1BnbhxLRW4Q60p+4Bn32vVOt9nzeih7qvauYM5M0PZdKEmwOHflqPP+ABfKhL+6jxBhykN5P5UY375wTFBJZ20Fx8jOJbRhJD02oUQ49YKlDu3MG5Y0ApyD4ER4WKgxuB2OdyQKd9vg2ZZa+P2pw1HkFPEin0h8KBUFBeLGDZni8PIJdHBP6dA+xbayGBxSM/8xQC0JIg6KlGTcLql37QJIhP2oSv0nAJNb6idFPAz0uMCQDQWKKWV5FUDCsFVH7VuQz8xUCwnPn/SdaratB+29bwUpVhgHXrHdJ0i8vjBEX7smD7pI8CcFHuVgACt86NMlBnNCVkwumQgZNAAxe2mJoYcotEWOnhCuMc6MwSj985bj8XEdFlbf4ny9QO9rETd5aYcwXBiV/T6vd637uvHb0KenghNmlb1Tv9LMj2b9ZwNc9C6oeCnbN2YAfxSDrb8Ik+yq4hRewOvIK7f0CcpZYDXK25aHXnHm306Uu53KIwMGf1mha5T5LWTNaYy5XFoMWHJ9E+AnU/MUJSrwCAITH/S0JFcna5Oatn70aTE9pISATsqB5Iz1c46MvdrxD8hPoDjT7x6/EO316DZrxQfJhjbWsCB+R0QxYLkXPHczhB2Z0HPna9xB6RbJHzph7ifDizhZoMCAwEAAQ== irs_attempt_api_public_key_id: key1 diff --git a/config/locales/errors/en.yml b/config/locales/errors/en.yml index 83688ef42fd..cb1d6c92a8a 100644 --- a/config/locales/errors/en.yml +++ b/config/locales/errors/en.yml @@ -34,9 +34,6 @@ en: security, we limit the number of times you can attempt to verify a document online.' general: Oops, something went wrong. Please try again. - inherited_proofing: - consent_form: Before you can continue, you must give us permission. Please check - the box below and then click continue.blah invalid_totp: Invalid code. Please try again. max_password_attempts_reached: You’ve entered too many incorrect passwords. You can reset your password using the “Forgot your password?” link. diff --git a/config/locales/errors/es.yml b/config/locales/errors/es.yml index bf923b3355f..eb5aa277e49 100644 --- a/config/locales/errors/es.yml +++ b/config/locales/errors/es.yml @@ -35,8 +35,6 @@ es: %{timeout}. Por su seguridad, limitamos el número de veces que puede intentar verificar un documento en línea.' general: '¡Oops! Algo salió mal. Inténtelo de nuevo.' - inherited_proofing: - consent_form: to be implemented invalid_totp: El código es inválido. Vuelva a intentarlo. max_password_attempts_reached: Ha ingresado demasiadas contraseñas incorrectas. Puede restablecer su contraseña usando el enlace “¿Olvidó su contraseña?”. diff --git a/config/locales/errors/fr.yml b/config/locales/errors/fr.yml index d2b4a55b0f0..b1649a805d0 100644 --- a/config/locales/errors/fr.yml +++ b/config/locales/errors/fr.yml @@ -39,8 +39,6 @@ fr: votre sécurité, nous limitons le nombre de fois où vous pouvez tenter de vérifier un document en ligne.' general: Oups, une erreur s’est produite. Veuillez essayer de nouveau. - inherited_proofing: - consent_form: to be implemented invalid_totp: Code non valide. Veuillez essayer de nouveau. max_password_attempts_reached: Vous avez inscrit des mots de passe incorrects un trop grand nombre de fois. Vous pouvez réinitialiser votre mot de passe en diff --git a/config/locales/inherited_proofing/en.yml b/config/locales/inherited_proofing/en.yml deleted file mode 100644 index 38da46a43ab..00000000000 --- a/config/locales/inherited_proofing/en.yml +++ /dev/null @@ -1,71 +0,0 @@ ---- -en: - inherited_proofing: - buttons: - continue: Continue - try_again: Try again - cancel: - actions: - keep_going: No, keep going - start_over: Start over - description: - start_over: If you start over, you will restart this process from the beginning - and the information you entered will not be saved. - headings: - confirmation: - hybrid: You have cancelled uploading photos of your ID on this phone - prompt: - standard: Cancel verifying your identity? - start_over: Start over verifying your identity - instructions: - switch_back: Switch back to your computer to finish verifying your identity. - switch_back_image: Arrow pointing from phone to computer - errors: - cannot_retrieve: - failure_info: Please check back later. - heading: We could not retrieve your information from your Partner Agency - info: We are temporarily having trouble retrieving your information. Please try - again. - title: Couldn’t retrieve information - service_provider: - communication: 'communication was unsuccessful' - headings: - lets_go: How verifying your identity works - retrieval: We are retrieving your information from your Partner Agency - secure_account: Secure your account - verify_identity: Verify your identity - verify_information: Verify your information - welcome: Get started verifying your identity - info: - lets_go: 'Identity verification happens in two parts:' - no_sp_name: VA needs to make sure you are you - privacy_html: '%{app_name} is a secure, government website that adheres to the - highest standards in data protection. We only use your data to verify - your identity. %{link} about our privacy and security measures.' - retrieval_thanks: Thanks for your patience! - retrieval_time: This might take up to a minute. We’ll load the next step - automatically when it’s done. - secure_account: We’ll encrypt your account with your password. Encryption means - your data is protected and only you will be able to access or change - your information. - verify_identity: We’ll retrieve your personal information from %{sp_name} and - ask you to verify it. - welcome_html: '%{sp_name} needs to make sure you are you - not someone - pretending to be you.' - instructions: - consent: By checking this box, you are letting login.gov ask for, use, keep, and - share your personal information. We will only use it to verify your - identity. - learn_more: Learn more - privacy: Our privacy and security standards - verify_requirements: We’ll call or text your phone number to verify your - identity. If we can’t verify your phone number, you can verify by mail - instead. - troubleshooting: - headings: - missing_required_items: Don’t have a phone number? Here’s how to get help - need_assistance: 'Need immediate assistance? Here’s how to get help:' - need_help_updating: Need to update your information? Here’s how to get help - options: - get_help: Get help at the %{sp_name} web site - learn_more_phone_or_mail: Learn more about verifying by phone or mail diff --git a/config/locales/inherited_proofing/es.yml b/config/locales/inherited_proofing/es.yml deleted file mode 100644 index d79cfd9ead4..00000000000 --- a/config/locales/inherited_proofing/es.yml +++ /dev/null @@ -1,76 +0,0 @@ ---- -es: - inherited_proofing: - buttons: - continue: Continuar - try_again: Inténtelo de nuevo - cancel: - actions: - keep_going: No, continuar - start_over: Empezar de nuevo - description: - start_over: Si empieza de nuevo, el proceso se reiniciará y la información que - haya ingresado se perderá. - headings: - confirmation: - hybrid: Ha cancelado la carga de fotos de su identificación en este teléfono - prompt: - standard: '¿Cancelar la verificación de su identidad?' - start_over: Empezar de nuevo a verificar su identidad - instructions: - switch_back: Regrese a su computadora para continuar con la verificación de su - identidad. - switch_back_image: Flecha que apunta del teléfono a la computadora - errors: - cannot_retrieve: - failure_info: to be implemented - heading: No hemos podido obtener su información de su agencia colaboradora - info: Estamos teniendo problemas temporalmente para obtener su información. - Inténtelo de nuevo. - title: to be implemented - service_provider: - communication: 'la comunicacion no tuvo exito' - headings: - lets_go: Cómo funciona la verificación de su identidad - retrieval: Estamos recuperando su información de su agencia colaboradora - secure_account: Asegure su cuenta - verify_identity: Verifique su identidad - verify_information: Verifique su información - welcome: Empiece con la verificación de su identidad - info: - lets_go: 'La verificación de la identidad se realiza en dos partes:' - no_sp_name: La agencia a la que está intentando acceder - privacy_html: '%{app_name} es un sitio web gubernamental seguro que cumple con - las normas más estrictas de protección de datos. Solo utilizamos sus - datos para verificar su identidad. %{link} sobre nuestras medidas de - privacidad y seguridad.' - retrieval_thanks: '¡Gracias por su paciencia!' - retrieval_time: Esto puede tardar hasta un minuto. Cargaremos el siguiente paso - automáticamente cuando haya terminado. - secure_account: Cifraremos su cuenta con su contraseña. La encriptación - significa que sus datos están protegidos y solo usted podrá acceder o - modificar su información. - verify_identity: Obtendremos su información personal de %{sp_name} y le - pediremos que la verifique. - welcome_html: '%{sp_name} necesita asegurarse de que sea usted y no alguien que - se haga pasar por usted.' - instructions: - consent: Al marcar esta casilla, usted permite que login.gov solicite, utilice, - conserve y comparta su información personal. Solo la utilizaremos para - verificar su identidad. - learn_more: Obtenga más información - privacy: Nuestras normas de privacidad y seguridad - verify_requirements: Te llamaremos o te enviaremos un mensaje de texto a tu - número de teléfono para verificar tu identidad. Si no podemos verificar - tu número de teléfono, puedes realizar la verificación por correo - postal. - troubleshooting: - headings: - missing_required_items: ¿No tienes número de teléfono? A continuación, te - indicamos cómo obtener ayuda - need_assistance: to be implemented - need_help_updating: ¿Necesita actualizar su información? A continuación le - indicamos cómo obtener ayuda - options: - get_help: Obtenga ayuda en %{sp_name} - learn_more_phone_or_mail: Más información sobre la verificación por teléfono o correo postal. diff --git a/config/locales/inherited_proofing/fr.yml b/config/locales/inherited_proofing/fr.yml deleted file mode 100644 index 140a6dc8650..00000000000 --- a/config/locales/inherited_proofing/fr.yml +++ /dev/null @@ -1,76 +0,0 @@ ---- -fr: - inherited_proofing: - buttons: - continue: Continuer - try_again: Réessayez - cancel: - actions: - keep_going: Non, continuer - start_over: Recommencer - description: - start_over: Si vous recommencez, vous reprendrez ce processus depuis le début et - les informations que vous avez saisies ne seront pas enregistrées. - headings: - confirmation: - hybrid: Vous avez annulé le téléchargement de vos photos d’identité sur ce - téléphone - prompt: - standard: Annuler la vérification de votre identité? - start_over: Recommencez la vérification de votre identité - instructions: - switch_back: Retournez sur votre ordinateur pour continuer à vérifier votre - identité. - switch_back_image: Flèche pointant du téléphone vers l’ordinateur - errors: - cannot_retrieve: - failure_info: to be implemented - heading: Nous n’avons pas pu récupérer vos informations dans votre agence - partenaire - info: Nous avons temporairement des difficultés à récupérer vos informations. - Veuillez réessayer. - title: to be implemented - service_provider: - communication: 'la communication a échoué' - headings: - lets_go: Comment fonctionne la vérification de votre identité - retrieval: Nous récupérons vos informations depuis votre agence partenaire. - secure_account: Sécuriser votre compte - verify_identity: Vérifier votre identité - verify_information: Vérifier votre information - welcome: Commencez à vérifier votre identité - info: - lets_go: 'La vérification de l’identité se fait en deux temps :' - no_sp_name: L’agence à laquelle vous essayez d’accéder - privacy_html: '%{app_name} est un site gouvernemental sécurisé qui respecte les - normes les plus strictes en matière de protection des données. Nous - n’utilisons vos données uniquement pour vérifier votre identité. %{link} - sur nos mesures de confidentialité et de sécurité.' - retrieval_thanks: Merci de votre patience! - retrieval_time: Cette opération peut prendre jusqu’à une minute. Nous chargerons - automatiquement l’étape suivante lorsque ce sera fait. - secure_account: Votre compte sera crypté avec votre mot de passe. Le cryptage - signifie que vos données sont protégées et que vous seul pourrez accéder - à vos informations ou les modifier. - verify_identity: Nous récupérerons vos informations personnelles sur %{sp_name} - et vous demanderons de les vérifier. - welcome_html: '%{sp_name} doit s’assurer que vous êtes bien vous, et non - quelqu’un qui se fait passer pour vous' - instructions: - consent: En cochant cette case, vous autorisez login.gov à demander, utiliser, - conserver et partager vos renseignements personnels. Nous ne les - utiliserons que pour vérifier votre identité. - learn_more: En savoir plus - privacy: Nos normes de confidentialité et de sécurité - verify_requirements: Nous allons vous appeler ou vous envoyer un SMS à partir de - votre contact pour vérifier votre identité. Si nous ne pouvons pas - vérifier votre numéro de téléphone, vous pouvez le faire par courriel. - troubleshooting: - headings: - missing_required_items: Vous n’avez pas de numéro de téléphone? Voici comment obtenir de l’aide - need_assistance: to be implemented - need_help_updating: Vous devez mettre à jour vos informations? Voici comment - obtenir de l’aide - options: - get_help: Obtenez de l’aide sur %{sp_name} - learn_more_phone_or_mail: En savoir plus sur la vérification par téléphone ou par courriel. diff --git a/config/locales/titles/en.yml b/config/locales/titles/en.yml index 783638a1ef9..2c68199daf3 100644 --- a/config/locales/titles/en.yml +++ b/config/locales/titles/en.yml @@ -42,9 +42,6 @@ en: reset_password: Reset Password review: Re-enter your password verify_info: Verify your information - inherited_proofing: - cancellation_prompt: Cancel identity verification - cancelled: Identity verification is cancelled mfa_setup: suggest_second_mfa: You’ve added your first authentication method! Add a second method as a backup. diff --git a/config/locales/titles/es.yml b/config/locales/titles/es.yml index 458620a62ee..8fd68b95f94 100644 --- a/config/locales/titles/es.yml +++ b/config/locales/titles/es.yml @@ -42,9 +42,6 @@ es: reset_password: Restablecer la contraseña review: Vuelve a ingresar tu contraseña verify_info: Verifica tu información - inherited_proofing: - cancellation_prompt: Cancela la verificación de identidad - cancelled: Se canceló la verificación de identidad mfa_setup: suggest_second_mfa: '¡Has agregado tu primer método de autenticación! Agrega un segundo método como respaldo.' diff --git a/config/locales/titles/fr.yml b/config/locales/titles/fr.yml index 5175de061b2..84a680fed84 100644 --- a/config/locales/titles/fr.yml +++ b/config/locales/titles/fr.yml @@ -42,9 +42,6 @@ fr: reset_password: Réinitialisez le mot de passe review: Saisissez à nouveau votre mot de passe verify_info: Vérifiez vos informations - inherited_proofing: - cancellation_prompt: Annulez la vérification d’identité - cancelled: La vérification d’identité est annulée mfa_setup: suggest_second_mfa: Vous avez ajouté votre première méthode d’authentification ! Ajoutez-en une deuxième en guise de sauvegarde. diff --git a/config/routes.rb b/config/routes.rb index 20fb8449910..bbee73be125 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -366,22 +366,6 @@ post '/confirmations' => 'personal_key#update' end - # Inherited Proofing (IP)-specific routes. - scope '/verify/inherited_proofing', module: 'idv', as: 'idv_inherited_proofing' do - # NOTE: cancellation routes need to be before any other IP - # routes in this scope. - delete '/session' => 'sessions#destroy' - get '/cancel' => 'inherited_proofing_cancellations#new', as: :cancel - put '/cancel' => 'inherited_proofing_cancellations#update' - delete '/cancel' => 'inherited_proofing_cancellations#destroy' - get '/' => 'inherited_proofing#index' - get '/:step' => 'inherited_proofing#show', as: :step - put '/:step' => 'inherited_proofing#update' - get '/return_to_sp' => 'inherited_proofing#return_to_sp' - get '/errors/no_information' => 'inherited_proofing_errors#warning' - get '/errors/failure' => 'inherited_proofing_errors#failure' - end - namespace :api do post '/verify/v2/document_capture' => 'verify/document_capture#create' delete '/verify/v2/document_capture_errors' => 'verify/document_capture_errors#delete' diff --git a/lib/identity_config.rb b/lib/identity_config.rb index e5982dfcfc6..f6ff43b26c1 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -222,11 +222,6 @@ def self.build_store(config_map) config.add(:in_person_completion_survey_url, type: :string) config.add(:in_person_verify_info_controller_enabled, type: :boolean) config.add(:include_slo_in_saml_metadata, type: :boolean) - config.add(:inherited_proofing_enabled, type: :boolean) - config.add(:inherited_proofing_va_base_url, type: :string) - config.add(:inherited_proofing_max_attempts, type: :integer) - config.add(:inherited_proofing_max_attempt_window_in_minutes, type: :integer) - config.add(:va_inherited_proofing_mock_enabled, type: :boolean) config.add(:irs_attempt_api_audience) config.add(:irs_attempt_api_auth_tokens, type: :comma_separated_string_list) config.add(:irs_attempt_api_bucket_name, type: :string, allow_nil: true) diff --git a/lib/session_encryptor.rb b/lib/session_encryptor.rb index 113a1b496b1..2ac918f8f7d 100644 --- a/lib/session_encryptor.rb +++ b/lib/session_encryptor.rb @@ -20,7 +20,6 @@ class SensitiveValueError < StandardError; end # personal keys are generated and stored in the session between requests, but are used # to decrypt PII bundles, so we treat them similarly to the PII itself. SENSITIVE_PATHS = [ - ['warden.user.user.session', 'idv/inherited_proofing'], ['warden.user.user.session', 'idv/doc_auth'], ['warden.user.user.session', 'idv/in_person'], ['warden.user.user.session', 'idv'], diff --git a/scripts/inherited_proofing/errorable.rb b/scripts/inherited_proofing/errorable.rb deleted file mode 100644 index 2c4bd406de6..00000000000 --- a/scripts/inherited_proofing/errorable.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Scripts - module InheritedProofing - module Errorable - module_function - - def puts_message(message) - puts message - end - - def puts_success(message) - puts_message "Success: #{message}" - end - - def puts_warning(message) - puts_message "Warning: #{message}" - end - - def puts_error(message) - puts_message "Oops! An error occurred: #{message}" - end - end - end -end diff --git a/scripts/inherited_proofing/va/lexis_nexis/phone_finder.rb b/scripts/inherited_proofing/va/lexis_nexis/phone_finder.rb deleted file mode 100644 index 4f32e37e5f1..00000000000 --- a/scripts/inherited_proofing/va/lexis_nexis/phone_finder.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Scripts - module InheritedProofing - module Va - module LexisNexis - module PhoneFinder - class << self - def call(user_pii) - proofer = if IdentityConfig.store.proofer_mock_fallback - Proofing::Mock::AddressMockClient.new - else - Proofing::LexisNexis::PhoneFinder::Proofer.new( - phone_finder_workflow: IdentityConfig.store.lexisnexis_phone_finder_workflow, - account_id: IdentityConfig.store.lexisnexis_account_id, - base_url: IdentityConfig.store.lexisnexis_base_url, - username: IdentityConfig.store.lexisnexis_username, - password: IdentityConfig.store.lexisnexis_password, - request_mode: IdentityConfig.store.lexisnexis_request_mode, - ) - end - - proofer.proof user_pii - end - end - end - end - end - end -end diff --git a/scripts/inherited_proofing/va/lexis_nexis/test_script.rb b/scripts/inherited_proofing/va/lexis_nexis/test_script.rb deleted file mode 100644 index 7a3d17c5262..00000000000 --- a/scripts/inherited_proofing/va/lexis_nexis/test_script.rb +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env ruby - -# rubocop:disable Layout/LineLength - -# Usage -# -# 1) Run with no ARGV and BASE_URI in the Idv::InheritedProofing::Va::Service -# will default to a base uri of: IdentityConfig.store.inherited_proofing_va_base_url -# and a private key using: AppArtifacts.store.oidc_private_key -# -# $ bin/rails r scripts/inherited_proofing/va/lexis_nexis/test_script.rb -# -# 2) To override BASE_URI in the Idv::InheritedProofing::Va::Service class -# and/or use a private key file, and/or force an error return. -# Where -u|-t|-f forces proofing to fail -# -# NOTE: Private key files are forced to be located at "#{Rails.root}/tmp". -# $ bin/rails r scripts/inherited_proofing/va/lexis_nexis/test_script.rb https://staging-api.va.gov private.key -u|-t|-f - -require_relative '../user_attributes/test_server' -require_relative './phone_finder' -require_relative '../../errorable' - -def error_phone_or_default(fail_option:, default_phone:) - return case fail_option - when '-u' - Scripts::InheritedProofing::Errorable.puts_message "Forcing unverifiable phone number failure (#{fail_option})" - Proofing::Mock::AddressMockClient::UNVERIFIABLE_PHONE_NUMBER - when '-t' - Scripts::InheritedProofing::Errorable.puts_message "Forcing proofer timeout failure (#{fail_option})" - Proofing::Mock::AddressMockClient::PROOFER_TIMEOUT_PHONE_NUMBER - when '-f' - Scripts::InheritedProofing::Errorable.puts_message "Forcing failed to contact phone number (#{fail_option})" - Proofing::Mock::AddressMockClient::FAILED_TO_CONTACT_PHONE_NUMBER - else - default_phone - end -end - -raise 'You must run this from the command-line!' unless $PROGRAM_NAME == __FILE__ - -Scripts::InheritedProofing::Errorable.puts_message "\nTesting call to Lexis Nexis Phone Finder - START" - -form, form_response = Scripts::InheritedProofing::Va::UserAttributes::TestServer.new( - auth_code: 'mocked-auth-code-for-testing', - base_uri: ARGV[0], - private_key_file: ARGV[1], -).run - -Scripts::InheritedProofing::Errorable.puts_message "Form response:\n\t#{form_response.to_h}" - -user_pii = form.payload_hash -user_pii[:uuid] = SecureRandom.uuid -# Lexis Nexis Phone Finder expects dob (as opposed to birth_date). -user_pii[:dob] = user_pii.delete(:birth_date) -user_pii[:phone] = error_phone_or_default fail_option: ARGV[2], default_phone: user_pii[:phone] -user_pii.delete(:address) -user_pii.delete(:mhv_data) - -Scripts::InheritedProofing::Errorable.puts_message "Calling Lexis Nexis Phone Finder using:\n\t#{user_pii}}" - -# Verify the user's pii. -address_proofer_results = Scripts::InheritedProofing::Va::LexisNexis::PhoneFinder.call(user_pii) - -Scripts::InheritedProofing::Errorable.puts_message "Call to Lexis Nexis Phone Finder complete. Results:\n\t#{address_proofer_results.to_h}" - -Scripts::InheritedProofing::Errorable.puts_message "\nTesting call to Lexis Nexis Phone Finder - END" - -Scripts::InheritedProofing::Errorable.puts_message "\nDone." -# rubocop:enable Layout/LineLength diff --git a/scripts/inherited_proofing/va/user_attributes/test_script.rb b/scripts/inherited_proofing/va/user_attributes/test_script.rb deleted file mode 100644 index 7586c86ee2e..00000000000 --- a/scripts/inherited_proofing/va/user_attributes/test_script.rb +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env ruby - -# Usage -# -# 1) Run with no ARGV and BASE_URI in the Idv::InheritedProofing::Va::Service -# will default to a base uri of: IdentityConfig.store.inherited_proofing_va_base_url -# and a private key using: AppArtifacts.store.oidc_private_key -# -# $ bin/rails r scripts/inherited_proofing/va/user_attributes/test_script.rb -# -# 2) To override BASE_URI in the Idv::InheritedProofing::Va::Service class -# and/or use a private key file: -# -# rubocop:disable Layout/LineLength -# NOTE: Private key files are forced to be located at "#{Rails.root}/tmp". -# $ bin/rails r scripts/inherited_proofing/va/user_attributes/test_script.rb https://staging-api.va.gov private.key -# rubocop:enable Layout/LineLength - -require_relative '../../../../app/services/idv/inherited_proofing/va/service' -require_relative '../../../../app/forms/idv/inherited_proofing/va/form' -require_relative '../../errorable' -require_relative './test_server' - -raise 'You must run this from the command-line!' unless $PROGRAM_NAME == __FILE__ - -Scripts::InheritedProofing::Errorable.puts_message "\nTesting call to VA API - START\n\n" - -_form, form_response = Scripts::InheritedProofing::Va::UserAttributes::TestServer.new( - auth_code: 'mocked-auth-code-for-testing', - base_uri: ARGV[0], - private_key_file: ARGV[1], -).run - -Scripts::InheritedProofing::Errorable.puts_message "Form response:\n\t#{form_response.to_h}" - -Scripts::InheritedProofing::Errorable.puts_message "\nTesting call to VA API - END" - -Scripts::InheritedProofing::Errorable.puts_message "\nDone." diff --git a/scripts/inherited_proofing/va/user_attributes/test_server.rb b/scripts/inherited_proofing/va/user_attributes/test_server.rb deleted file mode 100644 index ce5a65b2e9b..00000000000 --- a/scripts/inherited_proofing/va/user_attributes/test_server.rb +++ /dev/null @@ -1,88 +0,0 @@ -require_relative '../../errorable' - -module Scripts - module InheritedProofing - module Va - module UserAttributes - class TestServer < Idv::InheritedProofing::Va::Service - include Errorable - - attr_reader :base_uri - - def initialize(auth_code:, private_key_file: nil, base_uri: nil) - super({ auth_code: auth_code }) - - if private_key_file.present? - @private_key_file = force_tmp_private_key_file_name(private_key_file) - end - @base_uri = base_uri || BASE_URI - end - - def run - begin - # rubocop:disable Layout/LineLength - puts_message "Retrieving the user's PII from the VA using auth code: '#{auth_code}' at #{request_uri}..." - puts_message "Retrieved payload containing the user's PII from the VA:\n\tRetrieved user PII: #{user_pii}" - # rubocop:enable Layout/LineLength - - puts_message "Validating payload containing the user's PII from the VA..." - if form_response.success? - puts_success "Retrieved user PII is valid:\n\t#{user_pii}" - else - puts_error "Payload returned from the VA is invalid:" \ - "\n\t#{form.errors.full_messages}" - end - rescue => e - puts_error e.message - end - - [form, form_response] - end - - private - - attr_reader :private_key_file - - # Override - def request_uri - @request_uri ||= "#{ URI(@base_uri) }/inherited_proofing/user_attributes" - end - - def user_pii - @user_pii ||= execute - end - - def form - @form ||= Idv::InheritedProofing::Va::Form.new(payload_hash: user_pii) - end - - def form_response - @form_response ||= form.submit - end - - def private_key - if private_key_file? - if File.exist?(private_key_file) - return OpenSSL::PKey::RSA.new(File.read(private_key_file)) - else - puts_warning "private key file does not exist, using artifacts store: " \ - "#{private_key_file}" - end - end - - AppArtifacts.store.oidc_private_key - end - - def private_key_file? - @private_key_file.present? - end - - # Always ensure we're referencing files in the /tmp/ folder! - def force_tmp_private_key_file_name(private_key_file) - "#{Rails.root}/tmp/#{File.basename(private_key_file)}" - end - end - end - end - end -end diff --git a/spec/controllers/concerns/inherited_proofing_concern_spec.rb b/spec/controllers/concerns/inherited_proofing_concern_spec.rb deleted file mode 100644 index 5796827f075..00000000000 --- a/spec/controllers/concerns/inherited_proofing_concern_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'rails_helper' - -RSpec.describe InheritedProofingConcern do - subject do - Class.new do - include InheritedProofingConcern - end.new - end - - before do - allow(IdentityConfig.store).to receive(:inherited_proofing_enabled).and_return(true) - allow(subject).to receive(:va_inherited_proofing_auth_code).and_return auth_code - end - - let(:auth_code) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - let(:payload_hash) { Idv::InheritedProofing::Va::Mocks::Service::PAYLOAD_HASH } - - describe '#inherited_proofing?' do - context 'when inherited proofing proofing is not effect' do - let(:auth_code) { nil } - - it 'returns false' do - expect(subject.inherited_proofing?).to eq false - end - end - - context 'when inherited proofing proofing is effect' do - it 'returns true' do - expect(subject.inherited_proofing?).to eq true - end - end - end - - describe '#inherited_proofing_service_provider' do - context 'when a service provider cannot be identified' do - before do - allow(subject).to receive(:va_inherited_proofing_auth_code).and_return nil - end - - it 'returns nil' do - expect(subject.inherited_proofing_service_provider).to eq nil - end - end - - context 'when a service provider can be identified' do - let(:va) { :va } - - it 'returns the service provider' do - expect(subject.inherited_proofing_service_provider).to eq va - end - end - end - - describe '#va_inherited_proofing?' do - context 'when the va auth code is present' do - it 'returns true' do - expect(subject.va_inherited_proofing?).to eq true - end - end - - context 'when the va auth code is not present' do - let(:auth_code) { nil } - - it 'returns false' do - expect(subject.va_inherited_proofing?).to eq false - end - end - end - - describe '#va_inherited_proofing_auth_code_params_key' do - it 'returns the correct va auth code url query param key' do - expect(subject.va_inherited_proofing_auth_code_params_key).to eq 'inherited_proofing_auth' - end - end - - describe '#inherited_proofing_service_provider_data' do - context 'when there is a va inherited proofing request' do - it 'returns the correct service provider-specific data' do - expect(subject.inherited_proofing_service_provider_data).to \ - eq({ auth_code: auth_code }) - end - end - - context 'when the inherited proofing request cannot be identified' do - let(:auth_code) { nil } - - it 'returns an empty hash' do - expect(subject.inherited_proofing_service_provider_data).to eq({}) - end - end - end -end diff --git a/spec/controllers/idv/inherited_proofing_cancellations_controller_spec.rb b/spec/controllers/idv/inherited_proofing_cancellations_controller_spec.rb deleted file mode 100644 index 86451d87906..00000000000 --- a/spec/controllers/idv/inherited_proofing_cancellations_controller_spec.rb +++ /dev/null @@ -1,245 +0,0 @@ -require 'rails_helper' - -shared_examples 'an HTML 404 not found' do - it 'returns a 404 not found' do - expect(response).to have_http_status(:not_found) - end -end - -describe Idv::InheritedProofingCancellationsController do - let(:step) { Idv::Flows::InheritedProofingFlow::STEPS.keys.first } - - describe 'before_actions' do - it 'includes before_actions from IdvSession' do - expect(subject).to have_actions(:before, :redirect_if_sp_context_needed) - end - - it 'includes before_actions from InheritedProofing404Concern' do - expect(subject).to have_actions(:before, :render_404_if_disabled) - end - - it 'includes before_actions from AllowlistedFlowStepConcern' do - expect(subject).to have_actions(:before, :flow_step!) - end - end - - describe '#new' do - let(:go_back_path) { '/path/to/return' } - - before do - allow(controller).to receive(:go_back_path).and_return(go_back_path) - end - - context 'when the inherited proofing feature flipper is turned off' do - before do - allow(IdentityConfig.store).to receive(:inherited_proofing_enabled).and_return(false) - stub_sign_in - end - - describe '#new' do - before do - get :new, params: { step: step } - end - - it_behaves_like 'an HTML 404 not found' - end - - describe '#update' do - before do - get :update, params: { step: step } - end - - it_behaves_like 'an HTML 404 not found' - end - - describe '#destroy' do - before do - get :destroy, params: { step: step } - end - - it_behaves_like 'an HTML 404 not found' - end - end - - context 'when the flow step is not in the allowed list' do - before do - stub_sign_in - end - - let(:step) { :not_found_step } - let(:expected_logger_warning) { "Flow step param \"#{step})\" was not whitelisted!" } - - describe '#new' do - before do - expect(Rails.logger).to receive(:warn).with(expected_logger_warning) - get :new, params: { step: step } - end - - it_behaves_like 'an HTML 404 not found' - end - - describe '#update' do - before do - expect(Rails.logger).to receive(:warn).with(expected_logger_warning) - get :update, params: { step: step } - end - - it_behaves_like 'an HTML 404 not found' - end - - describe '#destroy' do - before do - expect(Rails.logger).to receive(:warn).with(expected_logger_warning) - get :destroy, params: { step: step } - end - - it_behaves_like 'an HTML 404 not found' - end - end - - context 'when there is no session' do - it 'redirects to root' do - get :new - - expect(response).to redirect_to(root_url) - end - end - - context 'when there is a session' do - subject(:action) do - get :new, params: { step: step } - end - - before do - stub_sign_in - end - - it 'renders template' do - action - - expect(response).to render_template(:new) - end - - it 'stores go back path' do - action - - expect(controller.user_session[:idv][:go_back_path]).to eq(go_back_path) - end - - it 'tracks the event in analytics' do - stub_analytics - request.env['HTTP_REFERER'] = 'https://example.com/' - - expect(@analytics).to receive(:track_event).with( - 'IdV: cancellation visited', - request_came_from: 'users/sessions#new', - step: step.to_s, - proofing_components: nil, - analytics_id: nil, - ) - - action - end - end - end - - describe '#update' do - subject(:action) do - put :update, params: { step: step, cancel: 'true' } - end - - before do - stub_sign_in - end - - it 'redirects to idv_inherited_proofing_path' do - action - - expect(response).to redirect_to idv_inherited_proofing_url - end - - context 'when a go back path is stored in session' do - let(:go_back_path) { '/path/to/return' } - - before do - allow(controller).to receive(:user_session).and_return( - idv: { go_back_path: go_back_path }, - ) - end - - it 'redirects to go back path' do - action - - expect(response).to redirect_to go_back_path - end - end - - it 'tracks the event in analytics' do - stub_analytics - request.env['HTTP_REFERER'] = 'https://example.com/' - - expect(@analytics).to receive(:track_event).with( - 'IdV: cancellation go back', - request_came_from: 'users/sessions#new', - step: step.to_s, - proofing_components: nil, - analytics_id: nil, - ) - - action - end - end - - describe '#destroy' do - subject(:action) do - delete :destroy, params: { step: step } - end - - context 'when there is no session' do - it 'redirects to root' do - action - - expect(response).to redirect_to(root_url) - end - end - - context 'when there is a session' do - let(:user) { create(:user) } - - before do - stub_sign_in user - allow(controller).to receive(:user_session). - and_return(idv: { go_back_path: '/path/to/return' }) - end - - it 'destroys session' do - expect(controller).to receive(:cancel_session).once - - action - end - - it 'renders a json response with the redirect path set to account_path' do - action - - parsed_body = JSON.parse(response.body, symbolize_names: true) - expect(response).not_to render_template(:destroy) - expect(parsed_body).to eq({ redirect_url: account_path }) - end - - it 'tracks the event in analytics' do - stub_analytics - request.env['HTTP_REFERER'] = 'https://example.com/' - - expect(@analytics).to receive(:track_event).with( - 'IdV: cancellation confirmed', - request_came_from: 'users/sessions#new', - step: step.to_s, - proofing_components: nil, - analytics_id: nil, - ) - - action - end - end - end -end diff --git a/spec/controllers/idv/inherited_proofing_controller_spec.rb b/spec/controllers/idv/inherited_proofing_controller_spec.rb deleted file mode 100644 index 2fc7541ff39..00000000000 --- a/spec/controllers/idv/inherited_proofing_controller_spec.rb +++ /dev/null @@ -1,83 +0,0 @@ -require 'rails_helper' - -shared_examples 'the flow steps work correctly' do - describe '#index' do - it 'redirects to the first step' do - get :index - - expect(response).to redirect_to idv_inherited_proofing_step_url(step: :get_started) - end - - context 'when the inherited proofing feature flag is disabled' do - it 'returns 404 not found' do - allow(IdentityConfig.store).to receive(:inherited_proofing_enabled).and_return(false) - - get :index - - expect(response).to have_http_status(:not_found) - end - end - end - - describe '#show' do - it 'renders the correct template' do - expect(subject).to receive(:render).with( - template: 'layouts/flow_step', - locals: hash_including( - :flow_session, - flow_namespace: 'idv', - step_template: 'idv/inherited_proofing/get_started', - step_indicator: hash_including( - :steps, - current_step: :getting_started, - ), - ), - ).and_call_original - - get :show, params: { step: 'get_started' } - end - - it 'redirects to the configured next step' do - mock_next_step(:some_next_step) - get :show, params: { step: 'getting_started' } - - expect(response).to redirect_to idv_inherited_proofing_step_url(:some_next_step) - end - - it 'redirects to the first step if a non-existent step is given' do - get :show, params: { step: 'non_existent_step' } - - expect(response).to redirect_to idv_inherited_proofing_step_url(step: :get_started) - end - end -end - -def mock_next_step(step) - allow_any_instance_of(Idv::Flows::InheritedProofingFlow).to receive(:next_step).and_return(step) -end - -describe Idv::InheritedProofingController do - let(:sp) { nil } - let(:user) { build(:user) } - - before do - allow(controller).to receive(:current_sp).and_return(sp) - stub_sign_in(user) - end - - context 'when VA inherited proofing mock is enabled' do - before do - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return(true) - end - - it_behaves_like 'the flow steps work correctly' - end - - context 'when VA inherited proofing mock is not enabled' do - before do - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return(false) - end - - it_behaves_like 'the flow steps work correctly' - end -end diff --git a/spec/controllers/idv/sessions_controller_spec.rb b/spec/controllers/idv/sessions_controller_spec.rb index faa34fca6b7..4b9bf2396e1 100644 --- a/spec/controllers/idv/sessions_controller_spec.rb +++ b/spec/controllers/idv/sessions_controller_spec.rb @@ -15,7 +15,6 @@ allow(subject).to receive(:idv_session).and_return(idv_session) controller.user_session['idv/doc_auth'] = flow_session controller.user_session['idv/in_person'] = flow_session - controller.user_session['idv/inherited_proofing'] = flow_session controller.user_session[:decrypted_pii] = pii end @@ -37,10 +36,6 @@ expect(controller.user_session['idv/in_person']).to be_blank end - it 'clears the idv/inherited_proofing session' do - expect(controller.user_session['idv/inherited_proofing']).to be_blank - end - it 'clears the decrypted_pii session' do expect(controller.user_session[:decrypted_pii]).to be_blank end diff --git a/spec/controllers/idv_controller_spec.rb b/spec/controllers/idv_controller_spec.rb index 8775f2e6003..a8de1503938 100644 --- a/spec/controllers/idv_controller_spec.rb +++ b/spec/controllers/idv_controller_spec.rb @@ -70,13 +70,6 @@ expect(response).to redirect_to idv_doc_auth_path end - it 'redirects to inherited proofing with a VA inherited proofing session' do - allow(controller).to receive(:va_inherited_proofing?).and_return(true) - - get :index - expect(response).to redirect_to idv_inherited_proofing_path - end - context 'no SP context' do let(:user) { build(:user, password: ControllerHelper::VALID_PASSWORD) } diff --git a/spec/controllers/openid_connect/authorization_controller_spec.rb b/spec/controllers/openid_connect/authorization_controller_spec.rb index 169aa997467..d0156405b7d 100644 --- a/spec/controllers/openid_connect/authorization_controller_spec.rb +++ b/spec/controllers/openid_connect/authorization_controller_spec.rb @@ -421,28 +421,6 @@ end end - context 'with an inherited_proofing_auth code' do - before do - params[inherited_proofing_auth_key] = inherited_proofing_auth_value - action - end - - let(:inherited_proofing_auth_key) { 'inherited_proofing_auth' } - let(:inherited_proofing_auth_value) { SecureRandom.hex } - let(:decorated_session) { controller.view_context.decorated_session } - - it 'persists the inherited_proofing_auth value' do - expect(decorated_session.request_url_params[inherited_proofing_auth_key]).to \ - eq inherited_proofing_auth_value - end - - it 'redirects to SP landing page with the request_id in the params' do - sp_request_id = ServiceProviderRequestProxy.last.uuid - - expect(response).to redirect_to new_user_session_url(request_id: sp_request_id) - end - end - it 'redirects to SP landing page with the request_id in the params' do action sp_request_id = ServiceProviderRequestProxy.last.uuid diff --git a/spec/features/idv/inherited_proofing/agreement_step_spec.rb b/spec/features/idv/inherited_proofing/agreement_step_spec.rb deleted file mode 100644 index 47e05fb191d..00000000000 --- a/spec/features/idv/inherited_proofing/agreement_step_spec.rb +++ /dev/null @@ -1,78 +0,0 @@ -require 'rails_helper' - -feature 'inherited proofing agreement' do - include InheritedProofingHelper - - before do - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return true - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:va_inherited_proofing?).and_return true - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:va_inherited_proofing_auth_code).and_return auth_code - end - - let(:auth_code) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - - def expect_ip_verify_info_step - expect(page).to have_current_path(idv_ip_verify_info_step) - end - - def expect_inherited_proofing_first_step - expect(page).to have_current_path(idv_inherited_proofing_agreement_step) - end - - context 'when JS is enabled', :js do - before do - sign_in_and_2fa_user - complete_inherited_proofing_steps_before_agreement_step - end - - it 'shows an inline error if the user clicks continue without giving consent' do - click_continue - expect_inherited_proofing_first_step - expect(page).to have_content(t('forms.validation.required_checkbox')) - end - - it 'allows the user to continue after checking the checkbox' do - check t('inherited_proofing.instructions.consent', app_name: APP_NAME) - click_continue - - expect_ip_verify_info_step - end - - context 'when clicking on the Cancel link' do - it 'redirects to the Cancellation UI' do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :agreement)) - end - end - end - - context 'when JS is disabled' do - before do - sign_in_and_2fa_user - complete_inherited_proofing_steps_before_agreement_step - end - - it 'shows the notice if the user clicks continue without giving consent' do - click_continue - - expect_inherited_proofing_first_step - expect(page).to have_content(t('errors.doc_auth.consent_form')) - end - - it 'allows the user to continue after checking the checkbox' do - check t('inherited_proofing.instructions.consent', app_name: APP_NAME) - click_continue - - expect_ip_verify_info_step - end - - context 'when clicking on the Cancel link' do - it 'redirects to the Cancellation UI' do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :agreement)) - end - end - end -end diff --git a/spec/features/idv/inherited_proofing/analytics_spec.rb b/spec/features/idv/inherited_proofing/analytics_spec.rb deleted file mode 100644 index 43462bb74e0..00000000000 --- a/spec/features/idv/inherited_proofing/analytics_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'rails_helper' - -feature 'Inherited Proofing Analytics Regression', js: true do - include InheritedProofingHelper - - let(:user) { user_with_2fa } - let(:fake_analytics) { FakeAnalytics.new } - let(:auth_code) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - # rubocop:disable Layout/LineLength - let(:happy_path_events) do - { - 'IdV: inherited proofing get started visited' => { flow_path: 'standard', step: 'get_started', step_count: 1, analytics_id: 'Inherited Proofing', irs_reproofing: false }, - 'IdV: inherited proofing get started submitted' => { success: true, errors: {}, flow_path: 'standard', step: 'get_started', step_count: 1, analytics_id: 'Inherited Proofing', irs_reproofing: false }, - 'IdV: inherited proofing agreement visited' => { flow_path: 'standard', step: 'agreement', step_count: 1, analytics_id: 'Inherited Proofing', irs_reproofing: false }, - 'IdV: inherited proofing agreement submitted' => { success: true, errors: {}, flow_path: 'standard', step: 'agreement', step_count: 1, analytics_id: 'Inherited Proofing', irs_reproofing: false }, - 'IdV: doc auth verify_wait visited' => { flow_path: 'standard', step: 'verify_wait', step_count: 1, analytics_id: 'Inherited Proofing', irs_reproofing: false }, - 'IdV: doc auth optional verify_wait submitted' => { success: true, errors: {}, step: 'verify_wait_step_show', analytics_id: 'Inherited Proofing' }, - 'IdV: doc auth verify visited' => { flow_path: 'standard', step: 'verify_info', step_count: 1, analytics_id: 'Inherited Proofing', irs_reproofing: false }, - 'IdV: doc auth verify submitted' => { success: true, errors: {}, flow_path: 'standard', step: 'verify_info', step_count: 1, analytics_id: 'Inherited Proofing', irs_reproofing: false }, - } - end - # rubocop:enable Layout/LineLength - - before do - allow_any_instance_of(ApplicationController).to receive(:analytics) do |controller| - fake_analytics.user = controller.analytics_user - fake_analytics - end - - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return true - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:va_inherited_proofing?).and_return true - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:va_inherited_proofing_auth_code).and_return auth_code - end - - context 'Happy path' do - before do - sign_in_and_2fa_user - complete_all_inherited_proofing_steps_to_handoff - end - - it 'records all of the events' do - happy_path_events.each do |event, attributes| - expect(fake_analytics).to have_logged_event(event, attributes) - end - end - end -end diff --git a/spec/features/idv/inherited_proofing/get_started_step_spec.rb b/spec/features/idv/inherited_proofing/get_started_step_spec.rb deleted file mode 100644 index 35222000f68..00000000000 --- a/spec/features/idv/inherited_proofing/get_started_step_spec.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'rails_helper' - -feature 'inherited proofing get started' do - include InheritedProofingHelper - - before do - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return true - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:va_inherited_proofing?).and_return true - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:va_inherited_proofing_auth_code).and_return auth_code - end - - let(:auth_code) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - - def expect_ip_get_started_step - expect(page).to have_current_path(idv_ip_get_started_step) - end - - def expect_inherited_proofing_get_started_step - expect(page).to have_current_path(idv_ip_get_started_step) - end - - context 'when JS is enabled', :js do - before do - sign_in_and_2fa_user - complete_inherited_proofing_steps_before_get_started_step - end - - context 'when clicking on the Cancel link' do - it 'redirects to the Cancellation UI' do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :get_started)) - end - end - end - - context 'when JS is disabled' do - before do - sign_in_and_2fa_user - complete_inherited_proofing_steps_before_get_started_step - end - - context 'when clicking on the Cancel link' do - it 'redirects to the Cancellation UI' do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :get_started)) - end - end - end -end diff --git a/spec/features/idv/inherited_proofing/inherited_proofing_cancel_spec.rb b/spec/features/idv/inherited_proofing/inherited_proofing_cancel_spec.rb deleted file mode 100644 index cf594bd0c6c..00000000000 --- a/spec/features/idv/inherited_proofing/inherited_proofing_cancel_spec.rb +++ /dev/null @@ -1,151 +0,0 @@ -require 'rails_helper' - -feature 'inherited proofing cancel process', :js do - include InheritedProofingWithServiceProviderHelper - - before do - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return true - send_user_from_service_provider_to_login_gov_openid_connect user, inherited_proofing_auth - end - - let!(:user) { user_with_2fa } - let(:inherited_proofing_auth) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - - context 'from the "Get started verifying your identity" view, and clicking the "Cancel" link' do - before do - complete_steps_up_to_inherited_proofing_get_started_step user - end - - it 'should have current path equal to the Getting Started page' do - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) - end - - context 'when clicking the "Start Over" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :get_started)) - end - - it 'redirects the user back to the start of the Inherited Proofing process' do - click_button t('inherited_proofing.cancel.actions.start_over') - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) - end - end - - context 'when clicking the "No, keep going" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :get_started)) - end - - it 'redirects the user back to where the user left off in the Inherited Proofing process' do - click_button t('inherited_proofing.cancel.actions.keep_going') - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) - end - end - - context 'when clicking the "Exit Login.gov" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :get_started)) - end - - it 'redirects the user back to the service provider website' do - click_button t('idv.cancel.actions.exit', app_name: APP_NAME) - expect(page).to have_current_path(/\/auth\/result\?/) - end - end - end - - context 'from the "How verifying your identify works" view, and clicking the "Cancel" link' do - before do - complete_steps_up_to_inherited_proofing_how_verifying_step user - end - - it 'should have current path equal to the How Verifying (agreement step) page' do - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :agreement)) - end - - context 'when clicking the "Start Over" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :agreement)) - end - - it 'redirects the user back to the start of the Inherited Proofing process' do - click_button t('inherited_proofing.cancel.actions.start_over') - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) - end - end - - context 'when clicking the "No, keep going" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :agreement)) - end - - it 'redirects the user back to where the user left off in the Inherited Proofing process' do - click_button t('inherited_proofing.cancel.actions.keep_going') - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :agreement)) - end - end - - context 'when clicking the "Exit Login.gov" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :agreement)) - end - - it 'redirects the user back to the service provider website' do - click_button t('idv.cancel.actions.exit', app_name: APP_NAME) - expect(page).to have_current_path(/\/auth\/result\?/) - end - end - end - - context 'from the "Verify your information..." view, and clicking the "Cancel" link' do - before do - complete_steps_up_to_inherited_proofing_verify_your_info_step user - end - - it 'should have current path equal to the Verify your information (verify_info step) page' do - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :verify_info)) - end - - context 'when clicking the "Start Over" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :verify_info)) - end - - it 'redirects the user back to the start of the Inherited Proofing process' do - click_button t('inherited_proofing.cancel.actions.start_over') - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) - end - end - - context 'when clicking the "No, keep going" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :verify_info)) - end - - it 'redirects the user back to where the user left off in the Inherited Proofing process' do - click_button t('inherited_proofing.cancel.actions.keep_going') - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :verify_info)) - end - end - - context 'when clicking the "Exit Login.gov" button from the "Cancel" view' do - before do - click_link t('links.cancel') - expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :verify_info)) - end - - it 'redirects the user back to the service provider website' do - click_button t('idv.cancel.actions.exit', app_name: APP_NAME) - expect(page).to have_current_path(/\/auth\/result\?/) - end - end - end -end diff --git a/spec/features/idv/inherited_proofing/verify_info_step_spec.rb b/spec/features/idv/inherited_proofing/verify_info_step_spec.rb deleted file mode 100644 index fe1a14ea848..00000000000 --- a/spec/features/idv/inherited_proofing/verify_info_step_spec.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'rails_helper' - -feature 'inherited proofing verify info' do - include InheritedProofingHelper - include_context 'va_user_context' - - before do - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return true - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:va_inherited_proofing?).and_return true - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:va_inherited_proofing_auth_code).and_return auth_code - @decorated_session = instance_double(ServiceProviderSessionDecorator) - allow(@decorated_session).to receive(:sp_name).and_return(sp_name) - allow(@decorated_session).to receive(:sp_logo_url).and_return('') - allow_any_instance_of(Idv::InheritedProofingController).to \ - receive(:decorated_session).and_return(@decorated_session) - sign_in_and_2fa_user - complete_inherited_proofing_steps_before_verify_step - end - - let(:sp_name) { 'VA.gov' } - let(:auth_code) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - - describe 'page content' do - it 'renders the Continue button' do - expect(page).to have_button(t('inherited_proofing.buttons.continue')) - end - - it 'renders content' do - expect(page).to have_content(t('titles.idv.verify_info')) - expect(page).to have_link( - t( - 'inherited_proofing.troubleshooting.options.get_help', - sp_name: sp_name, - ), - ) - end - end - - describe 'user info' do - it "displays the user's personal information" do - expect(page).to have_text user_attributes[:first_name] - expect(page).to have_text user_attributes[:last_name] - expect(page).to have_text user_attributes[:birth_date] - end - - it "displays the user's address" do - expect(page).to have_text user_attributes[:address][:street] - expect(page).to have_text user_attributes[:address][:city] - expect(page).to have_text user_attributes[:address][:state] - expect(page).to have_text user_attributes[:address][:zip] - end - - it "obfuscates the user's ssn" do - expect(page).to have_text '1**-**-***9' - end - - it "can display the user's ssn when selected" do - check 'Show Social Security number' - expect(page).to have_text '123-45-6789' - end - end -end diff --git a/spec/features/idv/inherited_proofing/verify_wait_step_spec.rb b/spec/features/idv/inherited_proofing/verify_wait_step_spec.rb deleted file mode 100644 index 3c17b33d889..00000000000 --- a/spec/features/idv/inherited_proofing/verify_wait_step_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require 'rails_helper' - -feature 'inherited proofing verify wait', :js do - include InheritedProofingWithServiceProviderHelper - - before do - allow_any_instance_of(ApplicationController).to receive(:analytics).and_return(fake_analytics) - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return(true) - send_user_from_service_provider_to_login_gov_openid_connect(user, inherited_proofing_auth) - end - - let!(:user) { user_with_2fa } - let(:inherited_proofing_auth) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - let(:fake_analytics) { FakeAnalytics.new } - - context 'when on the "How verifying your identify works" page, ' \ - 'and the user clicks the "Continue" button' do - before do - complete_steps_up_to_inherited_proofing_we_are_retrieving_step user - end - - context 'when there are no service-related errors' do - it 'displays the "Verify your information" page' do - expect(page).to have_current_path( - idv_inherited_proofing_step_path(step: :verify_info), - ) - end - end - - context 'when there are service-related errors on the first attempt' do - let(:inherited_proofing_auth) { 'invalid-auth-code' } - - it 'displays the warning page and allows retries' do - expect(page).to have_current_path( - idv_inherited_proofing_errors_no_information_path(flow: :inherited_proofing), - ) - expect(page).to have_selector(:link_or_button, t('inherited_proofing.buttons.try_again')) - end - end - - context 'when there are service-related errors on the second attempt' do - let(:inherited_proofing_auth) { 'invalid-auth-code' } - - it 'redirects to the error page, prohibits retries and logs the event' do - click_button t('inherited_proofing.buttons.try_again') - expect(page).to have_current_path( - idv_inherited_proofing_errors_failure_url(flow: :inherited_proofing), - ) - expect(fake_analytics).to have_logged_event( - 'Throttler Rate Limit Triggered', - throttle_type: :inherited_proofing, - step_name: Idv::Actions::InheritedProofing::RedoRetrieveUserInfoAction.name, - ) - end - end - end - - context 'when the async state is missing during polling' do - before do - allow_any_instance_of(ProofingSessionAsyncResult).to receive(:missing?).and_return(true) - complete_steps_up_to_inherited_proofing_we_are_retrieving_step user - end - - it 'redirects back to the agreement step and logs the event' do - expect(page).to have_current_path( - idv_inherited_proofing_step_path(step: :agreement), - ) - expect(fake_analytics).to have_logged_event( - 'Proofing Resolution Result Missing', - ) - end - end -end diff --git a/spec/features/services/idv/inherited_proofing/va/mocks/service_spec.rb b/spec/features/services/idv/inherited_proofing/va/mocks/service_spec.rb deleted file mode 100644 index 88d8c7d429f..00000000000 --- a/spec/features/services/idv/inherited_proofing/va/mocks/service_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'rails_helper' - -RSpec.describe 'Inherited Proofing VA API Proofer Service' do - subject(:form) { Idv::InheritedProofing::Va::Form.new(payload_hash: proofer_results) } - - let(:proofer_results) do - Idv::InheritedProofing::Va::Mocks::Service.new({ auth_code: auth_code }).execute - end - let(:auth_code) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - - context 'when used with the VA Inherited Proofing Response Form' do - it 'works as expected' do - expect(form.submit.success?).to eq true - end - end -end diff --git a/spec/forms/idv/inherited_proofing/base_form_spec.rb b/spec/forms/idv/inherited_proofing/base_form_spec.rb deleted file mode 100644 index 871142de3eb..00000000000 --- a/spec/forms/idv/inherited_proofing/base_form_spec.rb +++ /dev/null @@ -1,182 +0,0 @@ -require 'rails_helper' - -RSpec.describe Idv::InheritedProofing::BaseForm do - subject { form_object } - - let(:form_class) do - Class.new(Idv::InheritedProofing::BaseForm) do - class << self - def required_fields; [] end - - def optional_fields; [] end - end - - def user_pii; {} end - end - end - - let(:form_object) do - form_class.new(payload_hash: payload_hash) - end - - let(:payload_hash) do - { - first_name: 'Henry', - last_name: 'Ford', - phone: '12222222222', - birth_date: '2000-01-01', - ssn: '111223333', - address: { - street: '1234 Model Street', - street2: 'Suite A', - city: 'Detroit', - state: 'MI', - country: 'United States', - zip: '12345', - }, - } - end - - describe '#initialize' do - subject { form_class } - - context 'when .user_pii is not overridden' do - subject do - Class.new(Idv::InheritedProofing::BaseForm) do - class << self - def required_fields; [] end - - def optional_fields; [] end - end - end - end - - it 'raises an error' do - expected_error = 'Override this method and return a user PII Hash' - expect { subject.new(payload_hash: payload_hash).user_pii }.to raise_error(expected_error) - end - end - end - - describe 'class methods' do - describe '.model_name' do - it 'returns the right model name' do - expect(described_class.model_name).to eq 'IdvInheritedProofingBaseForm' - end - end - end - - describe '#initialize' do - context 'when passing an invalid payload hash' do - context 'when not a Hash' do - let(:payload_hash) { :x } - - it 'raises an error' do - expect { subject }.to raise_error 'payload_hash is not a Hash' - end - end - - context 'when nil?' do - let(:payload_hash) { nil } - - it_behaves_like 'the hash is blank?' - end - - context 'when empty?' do - let(:payload_hash) { {} } - - it_behaves_like 'the hash is blank?' - end - end - - context 'when passing a valid payload hash' do - it 'raises no errors' do - expect { subject }.to_not raise_error - end - end - end - - describe '#validate' do - subject do - Class.new(Idv::InheritedProofing::BaseForm) do - class << self - def required_fields; %i[required] end - - def optional_fields; %i[optional] end - end - - def user_pii; {} end - end.new(payload_hash: payload_hash) - end - - let(:payload_hash) do - { - required: 'Required', - optional: 'Optional', - } - end - - context 'with valid payload data' do - it 'returns true' do - expect(subject.validate).to eq true - end - end - - context 'with invalid payload data' do - context 'when the payload has unrecognized fields' do - let(:payload_hash) do - { - xrequired: 'xRequired', - xoptional: 'xOptional', - } - end - - let(:expected_error_messages) do - [ - # Required field presence - 'Required field is missing', - 'Optional field is missing', - ] - end - - it 'returns true' do - expect(subject.validate).to eq true - end - end - - context 'when the payload has missing required field data' do - let(:payload_hash) do - { - required: nil, - optional: '', - } - end - - it 'returns true' do - expect(subject.validate).to eq true - end - - it 'returns no errors because no data validations take place by default' do - subject.validate - expect(subject.errors.full_messages).to eq [] - end - end - end - end - - describe '#submit' do - it 'returns a FormResponse object' do - expect(subject.submit).to be_kind_of FormResponse - end - - describe 'before returning' do - after do - subject.submit - end - - it 'calls #valid?' do - expect(subject).to receive(:valid?).once - end - end - end -end diff --git a/spec/forms/idv/inherited_proofing/va/form_spec.rb b/spec/forms/idv/inherited_proofing/va/form_spec.rb deleted file mode 100644 index ad734ab37c1..00000000000 --- a/spec/forms/idv/inherited_proofing/va/form_spec.rb +++ /dev/null @@ -1,317 +0,0 @@ -require 'rails_helper' - -RSpec.describe Idv::InheritedProofing::Va::Form do - subject(:form) { described_class.new payload_hash: payload_hash } - - let(:required_fields) { %i[first_name last_name birth_date ssn address_street address_zip] } - let(:optional_fields) do - %i[phone address_street2 address_city address_state address_country service_error] - end - - let(:payload_hash) do - { - first_name: 'Henry', - last_name: 'Ford', - phone: '12222222222', - birth_date: '2000-01-01', - ssn: '111223333', - address: { - street: '1234 Model Street', - street2: 'Suite A', - city: 'Detroit', - state: 'MI', - country: 'United States', - zip: '12345', - }, - } - end - - describe 'constants' do - describe 'FIELDS' do - it 'returns all the fields' do - expect(described_class::FIELDS).to match_array required_fields + optional_fields - end - end - - describe 'REQUIRED_FIELDS' do - it 'returns the required fields' do - expect(described_class::REQUIRED_FIELDS).to match_array required_fields - end - end - - describe 'OPTIONAL_FIELDS' do - it 'returns the optional fields' do - expect(described_class::OPTIONAL_FIELDS).to match_array optional_fields - end - end - end - - describe 'class methods' do - describe '.model_name' do - it 'returns the right model name' do - expect(described_class.model_name).to eq 'IdvInheritedProofingVaForm' - end - end - end - - describe '#initialize' do - context 'when passing an invalid payload hash' do - context 'when not a Hash' do - let(:payload_hash) { :x } - - it 'raises an error' do - expect { form }.to raise_error 'payload_hash is not a Hash' - end - end - - context 'when nil?' do - let(:payload_hash) { nil } - - it_behaves_like 'the hash is blank?' - end - - context 'when empty?' do - let(:payload_hash) { {} } - - it_behaves_like 'the hash is blank?' - end - end - - context 'when passing a valid payload hash' do - it 'raises no errors' do - expect { form }.to_not raise_error - end - end - end - - describe '#validate' do - context 'with valid payload data' do - it 'returns true' do - expect(form.validate).to be true - end - end - - context 'with invalid payload data' do - context 'when the payload has missing fields' do - let(:payload_hash) do - { - xfirst_name: 'Henry', - xlast_name: 'Ford', - xphone: '12222222222', - xbirth_date: '2000-01-01', - xssn: '111223333', - xaddress: { - xstreet: '1234 Model Street', - xstreet2: 'Suite A', - xcity: 'Detroit', - xstate: 'MI', - xcountry: 'United States', - xzip: '12345', - }, - } - end - - let(:expected_error_messages) do - [ - 'First name Please fill in this field.', - 'Last name Please fill in this field.', - 'Birth date Please fill in this field.', - 'Ssn Please fill in this field.', - 'Address street Please fill in this field.', - 'Address zip Please fill in this field.', - ] - end - - it 'returns false' do - expect(form.validate).to be false - end - - it 'adds the correct error messages for missing fields' do - subject.validate - expect(form.errors.full_messages).to match_array expected_error_messages - end - end - - context 'when the payload has missing required field data' do - let(:payload_hash) do - { - first_name: nil, - last_name: '', - phone: nil, - birth_date: '', - ssn: nil, - address: { - street: '', - street2: nil, - city: '', - state: nil, - country: '', - zip: nil, - }, - } - end - - let(:expected_error_messages) do - [ - # Required field data presence - 'First name Please fill in this field.', - 'Last name Please fill in this field.', - 'Birth date Please fill in this field.', - 'Ssn Please fill in this field.', - 'Address street Please fill in this field.', - 'Address zip Please fill in this field.', - ] - end - - it 'returns false' do - expect(form.validate).to be false - end - - it 'adds the correct error messages for required fields that are missing data' do - subject.validate - expect(form.errors.full_messages).to match_array expected_error_messages - end - end - - context 'when the payload has missing optional field data' do - let(:payload_hash) do - { - first_name: 'x', - last_name: 'x', - phone: nil, - birth_date: '01/01/2022', - ssn: '123456789', - address: { - street: 'x', - street2: nil, - city: '', - state: nil, - country: '', - zip: '12345', - }, - } - end - - it 'returns true' do - expect(form.validate).to be true - end - end - - context 'when there is a service-related error' do - before do - subject.validate - end - - let(:payload_hash) { { service_error: 'service error' } } - - it 'returns false' do - expect(form.valid?).to be false - end - - it 'adds a user-friendly model error' do - expect(form.errors.full_messages).to \ - match_array ['Service provider communication was unsuccessful'] - end - end - end - end - - describe '#submit' do - context 'with an invalid payload' do - context 'when the payload has invalid field data' do - let(:payload_hash) do - { - first_name: nil, - last_name: '', - phone: nil, - birth_date: '', - ssn: nil, - address: { - street: '', - street2: nil, - city: '', - state: nil, - country: '', - zip: nil, - }, - } - end - - let(:expected_errors) do - { - # Required field data presence - first_name: ['Please fill in this field.'], - last_name: ['Please fill in this field.'], - birth_date: ['Please fill in this field.'], - ssn: ['Please fill in this field.'], - address_street: ['Please fill in this field.'], - address_zip: ['Please fill in this field.'], - } - end - - it 'returns a FormResponse indicating the correct errors and status' do - form_response = subject.submit - expect(form_response.success?).to be false - expect(form_response.errors).to match_array expected_errors - expect(form_response.extra).to eq({}) - end - end - end - - context 'with a valid payload' do - it 'returns a FormResponse indicating the no errors and successful status' do - form_response = subject.submit - expect(form_response.success?).to be true - expect(form_response.errors).to eq({}) - expect(form_response.extra).to eq({}) - end - end - - context 'when there is a service-related error' do - let(:payload_hash) { { service_error: 'service error' } } - - it 'adds the unfiltered error to the FormResponse :extra Hash' do - form_response = subject.submit - expect(form_response.success?).to be false - expect(form_response.errors).to \ - eq({ service_provider: ['communication was unsuccessful'] }) - expect(form_response.extra).to eq({ service_error: 'service error' }) - end - end - end - - describe '#user_pii' do - let(:expected_user_pii) do - { - first_name: subject.first_name, - last_name: subject.last_name, - dob: subject.birth_date, - ssn: subject.ssn, - phone: subject.phone, - address1: subject.address_street, - city: subject.address_city, - state: subject.address_state, - zipcode: subject.address_zip, - } - end - it 'returns the correct user pii' do - expect(form.user_pii).to eq expected_user_pii - end - end - - describe '#service_error?' do - context 'when there is a service-related error' do - let(:payload_hash) { { service_error: 'service error' } } - - it 'returns true' do - expect(form.service_error?).to be true - end - end - - context 'when there is not a service-related error' do - it 'returns false' do - expect(form.service_error?).to be false - end - end - end -end diff --git a/spec/jobs/inherited_proofing_job_spec.rb b/spec/jobs/inherited_proofing_job_spec.rb deleted file mode 100644 index 839d292cd33..00000000000 --- a/spec/jobs/inherited_proofing_job_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'rails_helper' - -RSpec.describe InheritedProofingJob, type: :job do - include Idv::InheritedProofing::ServiceProviderServices - include Idv::InheritedProofing::ServiceProviderForms - include_context 'va_api_context' - - let(:document_capture_session) { DocumentCaptureSession.new(result_id: SecureRandom.hex) } - let(:service_provider_data) { { auth_code: 'mocked-auth-code-for-testing' } } - let(:service_provider) { Idv::InheritedProofing::ServiceProviders::VA } - - before do - allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return true - allow_any_instance_of(Idv::InheritedProofing::ServiceProviderServices).to \ - receive(:inherited_proofing?).and_return true - end - - describe '#perform' do - it 'calls api for user data and stores in document capture session' do - document_capture_session.create_doc_auth_session - - InheritedProofingJob.perform_now( - service_provider, - service_provider_data, - document_capture_session.uuid, - ) - - result = document_capture_session.load_proofing_result[:result] - - expect(result).to be_present - expect(result).to include(last_name: 'Fakerson') - end - end -end diff --git a/spec/services/idv/inherited_proofing/service_provider_forms_spec.rb b/spec/services/idv/inherited_proofing/service_provider_forms_spec.rb deleted file mode 100644 index bbad02b360e..00000000000 --- a/spec/services/idv/inherited_proofing/service_provider_forms_spec.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'rails_helper' - -RSpec.describe Idv::InheritedProofing::ServiceProviderForms do - subject do - Class.new do - include Idv::InheritedProofing::ServiceProviderForms - end.new - end - - let(:service_provider) { :va } - let(:payload_hash) { Idv::InheritedProofing::Va::Mocks::Service::PAYLOAD_HASH } - - describe '#inherited_proofing_form_for' do - context 'when there is a va inherited proofing request' do - it 'returns the correct form' do - expect( - subject.inherited_proofing_form_for( - service_provider, - payload_hash: payload_hash, - ), - ).to \ - be_kind_of Idv::InheritedProofing::Va::Form - end - end - - context 'when the inherited proofing request cannot be identified' do - let(:service_provider) { :unknown_service_provider } - - it 'raises an error' do - expect do - subject.inherited_proofing_form_for(service_provider, payload_hash: payload_hash) - end.to \ - raise_error 'Inherited proofing form could not be identified' - end - end - end -end diff --git a/spec/services/idv/inherited_proofing/service_provider_services_spec.rb b/spec/services/idv/inherited_proofing/service_provider_services_spec.rb deleted file mode 100644 index 76380bf2374..00000000000 --- a/spec/services/idv/inherited_proofing/service_provider_services_spec.rb +++ /dev/null @@ -1,101 +0,0 @@ -require 'rails_helper' - -RSpec.describe Idv::InheritedProofing::ServiceProviderServices do - subject do - Class.new do - include Idv::InheritedProofing::ServiceProviderServices - end.new - end - - let(:service_provider) { :va } - let(:service_provider_data) { { auth_code: auth_code } } - let(:auth_code) { Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE } - - describe '#inherited_proofing_service_class_for' do - context 'when va inherited proofing is disabled' do - before do - allow(IdentityConfig.store).to receive(:inherited_proofing_enabled).and_return(false) - end - - it 'raises an error' do - expect do - subject.inherited_proofing_service_class_for(service_provider) - end.to raise_error 'Inherited Proofing is not enabled' - end - end - - context 'when there is a va inherited proofing request' do - context 'when va mock proofing is turned on' do - before do - allow(IdentityConfig.store).to \ - receive(:va_inherited_proofing_mock_enabled).and_return(true) - end - - it 'returns the correct service provider service class' do - expect(subject.inherited_proofing_service_class_for(service_provider)).to \ - eq Idv::InheritedProofing::Va::Mocks::Service - end - end - - context 'when va mock proofing is turned off' do - before do - allow(IdentityConfig.store).to \ - receive(:va_inherited_proofing_mock_enabled).and_return(false) - end - - it 'returns the correct service provider service class' do - expect(subject.inherited_proofing_service_class_for(service_provider)).to \ - eq Idv::InheritedProofing::Va::Service - end - end - end - - context 'when the inherited proofing class cannot be identified' do - let(:service_provider) { :unknown_service_provider } - - it 'raises an error' do - expect do - subject.inherited_proofing_service_class_for(service_provider) - end.to raise_error 'Inherited proofing service class could not be identified' - end - end - end - - describe '#inherited_proofing_service_for' do - context 'when there is a va inherited proofing request' do - context 'when va mock proofing is turned on' do - before do - allow(IdentityConfig.store).to \ - receive(:va_inherited_proofing_mock_enabled).and_return(true) - end - - it 'returns the correct service provider service class' do - expect( - subject.inherited_proofing_service_for( - service_provider, - service_provider_data: service_provider_data, - ), - ).to \ - be_kind_of Idv::InheritedProofing::Va::Mocks::Service - end - end - - context 'when va mock proofing is turned off' do - before do - allow(IdentityConfig.store).to \ - receive(:va_inherited_proofing_mock_enabled).and_return(false) - end - - it 'returns the correct service provider service class' do - expect( - subject.inherited_proofing_service_for( - service_provider, - service_provider_data: service_provider_data, - ), - ).to \ - be_kind_of Idv::InheritedProofing::Va::Service - end - end - end - end -end diff --git a/spec/services/idv/inherited_proofing/va/mocks/service_spec.rb b/spec/services/idv/inherited_proofing/va/mocks/service_spec.rb deleted file mode 100644 index 865383e874b..00000000000 --- a/spec/services/idv/inherited_proofing/va/mocks/service_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'rails_helper' - -RSpec.describe Idv::InheritedProofing::Va::Mocks::Service do - subject { described_class.new({ auth_code: auth_code }) } - let(:auth_code) { described_class::VALID_AUTH_CODE } - - describe '#initialize' do - it 'sets #auth_code' do - expect(subject.auth_code).to eq auth_code - end - end - - describe '#execute' do - context 'when auth_code is valid' do - it 'returns a Hash' do - expect(subject.execute).to eq(described_class::PAYLOAD_HASH) - end - end - - context 'with auth code is invalid' do - let(:auth_code) { "invalid-#{described_class::VALID_AUTH_CODE}" } - - it 'returns an error' do - expect(subject.execute).to eq(described_class::ERROR_HASH) - end - end - end -end diff --git a/spec/services/idv/inherited_proofing/va/service_spec.rb b/spec/services/idv/inherited_proofing/va/service_spec.rb deleted file mode 100644 index 7a5dece157b..00000000000 --- a/spec/services/idv/inherited_proofing/va/service_spec.rb +++ /dev/null @@ -1,124 +0,0 @@ -require 'rails_helper' - -RSpec.shared_examples 'an invalid auth code error is raised' do - it 'raises an error' do - expect { subject.execute }.to raise_error 'The provided auth_code is blank?' - end -end - -RSpec.describe Idv::InheritedProofing::Va::Service do - include_context 'va_api_context' - include_context 'va_user_context' - - subject(:service) { described_class.new(auth_code: auth_code) } - - before do - allow(service).to receive(:private_key).and_return(private_key) - end - - it { respond_to :execute } - - it do - expect(service.send(:private_key)).to eq private_key - end - - describe '#execute' do - context 'when the auth code is valid' do - let(:auth_code) { 'mocked-auth-code-for-testing' } - - it 'makes an authenticated request' do - freeze_time do - stub = stub_request(:get, request_uri). - with(headers: request_headers). - to_return(status: 200, body: '{}', headers: {}) - - service.execute - - expect(stub).to have_been_requested.once - end - end - - it 'decrypts the response' do - freeze_time do - stub_request(:get, request_uri). - with(headers: request_headers). - to_return(status: 200, body: encrypted_user_attributes, headers: {}) - - expect(service.execute).to eq user_attributes - end - end - end - - context 'when the auth code is invalid' do - context 'when an empty? string' do - let(:auth_code) { '' } - - it_behaves_like 'an invalid auth code error is raised' - end - - context 'when an nil?' do - let(:auth_code) { nil } - - it_behaves_like 'an invalid auth code error is raised' - end - end - - context 'when a request error is raised' do - before do - allow(service).to receive(:request).and_raise('Boom!') - end - - it 'rescues and returns the error' do - expect(service.execute).to eq({ service_error: 'Boom!' }) - end - end - - context 'when a decryption error is raised' do - it 'rescues and returns the error' do - freeze_time do - stub_request(:get, request_uri). - with(headers: request_headers). - to_return(status: 200, body: 'xyz', headers: {}) - - expect(service.execute[:service_error]).to match(/unexpected token at 'xyz'/) - end - end - end - - context 'when a non-200 error is raised' do - it 'rescues and returns the error' do - freeze_time do - stub_request(:get, request_uri). - with(headers: request_headers). - to_return(status: 302, body: encrypted_user_attributes, headers: {}) - - expect(service.execute.to_s).to \ - match(/The service provider API returned an http status other than 200/) - end - end - - context 'when http status is unavailable (nil)' do - before do - allow_any_instance_of(Faraday::Response).to receive(:status).and_return(nil) - end - - let(:expected_error) do - { - service_error: 'The service provider API returned an http status other than 200: ' \ - 'unavailable (unavailable)', - } - end - - it 'rescues and returns the error' do - freeze_time do - stub_request(:get, request_uri). - with(headers: request_headers). - to_return(status: nil, body: encrypted_user_attributes, headers: {}) - - expect(service.execute).to eq expected_error - end - end - end - end - end -end diff --git a/spec/support/features/idv_helper.rb b/spec/support/features/idv_helper.rb index 13cf08e2199..2deaaf63487 100644 --- a/spec/support/features/idv_helper.rb +++ b/spec/support/features/idv_helper.rb @@ -152,30 +152,6 @@ def visit_idp_from_oidc_sp_with_ial2( ) end - def visit_idp_from_oidc_va_with_ial2( - client_id: sp_oidc_issuer, - state: SecureRandom.hex, - nonce: SecureRandom.hex, - verified_within: nil, - inherited_proofing_auth: Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE - ) - @state = state - @client_id = sp_oidc_issuer - @nonce = nonce - visit openid_connect_authorize_path( - client_id: client_id, - response_type: 'code', - acr_values: Saml::Idp::Constants::IAL2_AUTHN_CONTEXT_CLASSREF, - scope: 'openid email profile:name phone social_security_number', - redirect_uri: sp_oidc_redirect_uri, - state: state, - prompt: 'select_account', - nonce: nonce, - verified_within: verified_within, - inherited_proofing_auth: inherited_proofing_auth, - ) - end - def visit_idp_from_oidc_sp_with_loa3 visit openid_connect_authorize_path( client_id: sp_oidc_issuer, diff --git a/spec/support/features/inherited_proofing_helper.rb b/spec/support/features/inherited_proofing_helper.rb deleted file mode 100644 index 90e397d0ce6..00000000000 --- a/spec/support/features/inherited_proofing_helper.rb +++ /dev/null @@ -1,62 +0,0 @@ -require_relative 'idv_step_helper' -require_relative 'doc_auth_helper' - -module InheritedProofingHelper - include IdvStepHelper - include DocAuthHelper - - # Steps - def idv_ip_get_started_step - idv_inherited_proofing_step_path(step: :get_started) - end - - def idv_inherited_proofing_agreement_step - idv_inherited_proofing_step_path(step: :agreement) - end - - def idv_ip_verify_info_step - idv_inherited_proofing_step_path(step: :verify_info) - end - - # Traverse Steps - - # create account - def complete_inherited_proofing_steps_before_get_started_step(expect_accessible: false) - visit idv_ip_get_started_step unless current_path == idv_ip_get_started_step - expect(page).to be_axe_clean.according_to :section508, :"best-practice" if expect_accessible - end - - # get started - def complete_get_started_step - click_on t('inherited_proofing.buttons.continue') - end - - def complete_inherited_proofing_steps_before_agreement_step(expect_accessible: false) - complete_inherited_proofing_steps_before_get_started_step(expect_accessible: expect_accessible) - complete_get_started_step - expect(page).to be_axe_clean.according_to :section508, :"best-practice" if expect_accessible - end - - # get started > agreement > verify_wait > please verify - def complete_agreement_step - find('label', text: t('inherited_proofing.instructions.consent', app_name: APP_NAME)).click - click_on t('inherited_proofing.buttons.continue') - end - - def complete_inherited_proofing_steps_before_verify_step(expect_accessible: false) - complete_inherited_proofing_steps_before_agreement_step(expect_accessible: expect_accessible) - complete_agreement_step - expect(page).to be_axe_clean.according_to :section508, :"best-practice" if expect_accessible - end - - def complete_inherited_proofing_verify_step - click_on t('inherited_proofing.buttons.continue') - end - - # get_started > agreement > verify_wait > please verify > complete - def complete_all_inherited_proofing_steps_to_handoff(expect_accessible: false) - complete_inherited_proofing_steps_before_verify_step(expect_accessible: expect_accessible) - complete_inherited_proofing_verify_step - expect(page).to be_axe_clean.according_to :section508, :"best-practice" if expect_accessible - end -end diff --git a/spec/support/features/inherited_proofing_with_service_provider_helper.rb b/spec/support/features/inherited_proofing_with_service_provider_helper.rb deleted file mode 100644 index f899b293d2c..00000000000 --- a/spec/support/features/inherited_proofing_with_service_provider_helper.rb +++ /dev/null @@ -1,55 +0,0 @@ -require_relative 'idv_step_helper' -require_relative 'doc_auth_helper' - -module InheritedProofingWithServiceProviderHelper - include IdvStepHelper - include DocAuthHelper - - # Simulates a user (in this case, a VA inherited proofing-authorized user) - # coming over to login.gov from a service provider, and hitting the - # OpenidConnect::AuthorizationController#index action. - def send_user_from_service_provider_to_login_gov_openid_connect(user, inherited_proofing_auth) - expect(user).to_not be_nil - # NOTE: VA user. - visit_idp_from_oidc_va_with_ial2 inherited_proofing_auth: inherited_proofing_auth - end - - def complete_steps_up_to_inherited_proofing_get_started_step(user, expect_accessible: false) - unless current_path == idv_inherited_proofing_step_path(step: :get_started) - complete_idv_steps_before_phone_step(user) - click_link t('links.cancel') - click_button t('idv.cancel.actions.start_over') - expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) - end - expect(page).to be_axe_clean.according_to :section508, :"best-practice" if expect_accessible - end - - def complete_steps_up_to_inherited_proofing_how_verifying_step(user, expect_accessible: false) - complete_steps_up_to_inherited_proofing_get_started_step user, - expect_accessible: expect_accessible - unless current_path == idv_inherited_proofing_step_path(step: :agreement) - click_on t('inherited_proofing.buttons.continue') - end - end - - def complete_steps_up_to_inherited_proofing_we_are_retrieving_step(user, - expect_accessible: false) - complete_steps_up_to_inherited_proofing_how_verifying_step( - user, - expect_accessible: expect_accessible, - ) - unless current_path == idv_inherited_proofing_step_path(step: :verify_wait) - check t('inherited_proofing.instructions.consent', app_name: APP_NAME), - allow_label_click: true - click_on t('inherited_proofing.buttons.continue') - end - end - - def complete_steps_up_to_inherited_proofing_verify_your_info_step(user, - expect_accessible: false) - complete_steps_up_to_inherited_proofing_we_are_retrieving_step( - user, - expect_accessible: expect_accessible, - ) - end -end diff --git a/spec/support/shared_contexts/inherited_proofing/encrypted_user_attributes.json b/spec/support/shared_contexts/inherited_proofing/encrypted_user_attributes.json deleted file mode 100644 index af29a512873..00000000000 --- a/spec/support/shared_contexts/inherited_proofing/encrypted_user_attributes.json +++ /dev/null @@ -1 +0,0 @@ -{"data":"eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.IL_uTLpwR3ZoDQKuRY_clxK1AmrEnf3rCREIj8XGQ-iA7NxCiYfZ2CxuXFOTIzFbKXjcNYT1F56bCUuPwSmHNt88AGumB3RcskR6POfBu8EcjK2CI6myycGuQwm_1Dp9Vi55TQpSFRy5Bld7IR0gbk4ju0qTVSeH59-AyBGr0w07vojdHcPe-SDWEC1pG0_4iyVg0x2wOFAh6kIjMJ04sJYB4e7uW8hEI7lSwDLpiW-8KsjGhwCVIkUGPw7XKtLiWo1U_nXSragpG-E6XRx0Hn3YckSwEAMTATeZZPJr0TAAMO_jtukL0e7_ApwsCI-sEdI035_4befLlDnuz1QFJg.oLmsRlZKFlL_3Th4.YumiTPq6y8jyCpVwuSpqsd8iWQ_AqEN81v8pV9lB2dPb6po03aj05K361IWmWfB3gXir--L3nPpUdlFFkxF1X12QVkpfmH03kj01Zoaq9hZcQvY7d4QoOkMNkdONNFZ3_sp-4-11m5ki2TpD1AidkLe7AIaSvBvhYOq0TC-0veLwRvp5234-XyDq9o5hLogzUa3G1BxcZO_TxpS5IhV4CzJ2a-o_ymSgUULDjrAty23XMiqXxTMFbVCpMDrvgGTX2TYOYx0PngjySlir6Zf4WjKhvFBOd34hvx2MUYTEGPw.UcPA0owzraT7ckc1cRDzeg"} diff --git a/spec/support/shared_contexts/inherited_proofing/va_api_context.rb b/spec/support/shared_contexts/inherited_proofing/va_api_context.rb deleted file mode 100644 index bec50c6a17c..00000000000 --- a/spec/support/shared_contexts/inherited_proofing/va_api_context.rb +++ /dev/null @@ -1,15 +0,0 @@ -RSpec.shared_context 'va_api_context' do - # Sample mocked API call: - # stub_request(:get, request_uri). - # with(headers: request_headers). - # to_return(status: 200, body: '{}', headers: {}) - - let(:auth_code) { 'mocked-auth-code-for-testing' } - let(:private_key) { private_key_from_store_or(file_name: 'empty.key') } - let(:payload) { { inherited_proofing_auth: auth_code, exp: 1.day.from_now.to_i } } - let(:jwt_token) { JWT.encode(payload, private_key, 'RS256') } - let(:request_uri) do - "#{Idv::InheritedProofing::Va::Service::BASE_URI}/inherited_proofing/user_attributes" - end - let(:request_headers) { { Authorization: "Bearer #{jwt_token}" } } -end diff --git a/spec/support/shared_contexts/inherited_proofing/va_user_context.rb b/spec/support/shared_contexts/inherited_proofing/va_user_context.rb deleted file mode 100644 index 81ac0b82545..00000000000 --- a/spec/support/shared_contexts/inherited_proofing/va_user_context.rb +++ /dev/null @@ -1,18 +0,0 @@ -RSpec.shared_context 'va_user_context' do - # As given to us from VA - let(:user_attributes) do - { first_name: 'Fakey', - last_name: 'Fakerson', - address: { street: '123 Fake St', - street2: 'Apt 235', - city: 'Faketown', - state: 'WA', - country: nil, - zip: '98037' }, - phone: '2063119187', - birth_date: '2022-1-31', - ssn: '123456789' } - end - # Encrypted with AppArtifacts.store.oidc_private_key for testing - let(:encrypted_user_attributes) { File.read("#{__dir__}/encrypted_user_attributes.json") } -end diff --git a/spec/views/idv/inherited_proofing/agreement.html.erb_spec.rb b/spec/views/idv/inherited_proofing/agreement.html.erb_spec.rb deleted file mode 100644 index d8f6ac9c379..00000000000 --- a/spec/views/idv/inherited_proofing/agreement.html.erb_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'rails_helper' - -describe 'idv/inherited_proofing/agreement.html.erb' do - include Devise::Test::ControllerHelpers - - let(:flow_session) { {} } - let(:sp_name) { 'test' } - - before do - allow(view).to receive(:decorated_session).and_return(@decorated_session) - allow(view).to receive(:flow_session).and_return(flow_session) - allow(view).to receive(:url_for).and_return('https://www.example.com/') - allow(view).to receive(:user_signing_up?).and_return(true) - end - - it 'renders the Continue button' do - render template: 'idv/inherited_proofing/agreement' - - expect(rendered).to have_button(t('inherited_proofing.buttons.continue')) - end - - it 'renders the Cancel link' do - render template: 'idv/inherited_proofing/agreement' - - expect(rendered).to have_link(t('links.cancel_account_creation')) - end - - context 'with or without service provider' do - it 'renders content' do - render template: 'idv/inherited_proofing/agreement' - - expect(rendered).to have_content(t('inherited_proofing.info.lets_go')) - expect(rendered).to have_content( - t('inherited_proofing.headings.verify_identity'), - ) - expect(rendered).to have_content(t('inherited_proofing.info.verify_identity')) - expect(rendered).to have_content( - t('inherited_proofing.headings.secure_account'), - ) - expect(rendered).to have_content( - t('inherited_proofing.info.secure_account', sp_name: sp_name), - ) - end - end -end diff --git a/spec/views/idv/inherited_proofing/get_started.html.erb_spec.rb b/spec/views/idv/inherited_proofing/get_started.html.erb_spec.rb deleted file mode 100644 index 76d27eef061..00000000000 --- a/spec/views/idv/inherited_proofing/get_started.html.erb_spec.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'rails_helper' - -describe 'idv/inherited_proofing/get_started.html.erb' do - include Devise::Test::ControllerHelpers - - let(:flow_session) { {} } - let(:sp_name) { 'test' } - - before do - @decorated_session = instance_double(ServiceProviderSessionDecorator) - allow(@decorated_session).to receive(:sp_name).and_return(sp_name) - allow(view).to receive(:decorated_session).and_return(@decorated_session) - allow(view).to receive(:flow_session).and_return(flow_session) - allow(view).to receive(:url_for).and_return('https://www.example.com/') - allow(view).to receive(:user_fully_authenticated?).and_return(true) - allow(view).to receive(:user_signing_up?).and_return(true) - - @presenter = instance_double(Idv::InheritedProofing::InheritedProofingPresenter) - allow(@presenter).to receive(:learn_more_phone_or_mail_url).and_return('https://www.va.gov/resources/managing-your-vagov-profile/') - allow(@presenter).to receive(:get_help_url).and_return('https://www.va.gov/resources/managing-your-vagov-profile/') - allow(view).to receive(:presenter).and_return(@presenter) - end - - it 'renders the Continue button' do - render template: 'idv/inherited_proofing/get_started' - - expect(rendered).to have_button(t('inherited_proofing.buttons.continue')) - end - - it 'renders the Cancel link' do - render template: 'idv/inherited_proofing/get_started' - - expect(rendered).to have_link(t('links.cancel_account_creation')) - end - - context 'with or without service provider' do - it 'renders troubleshooting options' do - render template: 'idv/inherited_proofing/get_started' - - expect(rendered).to have_link( - t('inherited_proofing.troubleshooting.options.learn_more_phone_or_mail'), - ) - expect(rendered).not_to have_link(nil, href: idv_inherited_proofing_return_to_sp_path) - expect(rendered).to have_link( - t( - 'inherited_proofing.troubleshooting.options.get_help', - sp_name: sp_name, - ), - ) - expect(rendered).to have_link( - t('inherited_proofing.troubleshooting.options.learn_more_phone_or_mail'), - ) - end - end -end diff --git a/spec/views/idv/inherited_proofing/retrieval.html.erb_spec.rb b/spec/views/idv/inherited_proofing/retrieval.html.erb_spec.rb deleted file mode 100644 index 7db2ed40eb1..00000000000 --- a/spec/views/idv/inherited_proofing/retrieval.html.erb_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'rails_helper' - -describe 'idv/inherited_proofing/verify_wait.html.erb' do - include Devise::Test::ControllerHelpers - - it 'renders' do - render template: 'idv/inherited_proofing/verify_wait' - - # Appropriate header - expect(rendered).to have_text(t('inherited_proofing.headings.retrieval')) - - # Spinner - expect(rendered).to have_css("img[src*='shield-spinner']") - - # Appropriate text - expect(rendered).to have_text(t('inherited_proofing.info.retrieval_time')) - expect(rendered).to have_text(t('inherited_proofing.info.retrieval_thanks')) - end -end From 86de0b5a07a4c6a816af39031ada45a37376b5a5 Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Fri, 3 Mar 2023 11:26:45 -0500 Subject: [PATCH 2/3] remove va test script --- scripts/va-api-test.rb | 50 ------------------------------------------ 1 file changed, 50 deletions(-) delete mode 100755 scripts/va-api-test.rb diff --git a/scripts/va-api-test.rb b/scripts/va-api-test.rb deleted file mode 100755 index f99e9b6e97d..00000000000 --- a/scripts/va-api-test.rb +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env ruby - -require 'jwt' -require 'jwe' -require 'net/http' - -# Script to test connection to VA API, can be removed once we create code inside the IDV flow -class VaApiTest - def run - uri = URI 'https://staging-api.va.gov/inherited_proofing/user_attributes' - headers = { Authorization: "Bearer #{jwt_token}" } - - response = Net::HTTP.get_response(uri, headers) - decrypt_payload(response) - end - - private - - def jwt_token - payload = { inherited_proofing_auth: 'mocked-auth-code-for-testing', exp: 1.day.from_now.to_i } - JWT.encode(payload, private_key, 'RS256') - end - - def decrypt_payload(response) - payload = JSON.parse(response.body)['data'] - JWE.decrypt(payload, private_key) if payload - end - - def private_key - return AppArtifacts.store.oidc_private_key if private_key_store? - - OpenSSL::PKey::RSA.new(File.read(private_key_file)) - end - - # Returns true if a private key store should be used - # (as opposed to the private key file). - def private_key_store? - Identity::Hostdata.in_datacenter? || !private_key_file? - end - - def private_key_file? - File.exist?(private_key_file) - end - - def private_key_file - @private_key_file ||= 'tmp/va_ip.key' - end -end - -puts(VaApiTest.new.run || 'VaApiTest#run returned no output') if $PROGRAM_NAME == __FILE__ From 322e9ddb7d35e5d3b61f7f78010d7fe4fc65601c Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Fri, 3 Mar 2023 11:49:29 -0500 Subject: [PATCH 3/3] remove sheild-spinner.gif --- app/assets/images/shield-spinner.gif | Bin 132377 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 app/assets/images/shield-spinner.gif diff --git a/app/assets/images/shield-spinner.gif b/app/assets/images/shield-spinner.gif deleted file mode 100644 index 729b9ad7f1c662fb65eaa43f8999ab7347b683d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132377 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