From ebcb031a6e6f6bdea83dc624325cb839c9dd0b4d Mon Sep 17 00:00:00 2001 From: Lauren George Date: Tue, 7 Jan 2025 16:19:16 -0500 Subject: [PATCH 1/7] LG-15166: Add new key to Idv::Session Adds a new key, `doc_auth_vendor`, to Idv::Session. This is part 1 to eliminate issues with 50/50 state handling. [skip changelog] --- app/services/idv/session.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/services/idv/session.rb b/app/services/idv/session.rb index b4ce639e580..ce1cf00bb10 100644 --- a/app/services/idv/session.rb +++ b/app/services/idv/session.rb @@ -31,6 +31,7 @@ module Idv # @attr skip_doc_auth_from_handoff [Boolean, nil] # @attr skip_doc_auth_from_how_to_verify [Boolean, nil] # @attr skip_hybrid_handoff [Boolean, nil] + # @attr doc_auth_vendor [String, nil] # @attr source_check_vendor [String, nil] # @attr ssn [String, nil] # @attr threatmetrix_review_status [String, nil] @@ -66,6 +67,7 @@ class Session profile_id proofing_started_at redo_document_capture + doc_auth_vendor source_check_vendor residential_resolution_vendor resolution_successful From 28f078256f76299a9def93882e5e42252f65acb1 Mon Sep 17 00:00:00 2001 From: Lauren George Date: Tue, 7 Jan 2025 18:17:33 -0500 Subject: [PATCH 2/7] sorted the attributes and doc strings --- app/services/idv/session.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/services/idv/session.rb b/app/services/idv/session.rb index ce1cf00bb10..bec7895135c 100644 --- a/app/services/idv/session.rb +++ b/app/services/idv/session.rb @@ -4,6 +4,7 @@ module Idv # @attr address_edited [Boolean, nil] # @attr address_verification_mechanism [String, nil] # @attr applicant [Struct, nil] + # @attr doc_auth_vendor [String, nil] # @attr document_capture_session_uuid [String, nil] # @attr flow_path [String, nil] # @attr go_back_path [String, nil] @@ -31,7 +32,6 @@ module Idv # @attr skip_doc_auth_from_handoff [Boolean, nil] # @attr skip_doc_auth_from_how_to_verify [Boolean, nil] # @attr skip_hybrid_handoff [Boolean, nil] - # @attr doc_auth_vendor [String, nil] # @attr source_check_vendor [String, nil] # @attr ssn [String, nil] # @attr threatmetrix_review_status [String, nil] @@ -48,6 +48,7 @@ class Session address_edited address_verification_mechanism applicant + doc_auth_vendor document_capture_session_uuid flow_path go_back_path @@ -67,8 +68,6 @@ class Session profile_id proofing_started_at redo_document_capture - doc_auth_vendor - source_check_vendor residential_resolution_vendor resolution_successful resolution_vendor @@ -78,6 +77,7 @@ class Session skip_doc_auth_from_how_to_verify skip_hybrid_handoff socure_docv_wait_polling_started_at + source_check_vendor ssn threatmetrix_review_status threatmetrix_session_id From 0248303fe578630012eeeefb68be8f90e40817f8 Mon Sep 17 00:00:00 2001 From: Lauren George Date: Fri, 10 Jan 2025 15:42:15 -0500 Subject: [PATCH 3/7] LG-15166: Store doc_auth_vendor in Idv::Session **Why** * Currently, we compute the vendor for remote document verification using DocAuthRouter, which requires downstream business logic to depend on context that may or may not be available. In order to eliminate calls to DocAuthRouter in places like Idv::ProofingComponents, we first need to start storing the vendor directly in Idv::Session. **How** * Add a new key `doc_auth_vendor` to Idv::Session. * Set the new key after successful document capture. If the user opted for in person proofing, it will be `usps`, otherwise we use the existing `Idv::DocumentCaptureConcern#doc_auth_vendor` method. * Clear `doc_auth_vendor` if the following steps are undone: link_sent, document_capture, and socure_document_capture. changelog: Internal, IdV flow, Simplify creation of Idv::ProofingComponents --- app/controllers/concerns/idv/document_capture_concern.rb | 9 +++++++++ app/controllers/idv/document_capture_controller.rb | 1 + app/controllers/idv/link_sent_controller.rb | 1 + .../idv/socure/document_capture_controller.rb | 1 + app/services/idv/session.rb | 2 +- 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/controllers/concerns/idv/document_capture_concern.rb b/app/controllers/concerns/idv/document_capture_concern.rb index 5cd9eb2ea57..e23cc521cbb 100644 --- a/app/controllers/concerns/idv/document_capture_concern.rb +++ b/app/controllers/concerns/idv/document_capture_concern.rb @@ -39,6 +39,7 @@ def error_hash(message) def extract_pii_from_doc(user, store_in_session: false) if defined?(idv_session) # hybrid mobile does not have idv_session idv_session.had_barcode_read_failure = stored_result.attention_with_barcode? + idv_session.doc_auth_vendor = resolve_doc_auth_vendor(user) if store_in_session idv_session.pii_from_doc = stored_result.pii_from_doc idv_session.selfie_check_performed = stored_result.selfie_check_performed? @@ -58,6 +59,14 @@ def selfie_requirement_met? stored_result.selfie_check_performed? end + def resolve_doc_auth_vendor(user) + if user.establishing_in_person_enrollment || user.pending_in_person_enrollment + Idp::Constants::Vendors::USPS + else + doc_auth_vendor + end + end + def redirect_to_correct_vendor(vendor, in_hybrid_mobile) return if IdentityConfig.store.doc_auth_redirect_to_correct_vendor_disabled diff --git a/app/controllers/idv/document_capture_controller.rb b/app/controllers/idv/document_capture_controller.rb index 47fdc45dc19..277be18523f 100644 --- a/app/controllers/idv/document_capture_controller.rb +++ b/app/controllers/idv/document_capture_controller.rb @@ -75,6 +75,7 @@ def self.step_info idv_session.had_barcode_attention_error = nil idv_session.had_barcode_read_failure = nil idv_session.selfie_check_performed = nil + idv_session.doc_auth_vendor = nil end, ) end diff --git a/app/controllers/idv/link_sent_controller.rb b/app/controllers/idv/link_sent_controller.rb index 9070b461809..4ab181d49bc 100644 --- a/app/controllers/idv/link_sent_controller.rb +++ b/app/controllers/idv/link_sent_controller.rb @@ -50,6 +50,7 @@ def self.step_info idv_session.had_barcode_attention_error = nil idv_session.had_barcode_read_failure = nil idv_session.selfie_check_performed = nil + idv_session.doc_auth_vendor = nil end, ) end diff --git a/app/controllers/idv/socure/document_capture_controller.rb b/app/controllers/idv/socure/document_capture_controller.rb index f84854fe9df..36369700817 100644 --- a/app/controllers/idv/socure/document_capture_controller.rb +++ b/app/controllers/idv/socure/document_capture_controller.rb @@ -105,6 +105,7 @@ def self.step_info idv_session.pii_from_doc = nil idv_session.socure_docv_wait_polling_started_at = nil idv_session.invalidate_in_person_pii_from_user! + idv_session.doc_auth_vendor = nil end, ) end diff --git a/app/services/idv/session.rb b/app/services/idv/session.rb index bec7895135c..d9b0570513f 100644 --- a/app/services/idv/session.rb +++ b/app/services/idv/session.rb @@ -21,7 +21,7 @@ module Idv # @attr phone_for_mobile_flow [String, nil] # @attr previous_phone_step_params [Array] # @attr previous_ssn [String, nil] - # @attr profile_id [String, nil] + # @attr profile_id [Integer, nil] # @attr proofing_started_at [String, nil] # @attr redo_document_capture [Boolean, nil] # @attr residential_resolution_vendor [String, nil] From 312a75936ac74e60899874d21aeb9df5e0e2a809 Mon Sep 17 00:00:00 2001 From: Lauren George Date: Mon, 13 Jan 2025 18:08:22 -0500 Subject: [PATCH 4/7] Add minimal specs --- .../idv/socure/document_capture_controller_spec.rb | 1 + spec/policies/idv/flow_policy_spec.rb | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/spec/controllers/idv/socure/document_capture_controller_spec.rb b/spec/controllers/idv/socure/document_capture_controller_spec.rb index d663103604c..134660033df 100644 --- a/spec/controllers/idv/socure/document_capture_controller_spec.rb +++ b/spec/controllers/idv/socure/document_capture_controller_spec.rb @@ -376,6 +376,7 @@ end it 'returns FOUND (302) and redirects to SSN' do + expect(subject.idv_session.doc_auth_vendor).to_not be_nil expect(response).to redirect_to(idv_ssn_path) expect(@analytics).to have_logged_event('IdV: doc auth document_capture submitted') end diff --git a/spec/policies/idv/flow_policy_spec.rb b/spec/policies/idv/flow_policy_spec.rb index 246cb8ddf1b..2c7fa19a8d5 100644 --- a/spec/policies/idv/flow_policy_spec.rb +++ b/spec/policies/idv/flow_policy_spec.rb @@ -42,6 +42,7 @@ idv_session.phone_for_mobile_flow = '201-555-1212' idv_session.pii_from_doc = Pii::StateId.new(**Idp::Constants::MOCK_IDV_APPLICANT) + idv_session.doc_auth_vendor = 'test_vendor' idv_session.had_barcode_read_failure = true idv_session.had_barcode_attention_error = true @@ -63,6 +64,7 @@ expect(idv_session.phone_for_mobile_flow).to be_nil expect(idv_session.pii_from_doc).to be_nil + expect(idv_session.doc_auth_vendor).to be_nil expect(idv_session.had_barcode_read_failure).to be_nil expect(idv_session.had_barcode_attention_error).to be_nil @@ -86,6 +88,7 @@ idv_session.pii_from_doc = nil idv_session.had_barcode_read_failure = true idv_session.had_barcode_attention_error = true + idv_session.doc_auth_vendor = 'test_vendor' idv_session.ssn = nil @@ -130,6 +133,7 @@ end.not_to change { idv_session.welcome_visited idv_session.document_capture_session_uuid + idv_session.doc_auth_vendor idv_session.idv_consent_given_at idv_session.idv_consent_given? idv_session.skip_hybrid_handoff @@ -150,6 +154,7 @@ .with(user_phone_confirmation_session).and_return(user_phone_confirmation_session) allow(user).to receive(:gpo_pending_profile?).and_return(has_gpo_pending_profile) end + context 'empty session' do it 'returns welcome' do expect(subject.info_for_latest_step.key).to eq(:welcome) @@ -311,6 +316,7 @@ context 'preconditions for personal_key are present' do let(:is_enhanced_ipp) { false } let(:password) { 'sekrit phrase' } + context 'user has a verify by mail pending profile' do it 'returns personal_key' do stub_up_to(:request_letter, idv_session: idv_session) @@ -326,6 +332,7 @@ context 'user has a newly activated profile' do let(:is_enhanced_ipp) { false } + it 'returns personal_key' do stub_up_to(:otp_verification, idv_session: idv_session) idv_session.create_profile_from_applicant_with_password( From 2ca526d4b642c7f7236ceb85f224e84e2d3823cd Mon Sep 17 00:00:00 2001 From: Lauren George Date: Tue, 14 Jan 2025 18:18:36 -0500 Subject: [PATCH 5/7] For IPP, update idv_session.doc_auth_vendor in InPerson::StateIdController --- .../concerns/idv/document_capture_concern.rb | 11 ++--------- app/controllers/idv/in_person/state_id_controller.rb | 2 ++ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/app/controllers/concerns/idv/document_capture_concern.rb b/app/controllers/concerns/idv/document_capture_concern.rb index e23cc521cbb..dcd487a7e48 100644 --- a/app/controllers/concerns/idv/document_capture_concern.rb +++ b/app/controllers/concerns/idv/document_capture_concern.rb @@ -39,7 +39,8 @@ def error_hash(message) def extract_pii_from_doc(user, store_in_session: false) if defined?(idv_session) # hybrid mobile does not have idv_session idv_session.had_barcode_read_failure = stored_result.attention_with_barcode? - idv_session.doc_auth_vendor = resolve_doc_auth_vendor(user) + # See also Idv::InPerson::StateIdController#update + idv_session.doc_auth_vendor = doc_auth_vendor if store_in_session idv_session.pii_from_doc = stored_result.pii_from_doc idv_session.selfie_check_performed = stored_result.selfie_check_performed? @@ -59,14 +60,6 @@ def selfie_requirement_met? stored_result.selfie_check_performed? end - def resolve_doc_auth_vendor(user) - if user.establishing_in_person_enrollment || user.pending_in_person_enrollment - Idp::Constants::Vendors::USPS - else - doc_auth_vendor - end - end - def redirect_to_correct_vendor(vendor, in_hybrid_mobile) return if IdentityConfig.store.doc_auth_redirect_to_correct_vendor_disabled diff --git a/app/controllers/idv/in_person/state_id_controller.rb b/app/controllers/idv/in_person/state_id_controller.rb index 638aa26a08f..80d8bde6146 100644 --- a/app/controllers/idv/in_person/state_id_controller.rb +++ b/app/controllers/idv/in_person/state_id_controller.rb @@ -56,6 +56,7 @@ def update redirect_url = idv_in_person_ssn_url end + idv_session.doc_auth_vendor = Idp::Constants::Vendors::USPS redirect_to redirect_url else render :show, locals: extra_view_variables @@ -85,6 +86,7 @@ def self.step_info pii_from_user[:identity_doc_city] = nil pii_from_user[:identity_doc_zipcode] = nil pii_from_user[:identity_doc_state] = nil + idv_session.doc_auth_vendor = nil end, ) end From 4ef3cb7a15331e5273193c8bb7d4a4dcdb0d2bd3 Mon Sep 17 00:00:00 2001 From: Lauren George Date: Tue, 14 Jan 2025 18:23:26 -0500 Subject: [PATCH 6/7] PR feedback: capture edge cases and expand coverage --- .../idv/document_capture_controller_spec.rb | 111 ++++++++++-------- .../idv/in_person/state_id_controller_spec.rb | 7 ++ .../idv/link_sent_controller_spec.rb | 11 ++ .../document_capture_controller_spec.rb | 14 ++- 4 files changed, 88 insertions(+), 55 deletions(-) diff --git a/spec/controllers/idv/document_capture_controller_spec.rb b/spec/controllers/idv/document_capture_controller_spec.rb index 4a0d945b92e..aa14fc0059e 100644 --- a/spec/controllers/idv/document_capture_controller_spec.rb +++ b/spec/controllers/idv/document_capture_controller_spec.rb @@ -3,48 +3,67 @@ RSpec.describe Idv::DocumentCaptureController do include FlowPolicyHelper + let(:user) { create(:user) } + let(:idv_vendor) { Idp::Constants::Vendors::LEXIS_NEXIS } + let(:vendor_switching_enabled) { true } + let(:ab_test_args) { {} } + + # selfie related test flags + let(:facial_match_required) { false } + let(:flow_path) { 'standard' } + let(:doc_auth_selfie_desktop_test_mode) { false } + + # document capture setup + let(:doc_auth_success) { true } let(:document_capture_session_requested_at) { Time.zone.now } + let(:document_capture_session_uuid) { document_capture_session&.uuid } - let!(:document_capture_session) do - DocumentCaptureSession.create!( + let(:document_capture_session) do + DocumentCaptureSession.create( user: user, requested_at: document_capture_session_requested_at, ) end - let(:document_capture_session_uuid) { document_capture_session&.uuid } - - let(:user) { create(:user) } - let(:ab_test_args) { {} } - - # selfie related test flags - let(:sp_selfie_enabled) { false } - let(:flow_path) { 'standard' } - let(:doc_auth_selfie_desktop_test_mode) { false } + let(:stored_result) do + DocumentCaptureSessionResult.new( + id: SecureRandom.uuid, + success: doc_auth_success, + doc_auth_success: doc_auth_success, + selfie_status: :none, + pii: { first_name: 'Testy', last_name: 'Testerson' }, + attention_with_barcode: false, + ) + end before do stub_sign_in(user) stub_up_to(:hybrid_handoff, idv_session: subject.idv_session) - stub_analytics + subject.idv_session.flow_path = flow_path subject.idv_session.document_capture_session_uuid = document_capture_session_uuid - vot = sp_selfie_enabled ? 'Pb' : 'P1' + vot = facial_match_required ? 'Pb' : 'P1' resolved_authn_context = Vot::Parser.new(vector_of_trust: vot).parse - allow(controller).to receive(:resolved_authn_context_result) .and_return(resolved_authn_context) - subject.idv_session.flow_path = flow_path - allow(subject).to receive(:ab_test_analytics_buckets).and_return(ab_test_args) - allow(IdentityConfig.store).to receive(:doc_auth_vendor).and_return( - Idp::Constants::Vendors::LEXIS_NEXIS, - ) - allow(IdentityConfig.store).to receive(:doc_auth_vendor_default).and_return( - Idp::Constants::Vendors::LEXIS_NEXIS, - ) + allow(subject).to receive(:ab_test_analytics_buckets).and_return(ab_test_args) + allow(IdentityConfig.store).to receive(:doc_auth_vendor).and_return(idv_vendor) + allow(IdentityConfig.store).to receive(:doc_auth_vendor_default).and_return(idv_vendor) + allow(IdentityConfig.store).to receive(:doc_auth_vendor_switching_enabled) + .and_return(vendor_switching_enabled) allow(IdentityConfig.store).to receive(:doc_auth_selfie_desktop_test_mode) .and_return(doc_auth_selfie_desktop_test_mode) + + allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) + + allow(subject).to receive(:stored_result).and_return(stored_result) + + user_session = {} + allow(subject).to receive(:user_session).and_return(user_session) + + stub_analytics end describe '#step_info' do @@ -54,7 +73,7 @@ context 'when selfie feature is enabled system wide' do describe 'with sp selfie disabled' do - let(:sp_selfie_enabled) { false } + let(:facial_match_required) { false } it 'does not satisfy precondition' do expect(Idv::DocumentCaptureController.step_info.preconditions.is_a?(Proc)) @@ -66,7 +85,7 @@ end describe 'with sp selfie enabled' do - let(:sp_selfie_enabled) { true } + let(:facial_match_required) { true } it 'does satisfy precondition' do expect(Idv::DocumentCaptureController.step_info.preconditions.is_a?(Proc)) @@ -105,31 +124,17 @@ describe '#show' do let(:analytics_name) { 'IdV: doc auth document_capture visited' } + let(:analytics_args) do { analytics_id: 'Doc Auth', flow_path: 'standard', step: 'document_capture', liveness_checking_required: false, - selfie_check_required: sp_selfie_enabled, + selfie_check_required: facial_match_required, } end - let(:idv_vendor) { Idp::Constants::Vendors::LEXIS_NEXIS } - let(:vendor_switching_enabled) { true } - - before do - allow(IdentityConfig.store).to receive(:doc_auth_vendor).and_return( - idv_vendor, - ) - allow(IdentityConfig.store).to receive(:doc_auth_vendor_default).and_return( - idv_vendor, - ) - allow(IdentityConfig.store).to receive(:doc_auth_vendor_switching_enabled).and_return( - vendor_switching_enabled, - ) - end - it 'has non-nil presenter' do get :show expect(assigns(:presenter)).to be_kind_of(Idv::InPerson::UspsFormPresenter) @@ -188,13 +193,7 @@ context 'socure is the default vendor but facial match is required' do let(:idv_vendor) { Idp::Constants::Vendors::SOCURE } - let(:vot) { 'Pb' } - - before do - resolved_authn_context = Vot::Parser.new(vector_of_trust: vot).parse - allow(controller).to receive(:resolved_authn_context_result) - .and_return(resolved_authn_context) - end + let(:facial_match_required) { true } it 'does not redirect to Socure controller' do get :show @@ -204,7 +203,7 @@ end context 'when a selfie is requested' do - let(:sp_selfie_enabled) { true } + let(:facial_match_required) { true } describe 'when desktop selfie disabled' do it 'redirect back to handoff page' do @@ -224,6 +223,7 @@ describe 'when desktop selfie enabled' do let(:doc_auth_selfie_desktop_test_mode) { true } + it 'allows capture' do expect(subject).to receive(:render).with( :show, @@ -325,7 +325,7 @@ end context 'ipp disabled for sp' do - let(:sp_selfie_enabled) { true } + let(:facial_match_required) { true } before do allow(Idv::InPersonConfig).to receive(:enabled_for_issuer?).with(anything).and_return(false) @@ -344,6 +344,7 @@ describe '#update' do let(:analytics_name) { 'IdV: doc auth document_capture submitted' } + let(:analytics_args) do { success: true, @@ -402,7 +403,7 @@ it 'stays on document capture' do put :update - + expect(subject.idv_session.doc_auth_vendor).to be_nil expect(response).to redirect_to idv_document_capture_url end end @@ -410,10 +411,18 @@ context 'performed' do let(:performed_if_needed) { true } - it 'redirects to ssn' do + before do put :update + end + + it 'redirects to ssn' do expect(response).to redirect_to idv_ssn_url end + + it 'correctly updates Idv::Session' do + expect(subject.idv_session.doc_auth_vendor).to_not be_nil + expect(subject.idv_session.doc_auth_vendor).to match(idv_vendor) + end end end diff --git a/spec/controllers/idv/in_person/state_id_controller_spec.rb b/spec/controllers/idv/in_person/state_id_controller_spec.rb index 6b448276214..8e40a58b470 100644 --- a/spec/controllers/idv/in_person/state_id_controller_spec.rb +++ b/spec/controllers/idv/in_person/state_id_controller_spec.rb @@ -161,6 +161,7 @@ put :update, params: invalid_params expect(subject.idv_session.ssn).to eq(nil) + expect(subject.idv_session.doc_auth_vendor).to eq(nil) expect(subject.extra_view_variables[:updating_state_id]).to eq(false) expect(response).to render_template :show end @@ -196,6 +197,12 @@ # param from form as id_number but is renamed to state_id_number on update expect(pii_from_user[:state_id_number]).to eq id_number end + + it 'sets values in Idv::Session' do + put :update, params: params + + expect(subject.idv_session.doc_auth_vendor).to eq(Idp::Constants::Vendors::USPS) + end end context 'when same_address_as_id is...' do diff --git a/spec/controllers/idv/link_sent_controller_spec.rb b/spec/controllers/idv/link_sent_controller_spec.rb index 967cefa019f..d59a440f370 100644 --- a/spec/controllers/idv/link_sent_controller_spec.rb +++ b/spec/controllers/idv/link_sent_controller_spec.rb @@ -42,6 +42,7 @@ describe '#show' do let(:analytics_name) { 'IdV: doc auth link_sent visited' } + let(:analytics_args) do { analytics_id: 'Doc Auth', @@ -104,6 +105,7 @@ describe '#update' do let(:analytics_name) { 'IdV: doc auth link_sent submitted' } + let(:analytics_args) do { analytics_id: 'Doc Auth', @@ -143,6 +145,7 @@ end context 'check results' do + let(:idv_vendor) { Idp::Constants::Vendors::MOCK } let(:load_result) { double('load result') } let(:session_canceled_at) { nil } let(:load_result_success) { true } @@ -167,6 +170,8 @@ it 'redirects to ssn page' do put :update + expect(subject.idv_session.doc_auth_vendor).to_not be_nil + expect(subject.idv_session.doc_auth_vendor).to eq(idv_vendor) expect(response).to redirect_to(idv_ssn_url) proofing_components = Idv::ProofingComponents.new( @@ -183,9 +188,11 @@ before do subject.idv_session.redo_document_capture = true end + it 'resets redo_document capture to nil in idv_session' do put :update expect(subject.idv_session.redo_document_capture).to be_nil + expect(subject.idv_session.doc_auth_vendor).to eq(idv_vendor) end end @@ -202,6 +209,7 @@ put :update expect(response.status).to eq(204) + expect(subject.idv_session.doc_auth_vendor).to be_nil end end @@ -211,6 +219,7 @@ it 'redirects to ssn' do put :update expect(flash[:error]).to eq nil + expect(subject.idv_session.doc_auth_vendor).to eq(idv_vendor) expect(response).to redirect_to idv_ssn_url end end @@ -233,6 +242,7 @@ it 'redirects to hybrid_handoff page' do put :update + expect(subject.idv_session.doc_auth_vendor).to be_nil expect(response).to redirect_to(idv_hybrid_handoff_url) end end @@ -244,6 +254,7 @@ put :update expect(response).to have_http_status(204) + expect(subject.idv_session.doc_auth_vendor).to be_nil end end end diff --git a/spec/controllers/idv/socure/document_capture_controller_spec.rb b/spec/controllers/idv/socure/document_capture_controller_spec.rb index 134660033df..8f059246b7b 100644 --- a/spec/controllers/idv/socure/document_capture_controller_spec.rb +++ b/spec/controllers/idv/socure/document_capture_controller_spec.rb @@ -375,10 +375,16 @@ get :update end - it 'returns FOUND (302) and redirects to SSN' do - expect(subject.idv_session.doc_auth_vendor).to_not be_nil - expect(response).to redirect_to(idv_ssn_path) - expect(@analytics).to have_logged_event('IdV: doc auth document_capture submitted') + context 'when doc auth succeeds' do + it 'correctly stores doc_auth_vendor in Idv::Session' do + expect(subject.idv_session.doc_auth_vendor).to_not be_nil + expect(subject.idv_session.doc_auth_vendor).to match(idv_vendor) + end + + it 'returns FOUND (302) and redirects to SSN' do + expect(response).to redirect_to(idv_ssn_path) + expect(@analytics).to have_logged_event('IdV: doc auth document_capture submitted') + end end context 'when doc auth fails' do From dc210cea20e7e66bebb37c83269f2420c3a982ce Mon Sep 17 00:00:00 2001 From: Lauren George Date: Tue, 14 Jan 2025 18:24:37 -0500 Subject: [PATCH 7/7] Layout fixes, updating some language, and removing old cruft --- .../socure/responses/docv_result_response.rb | 2 +- .../idv/document_capture_controller_spec.rb | 12 +++--------- .../idv/in_person/state_id_controller_spec.rb | 9 +++++++++ .../socure/document_capture_controller_spec.rb | 18 +++++++++++++++--- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/app/services/doc_auth/socure/responses/docv_result_response.rb b/app/services/doc_auth/socure/responses/docv_result_response.rb index 49876ec7de3..a2ccd250cae 100644 --- a/app/services/doc_auth/socure/responses/docv_result_response.rb +++ b/app/services/doc_auth/socure/responses/docv_result_response.rb @@ -81,7 +81,7 @@ def extra_attributes liveness_checking_required: @biometric_comparison_required, issue_year: state_id_issued&.year, doc_auth_success: successful_result?, - vendor: 'Socure', + vendor: 'Socure', # TODO: Replace with Idp::Constants::Vendors::SOCURE address_line2_present: address2.present?, zip_code: zipcode, birth_year: dob&.year, diff --git a/spec/controllers/idv/document_capture_controller_spec.rb b/spec/controllers/idv/document_capture_controller_spec.rb index aa14fc0059e..7755466caf0 100644 --- a/spec/controllers/idv/document_capture_controller_spec.rb +++ b/spec/controllers/idv/document_capture_controller_spec.rb @@ -353,10 +353,9 @@ flow_path: 'standard', step: 'document_capture', liveness_checking_required: false, - selfie_check_required: sp_selfie_enabled, + selfie_check_required: facial_match_required, } end - let(:result) { { success: true, errors: {} } } it 'invalidates future steps' do subject.idv_session.applicant = Idp::Constants::MOCK_IDV_APPLICANT @@ -364,12 +363,10 @@ put :update expect(subject.idv_session.applicant).to be_nil + expect(subject.idv_session.doc_auth_vendor).to match(idv_vendor) end it 'sends analytics_submitted event' do - allow(result).to receive(:success?).and_return(true) - allow(subject).to receive(:handle_stored_result).and_return(result) - put :update expect(@analytics).to have_logged_event(analytics_name, analytics_args) @@ -392,10 +389,6 @@ before do expect(controller).to receive(:selfie_requirement_met?) .and_return(performed_if_needed) - allow(result).to receive(:success?).and_return(true) - allow(result).to receive(:errors).and_return(result[:errors]) - allow(subject).to receive(:stored_result).and_return(result) - allow(subject).to receive(:extract_pii_from_doc) end context 'not performed' do @@ -440,6 +433,7 @@ describe '#direct_in_person' do let(:analytics_name) { :idv_in_person_direct_start } + let(:analytics_args) do { remaining_submit_attempts: 4, diff --git a/spec/controllers/idv/in_person/state_id_controller_spec.rb b/spec/controllers/idv/in_person/state_id_controller_spec.rb index 8e40a58b470..fe40682d3e7 100644 --- a/spec/controllers/idv/in_person/state_id_controller_spec.rb +++ b/spec/controllers/idv/in_person/state_id_controller_spec.rb @@ -28,6 +28,7 @@ context '#confirm_establishing_enrollment' do let(:enrollment) { nil } + it 'redirects to document capture if not complete' do get :show @@ -38,6 +39,7 @@ describe '#show' do let(:analytics_name) { 'IdV: in person proofing state_id visited' } + let(:analytics_args) do { analytics_id: 'In Person Proofing', @@ -88,12 +90,14 @@ let(:first_name) { 'Natalya' } let(:last_name) { 'Rostova' } let(:formatted_dob) { InPersonHelper::GOOD_DOB } + let(:dob) do parsed_dob = Date.parse(formatted_dob) { month: parsed_dob.month.to_s, day: parsed_dob.day.to_s, year: parsed_dob.year.to_s } end + # residential let(:address1) { InPersonHelper::GOOD_ADDRESS1 } let(:address2) { InPersonHelper::GOOD_ADDRESS2 } @@ -107,6 +111,7 @@ let(:identity_doc_city) { InPersonHelper::GOOD_IDENTITY_DOC_CITY } let(:identity_doc_address_state) { InPersonHelper::GOOD_IDENTITY_DOC_ADDRESS_STATE } let(:identity_doc_zipcode) { InPersonHelper::GOOD_IDENTITY_DOC_ZIPCODE } + context 'with values submitted' do let(:invalid_params) do { identity_doc: { @@ -123,6 +128,7 @@ dob:, } } end + let(:params) do { identity_doc: { first_name:, @@ -138,7 +144,9 @@ dob:, } } end + let(:analytics_name) { 'IdV: in person proofing state_id submitted' } + let(:analytics_args) do { success: true, @@ -329,6 +337,7 @@ identity_doc_zipcode:, } } end + it 'retains identity_doc_ and addr attrs/value in flow session' do Idv::StateIdForm::ATTRIBUTES.each do |attr| expect(subject.user_session['idv/in_person'][:pii_from_user]).to_not have_key attr diff --git a/spec/controllers/idv/socure/document_capture_controller_spec.rb b/spec/controllers/idv/socure/document_capture_controller_spec.rb index 8f059246b7b..3b4afd15a2d 100644 --- a/spec/controllers/idv/socure/document_capture_controller_spec.rb +++ b/spec/controllers/idv/socure/document_capture_controller_spec.rb @@ -8,6 +8,9 @@ let(:fake_socure_endpoint) { 'https://fake-socure.test' } let(:user) { create(:user) } let(:doc_auth_success) { true } + let(:socure_docv_enabled) { true } + let(:socure_docv_verification_data_test_mode) { false } + let(:stored_result) do DocumentCaptureSessionResult.new( id: SecureRandom.uuid, @@ -18,7 +21,6 @@ attention_with_barcode: false, ) end - let(:socure_docv_enabled) { true } let(:document_capture_session) do DocumentCaptureSession.create( @@ -27,8 +29,6 @@ ) end - let(:socure_docv_verification_data_test_mode) { false } - before do allow(IdentityConfig.store).to receive(:socure_docv_enabled) .and_return(socure_docv_enabled) @@ -128,6 +128,7 @@ Saml::Idp::Constants::DEFAULT_AAL_AUTHN_CONTEXT_CLASSREF, ].join(' ') end + before do resolved_authn_context = AuthnContextResolver.new( user: user, @@ -149,6 +150,7 @@ context 'happy path' do let(:socure_capture_app_url) { 'https://verify.socure.test/' } let(:docv_transaction_token) { '176dnc45d-2e34-46f3-82217-6f540ae90673' } + let(:response_body) do { referenceId: '123ab45d-2e34-46f3-8d17-6f540ae90303', @@ -260,6 +262,7 @@ context 'when socure is disabled' do let(:socure_docv_enabled) { false } + it 'the webhook route does not exist' do get(:show) @@ -269,12 +272,14 @@ context 'when socure error encountered' do let(:fake_socure_endpoint) { 'https://fake-socure.test/' } + let(:failed_response_body) do { 'status' => 'Error', 'referenceId' => '1cff6d33-1cc0-4205-b740-c9a9e6b8bd66', 'data' => {}, 'msg' => 'No active account is associated with this request' } end + let(:response_body_401) do { status: 'Error', @@ -282,6 +287,7 @@ msg: 'string', } end + let(:no_doc_found_response_body) do { referenceId: '0dc21b0d-04df-4dd5-8533-ec9ecdafe0f4', @@ -291,10 +297,12 @@ }, } end + before do allow(IdentityConfig.store).to receive(:socure_docv_document_request_endpoint) .and_return(fake_socure_endpoint) end + it 'connection timeout still responds to user' do stub_request(:post, fake_socure_endpoint).to_raise(Faraday::ConnectionFailed) get(:show) @@ -309,6 +317,7 @@ get(:show) expect(response).to redirect_to(idv_socure_document_capture_errors_url) end + it 'socure nil response still gives a result to user' do stub_request(:post, fake_socure_endpoint).to_return( status: 500, @@ -317,6 +326,7 @@ get(:show) expect(response).to redirect_to(idv_socure_document_capture_errors_url) end + it 'socure nil response still gives a result to user' do stub_request(:post, fake_socure_endpoint).to_return( status: 401, @@ -325,6 +335,7 @@ get(:show) expect(response).to redirect_to(idv_socure_document_capture_errors_url) end + it 'socure nil response still gives a result to user' do stub_request(:post, fake_socure_endpoint).to_return( status: 401, @@ -339,6 +350,7 @@ let(:fake_capture_app_url) { 'https://verify.socure.test/fake_capture_app' } let(:socure_capture_app_url) { 'https://verify.socure.test/' } let(:docv_transaction_token) { '176dnc45d-2e34-46f3-82217-6f540ae90673' } + let(:response_body) do { referenceId: '123ab45d-2e34-46f3-8d17-6f540ae90303',