From 54c66a3cdee5ac3466e5f1ebad9dbad55f8a8738 Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Tue, 19 Nov 2024 13:58:20 -0500 Subject: [PATCH 1/3] LG-14366 Store dynamically-generated proofing components on Profile Proofing components are intended to represent the tooling that was used to create a profile. Traditionally these have been generated by tracking proofing components in a database table associated with the user. There were a number of problems with this approach which 5021e2ef8237ecc6ff38f6338371e89fb8dcf06d introduced a `Idv::ProofingComponents` service to address. This service generates proofing components from the session instead of from the database table. This commit uses the `Idv::ProofingComponents` service to generate the proofing components stored on the profile. This will allow us to drop the proofing components table in a future change. [skip changelog] --- .../idv/enter_password_controller.rb | 8 ++- app/services/idv/profile_maker.rb | 9 ++-- app/services/idv/session.rb | 5 +- .../idv/personal_key_controller_spec.rb | 6 ++- spec/policies/idv/flow_policy_spec.rb | 8 ++- spec/services/idv/profile_maker_spec.rb | 12 ++++- spec/services/idv/session_spec.rb | 51 ++++++++++++++----- 7 files changed, 73 insertions(+), 26 deletions(-) diff --git a/app/controllers/idv/enter_password_controller.rb b/app/controllers/idv/enter_password_controller.rb index 101d3fb0cdb..64768ea7ec8 100644 --- a/app/controllers/idv/enter_password_controller.rb +++ b/app/controllers/idv/enter_password_controller.rb @@ -129,7 +129,13 @@ def confirm_current_password def init_profile idv_session.create_profile_from_applicant_with_password( password, - resolved_authn_context_result.enhanced_ipp?, + is_enhanced_ipp: resolved_authn_context_result.enhanced_ipp?, + proofing_components: ProofingComponents.new( + user: current_user, + idv_session:, + session:, + user_session:, + ).to_h, ) if idv_session.verify_by_mail? current_user.send_email_to_all_addresses(:verify_by_mail_letter_requested) diff --git a/app/services/idv/profile_maker.rb b/app/services/idv/profile_maker.rb index 2e9e3a5e2d8..2429f7bf58c 100644 --- a/app/services/idv/profile_maker.rb +++ b/app/services/idv/profile_maker.rb @@ -2,7 +2,7 @@ module Idv class ProfileMaker - attr_reader :pii_attributes + attr_reader :pii_attributes, :proofing_components def initialize( applicant:, @@ -21,13 +21,14 @@ def save_profile( gpo_verification_needed:, in_person_verification_needed:, selfie_check_performed:, + proofing_components:, deactivation_reason: nil ) profile = Profile.new(user: user, active: false, deactivation_reason: deactivation_reason) profile.initiating_service_provider = initiating_service_provider profile.deactivate_for_in_person_verification if in_person_verification_needed profile.encrypt_pii(pii_attributes, user_password) - profile.proofing_components = current_proofing_components + profile.proofing_components = proofing_components.to_json profile.fraud_pending_reason = fraud_pending_reason profile.idv_level = set_idv_level( @@ -61,10 +62,6 @@ def set_idv_level(in_person_verification_needed:, selfie_check_performed:) end end - def current_proofing_components - user.proofing_component&.as_json || {} - end - attr_accessor( :user, :user_password, diff --git a/app/services/idv/session.rb b/app/services/idv/session.rb index abc19910394..33667bee1d0 100644 --- a/app/services/idv/session.rb +++ b/app/services/idv/session.rb @@ -66,7 +66,9 @@ def respond_to_missing?(method_sym, include_private) VALID_SESSION_ATTRIBUTES.include?(attr_name_sym) || super end - def create_profile_from_applicant_with_password(user_password, is_enhanced_ipp) + def create_profile_from_applicant_with_password( + user_password, is_enhanced_ipp:, proofing_components: + ) if user_has_unscheduled_in_person_enrollment? UspsInPersonProofing::EnrollmentHelper.schedule_in_person_enrollment( user: current_user, @@ -82,6 +84,7 @@ def create_profile_from_applicant_with_password(user_password, is_enhanced_ipp) gpo_verification_needed: !phone_confirmed? || verify_by_mail?, in_person_verification_needed: current_user.has_in_person_enrollment?, selfie_check_performed: session[:selfie_check_performed], + proofing_components:, ) profile.activate unless profile.reason_not_to_activate diff --git a/spec/controllers/idv/personal_key_controller_spec.rb b/spec/controllers/idv/personal_key_controller_spec.rb index dabd49f265e..33946f4bbe1 100644 --- a/spec/controllers/idv/personal_key_controller_spec.rb +++ b/spec/controllers/idv/personal_key_controller_spec.rb @@ -69,7 +69,11 @@ def assert_personal_key_generated_for_profiles(*profile_pii_pairs) idv_session.applicant = applicant if mint_profile_from_idv_session - idv_session.create_profile_from_applicant_with_password(password, is_enhanced_ipp) + idv_session.create_profile_from_applicant_with_password( + password, + is_enhanced_ipp:, + proofing_components: {}, + ) end end diff --git a/spec/policies/idv/flow_policy_spec.rb b/spec/policies/idv/flow_policy_spec.rb index d96c9006355..8561f382d84 100644 --- a/spec/policies/idv/flow_policy_spec.rb +++ b/spec/policies/idv/flow_policy_spec.rb @@ -315,7 +315,9 @@ it 'returns personal_key' do stub_up_to(:request_letter, idv_session: idv_session) idv_session.gpo_code_verified = true - idv_session.create_profile_from_applicant_with_password('password', is_enhanced_ipp) + idv_session.create_profile_from_applicant_with_password( + 'password', is_enhanced_ipp:, proofing_components: {} + ) expect(subject.info_for_latest_step.key).to eq(:personal_key) expect(subject.controller_allowed?(controller: Idv::PersonalKeyController)).to be @@ -326,7 +328,9 @@ 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('password', is_enhanced_ipp) + idv_session.create_profile_from_applicant_with_password( + 'password', is_enhanced_ipp:, proofing_components: {} + ) expect(subject.info_for_latest_step.key).to eq(:personal_key) expect(subject.controller_allowed?(controller: Idv::PersonalKeyController)).to be diff --git a/spec/services/idv/profile_maker_spec.rb b/spec/services/idv/profile_maker_spec.rb index 6736bcba24e..b30ac449b9b 100644 --- a/spec/services/idv/profile_maker_spec.rb +++ b/spec/services/idv/profile_maker_spec.rb @@ -7,6 +7,7 @@ let(:user_password) { user.password } let(:initiating_service_provider) { nil } let(:in_person_proofing_enforce_tmx_mock) { false } + let(:proofing_components) { { document_check: :mock } } subject do described_class.new( @@ -18,12 +19,12 @@ end it 'creates an inactive Profile with encrypted PII' do - proofing_component = ProofingComponent.create(user_id: user.id, document_check: 'mock') profile = subject.save_profile( fraud_pending_reason: nil, gpo_verification_needed: false, in_person_verification_needed: false, selfie_check_performed: false, + proofing_components:, ) pii = subject.pii_attributes @@ -32,7 +33,7 @@ expect(profile.encrypted_pii).to_not be_nil expect(profile.encrypted_pii).to_not match('Some') expect(profile.fraud_pending_reason).to be_nil - expect(profile.proofing_components).to match(proofing_component.as_json) + expect(profile.proofing_components).to match(proofing_components.to_json) expect(profile.active).to eq(false) expect(profile.deactivation_reason).to be_nil @@ -48,6 +49,7 @@ deactivation_reason: :encryption_error, in_person_verification_needed: false, selfie_check_performed: false, + proofing_components:, ) end it 'creates an inactive profile with deactivation reason' do @@ -75,6 +77,7 @@ deactivation_reason: nil, in_person_verification_needed: in_person_verification_needed, selfie_check_performed: false, + proofing_components:, ) end @@ -118,6 +121,7 @@ deactivation_reason: nil, in_person_verification_needed: false, selfie_check_performed: false, + proofing_components:, ) end it 'creates a pending profile for gpo verification' do @@ -151,6 +155,7 @@ deactivation_reason: nil, in_person_verification_needed: true, selfie_check_performed: false, + proofing_components:, ) end @@ -190,6 +195,7 @@ deactivation_reason: nil, in_person_verification_needed: true, selfie_check_performed: false, + proofing_components:, ) end @@ -220,6 +226,7 @@ deactivation_reason: nil, in_person_verification_needed: false, selfie_check_performed: selfie_check_performed, + proofing_components:, ) end @@ -267,6 +274,7 @@ deactivation_reason: nil, in_person_verification_needed: false, selfie_check_performed: false, + proofing_components:, ) end it 'creates a profile with the initiating sp recorded' do diff --git a/spec/services/idv/session_spec.rb b/spec/services/idv/session_spec.rb index e7009ef5352..df023971d8d 100644 --- a/spec/services/idv/session_spec.rb +++ b/spec/services/idv/session_spec.rb @@ -3,7 +3,6 @@ RSpec.describe Idv::Session do let(:user) { create(:user) } let(:user_session) { {} } - let(:is_enhanced_ipp) { false } subject do Idv::Session.new(user_session: user_session, current_user: user, service_provider: nil) @@ -128,6 +127,8 @@ end describe '#create_profile_from_applicant_with_password' do + let(:is_enhanced_ipp) { false } + let(:proofing_components) { { document_check: 'mock' } } let(:opt_in_param) { nil } before do @@ -146,7 +147,9 @@ now = Time.zone.now subject.user_phone_confirmation = true - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) profile = subject.profile expect(profile.activated_at).to eq now @@ -165,7 +168,9 @@ it 'does not complete the profile if the user has not completed OTP phone confirmation' do subject.user_phone_confirmation = nil - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) profile = subject.profile expect(profile.activated_at).to eq nil @@ -200,7 +205,9 @@ end it 'creates an USPS enrollment' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) expect(UspsInPersonProofing::EnrollmentHelper).to have_received( :schedule_in_person_enrollment, ).with( @@ -212,7 +219,9 @@ end it 'creates a profile with in person verification pending' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) expect(profile).to have_attributes( { activated_at: nil, @@ -227,12 +236,16 @@ end it 'saves the pii to the session' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) expect(Pii::Cacher.new(user, user_session).fetch(profile.id)).to_not be_nil end it 'associates the in person enrollment with the created profile' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) expect(enrollment.reload.profile_id).to eq(profile.id) end end @@ -245,7 +258,9 @@ end it 'does not create a profile' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) rescue expect(profile).to be_nil end @@ -264,14 +279,18 @@ end it 'does not create an USPS enrollment' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) expect(UspsInPersonProofing::EnrollmentHelper).to_not have_received( :schedule_in_person_enrollment, ) end it 'creates a profile' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) expect(profile).to have_attributes( { active: true, @@ -284,7 +303,9 @@ end it 'saves the pii to the session' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) expect(Pii::Cacher.new(user, user_session).fetch(profile.id)).to_not be_nil end end @@ -297,7 +318,9 @@ end it 'sets profile to pending gpo verification' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) profile = subject.profile expect(profile.activated_at).to eq nil @@ -321,7 +344,9 @@ end it 'does not complete the user profile' do - subject.create_profile_from_applicant_with_password(user.password, is_enhanced_ipp) + subject.create_profile_from_applicant_with_password( + user.password, is_enhanced_ipp:, proofing_components: + ) profile = subject.profile expect(profile.activated_at).to eq nil From 121b105697eefd573bd8199f8853d2f3ddb81ebf Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Wed, 20 Nov 2024 10:05:07 -0500 Subject: [PATCH 2/3] remove the `to_json` call --- app/services/idv/profile_maker.rb | 2 +- spec/services/idv/profile_maker_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/idv/profile_maker.rb b/app/services/idv/profile_maker.rb index 2429f7bf58c..27ef45e8be0 100644 --- a/app/services/idv/profile_maker.rb +++ b/app/services/idv/profile_maker.rb @@ -28,7 +28,7 @@ def save_profile( profile.initiating_service_provider = initiating_service_provider profile.deactivate_for_in_person_verification if in_person_verification_needed profile.encrypt_pii(pii_attributes, user_password) - profile.proofing_components = proofing_components.to_json + profile.proofing_components = proofing_components profile.fraud_pending_reason = fraud_pending_reason profile.idv_level = set_idv_level( diff --git a/spec/services/idv/profile_maker_spec.rb b/spec/services/idv/profile_maker_spec.rb index b30ac449b9b..b1150af6e47 100644 --- a/spec/services/idv/profile_maker_spec.rb +++ b/spec/services/idv/profile_maker_spec.rb @@ -33,7 +33,7 @@ expect(profile.encrypted_pii).to_not be_nil expect(profile.encrypted_pii).to_not match('Some') expect(profile.fraud_pending_reason).to be_nil - expect(profile.proofing_components).to match(proofing_components.to_json) + expect(profile.proofing_components).to match(proofing_components) expect(profile.active).to eq(false) expect(profile.deactivation_reason).to be_nil From dde57cc25db13458404242eb916e1b1ff9eeff02 Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Wed, 20 Nov 2024 11:01:10 -0500 Subject: [PATCH 3/3] spec fix --- spec/services/idv/profile_maker_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/idv/profile_maker_spec.rb b/spec/services/idv/profile_maker_spec.rb index b1150af6e47..987438eff83 100644 --- a/spec/services/idv/profile_maker_spec.rb +++ b/spec/services/idv/profile_maker_spec.rb @@ -33,7 +33,7 @@ expect(profile.encrypted_pii).to_not be_nil expect(profile.encrypted_pii).to_not match('Some') expect(profile.fraud_pending_reason).to be_nil - expect(profile.proofing_components).to match(proofing_components) + expect(profile.proofing_components).to match(proofing_components.as_json) expect(profile.active).to eq(false) expect(profile.deactivation_reason).to be_nil