Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -542,10 +542,7 @@ def user_duplicate_profiles_detected?
return false unless sp_eligible_for_one_account?
profile = current_user&.active_profile
return false unless profile
DuplicateProfileConfirmation.where(
profile_id: profile.id,
confirmed_all: nil,
).present?
user_session[:duplicate_profile_ids].present?
end

def sp_eligible_for_one_account?
Expand Down
20 changes: 9 additions & 11 deletions app/controllers/duplicate_profiles_detected_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,35 @@ class DuplicateProfilesDetectedController < ApplicationController
before_action :redirect_unless_user_has_active_duplicate_profile_confirmation

def show
@dupe_profiles_detected_presenter = DuplicateProfilesDetectedPresenter.new(user: current_user)
@dupe_profiles_detected_presenter = DuplicateProfilesDetectedPresenter.new(
user: current_user, user_session: user_session,
)
analytics.one_account_duplicate_profiles_detected
end

def do_not_recognize_profiles
analytics.one_account_unknown_profile_detected
dupe_profile_confirmation.mark_some_profiles_not_recognized

user_session.delete(:duplicate_profile_ids)

redirect_to after_sign_in_path_for(current_user)
end

def recognize_all_profiles
analytics.one_account_recognize_all_profiles
dupe_profile_confirmation.mark_all_profiles_recognized

user_session.delete(:duplicate_profile_ids)
redirect_to after_sign_in_path_for(current_user)
end

private

def redirect_unless_user_has_active_duplicate_profile_confirmation
if current_user&.active_profile.present?
if dupe_profile_confirmation && dupe_profile_confirmation&.confirmed_all.nil?
if user_session[:duplicate_profile_ids].present?
return
end
end
redirect_to root_url
end

def dupe_profile_confirmation
return unless current_user.active_profile
@dupe_profile_confirmation ||= DuplicateProfileConfirmation.find_by(
profile_id: current_user.active_profile.id,
)
end
end
1 change: 0 additions & 1 deletion app/models/profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class Profile < ApplicationRecord
# rubocop:enable Rails/InverseOf
has_many :gpo_confirmation_codes, dependent: :destroy
has_one :in_person_enrollment, dependent: :destroy
has_many :duplicate_profile_confirmations, dependent: :destroy

validates :active, uniqueness: { scope: :user_id, if: :active? }

Expand Down
12 changes: 5 additions & 7 deletions app/presenters/duplicate_profiles_detected_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
class DuplicateProfilesDetectedPresenter
include ActionView::Helpers::TranslationHelper

attr_reader :user, :dupe_profile_confirmation
attr_reader :user, :user_session

def initialize(user:)
def initialize(user:, user_session:)
@user = user
@dupe_profile_confirmation = DuplicateProfileConfirmation.where(
profile_id: user.active_profile.id,
).last
@user_session = user_session
end

def heading
Expand All @@ -21,7 +19,7 @@ def intro
end

def duplicate_profiles
profile_ids = dupe_profile_confirmation.duplicate_profile_ids
profile_ids = user_session[:duplicate_profile_ids]

profiles = Profile.where(id: profile_ids)
profiles.map do |profile|
Expand Down Expand Up @@ -55,6 +53,6 @@ def dont_recognize_some_profiles
private

def multiple_dupe_profiles?
dupe_profile_confirmation.duplicate_profile_ids.count > 1
user_session[:duplicate_profile_ids].count > 1
end
end
24 changes: 7 additions & 17 deletions app/services/duplicate_profile_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,15 @@ def initialize(user:, user_session:, sp:)
end

def check_for_duplicate_profiles
return unless user_has_ial2_profile?
return unless user_has_ial2_profile? && user_sp_eligible_for_one_account?
cacher = Pii::Cacher.new(user, user_session)

pii = cacher.fetch(profile.id)
duplicate_ssn_finder = Idv::DuplicateSsnFinder.new(user:, ssn: pii[:ssn])
associated_profiles = duplicate_ssn_finder.associated_facial_match_profiles_with_ssn
if !duplicate_ssn_finder.ial2_profile_ssn_is_unique?
confirmation = DuplicateProfileConfirmation.find_by(profile_id: profile.id)
if confirmation
if !(confirmation.duplicate_profile_ids == associated_profiles.map(&:id))
confirmation.update(
confirmed_at: Time.zone.now,
confirmed_all: false,
duplicate_profile_ids: associated_profiles.map(&:id),
)
end
else
DuplicateProfileConfirmation.create(
profile_id: profile.id,
confirmed_at: Time.zone.now,
duplicate_profile_ids: associated_profiles.map(&:id),
)
end
ids = associated_profiles.map(&:id)
user_session[:duplicate_profile_ids] = ids
end
end

Expand All @@ -42,4 +28,8 @@ def check_for_duplicate_profiles
def user_has_ial2_profile?
user.identity_verified_with_facial_match?
end

def user_sp_eligible_for_one_account?
IdentityConfig.store.eligible_one_account_providers.include?(sp&.issuer)
end
end
12 changes: 10 additions & 2 deletions app/services/idv/duplicate_ssn_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ def initialize(user:, ssn:)
end

def ssn_is_unique?
Profile.where(ssn_signature: ssn_signatures).where.not(user_id: user.id).empty?
Profile.where(ssn_signature: ssn_signatures)
.where(initiating_service_provider_issuer: sp_eligible_for_one_account)
.where.not(user_id: user.id).empty?
end

def associated_facial_match_profiles_with_ssn
Profile.active.facial_match.where(ssn_signature: ssn_signatures).where.not(user_id: user.id)
Profile.active.facial_match.where(ssn_signature: ssn_signatures)
.where(initiating_service_provider_issuer: sp_eligible_for_one_account)
.where.not(user_id: user.id)
end

def ial2_profile_ssn_is_unique?
Expand Down Expand Up @@ -43,5 +47,9 @@ def ssn_signatures
end
end
end

def sp_eligible_for_one_account
IdentityConfig.store.eligible_one_account_providers
end
end
end
2 changes: 2 additions & 0 deletions app/views/duplicate_profiles_detected/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
timestamp_html: render(TimeComponent.new(time: dupe_profile[:created_at])),
) %>
</p>
<% if dupe_profile[:last_sign_in] %>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this in a previously un-merged PR. Individual local testing would throw an error if the test user hadn't logged in yet. I don't know if this would be a real-world problem.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks yea i saw this. goood chatch.

<p> <%= t(
'duplicate_profiles_detected.last_sign_in_at_html',
timestamp_html: render(TimeComponent.new(time: dupe_profile[:last_sign_in])),
) %>
</p>
<% end %>
</div>
</li>
<% end %>
Expand Down
15 changes: 0 additions & 15 deletions spec/controllers/application_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -666,21 +666,6 @@ def index
expect(response.body).to eq('false')
end
end

context 'when unconfirmed duplicate profile confirmations exist' do
before do
create(
:duplicate_profile_confirmation,
profile: active_profile,
confirmed_all: nil,
)
end

it 'returns true' do
get :index
expect(response.body).to eq('true')
end
end
end
end
end
Expand Down
36 changes: 6 additions & 30 deletions spec/controllers/duplicate_profiles_detected_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
before do
stub_sign_in(user)
stub_analytics
session[:duplicate_profile_ids] = profile2.id
end

describe '#show' do
Expand All @@ -21,11 +22,7 @@

context 'when user has an active duplicate profile confirmation' do
before do
DuplicateProfileConfirmation.create(
profile_id: user.active_profile.id,
confirmed_at: Time.zone.now,
duplicate_profile_ids: [profile2.id],
)
allow(controller).to receive(:user_session).and_return(session)
end

it 'renders the show template' do
Expand All @@ -34,7 +31,8 @@
end

it 'initializes the DuplicateProfilesDetectedPresenter' do
expect(DuplicateProfilesDetectedPresenter).to receive(:new).with(user: user)
expect(DuplicateProfilesDetectedPresenter).to receive(:new)
.with(user: user, user_session: session)
get :show
end

Expand All @@ -50,11 +48,7 @@

describe '#do_not_recognize_profiles' do
before do
@dupe_profile_confirmation = DuplicateProfileConfirmation.create(
profile_id: user.active_profile.id,
confirmed_at: Time.zone.now,
duplicate_profile_ids: [profile2.id],
)
allow(controller).to receive(:user_session).and_return(session)
end

it 'logs an event' do
Expand All @@ -64,35 +58,17 @@
:one_account_unknown_profile_detected,
)
end

it 'marks some accounts as not recognized' do
post :do_not_recognize_profiles
@dupe_profile_confirmation.reload
expect(@dupe_profile_confirmation.confirmed_all).to eq(false)
end
end

describe '#recognize_all_profiles' do
before do
@dupe_profile_confirmation = DuplicateProfileConfirmation.create(
profile_id: user.active_profile.id,
confirmed_at: Time.zone.now,
duplicate_profile_ids: [profile2.id],
)
allow(controller).to receive(:user_session).and_return(session)
end

it 'logs an analytics event' do
post :recognize_all_profiles
expect(@analytics).to have_logged_event
end

it 'marks profile dupe confirmation as recognized' do
post :recognize_all_profiles

@dupe_profile_confirmation.reload

expect(@dupe_profile_confirmation.confirmed_all).to eq(true)
end
end

describe '#redirect_unless_user_has_active_duplicate_profile_confirmation' do
Expand Down
4 changes: 3 additions & 1 deletion spec/jobs/resolution_proofing_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@

context 'when the SSN is not unique' do
before do
create(:profile, pii: Idp::Constants::MOCK_IDV_APPLICANT_WITH_SSN)
allow(IdentityConfig.store).to receive(:eligible_one_account_providers)
.and_return(['urn:gov:gsa:openidconnect:inactive:sp:test'])
create(:profile, :facial_match_proof, pii: Idp::Constants::MOCK_IDV_APPLICANT_WITH_SSN)
end

it 'sets ssn_is_unique: false on the result' do
Expand Down
43 changes: 15 additions & 28 deletions spec/presenters/duplicate_profiles_detected_presenter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,15 @@

RSpec.describe DuplicateProfilesDetectedPresenter do
let(:user) { create(:user, :proofed_with_selfie) }
let(:presenter) { described_class.new(user: user) }
let(:user_session) { {} }
let(:presenter) { described_class.new(user: user, user_session: user_session) }
let(:profile2) { create(:profile, :facial_match_proof) }

before do
DuplicateProfileConfirmation.create(
profile_id: user.active_profile.id,
confirmed_at: Time.zone.now,
duplicate_profile_ids: [profile2.id],
)
end

describe '#duplicate_profiles' do
context 'when multiple duplicate profiles were found for user' do
let(:profile3) { create(:profile, :facial_match_proof) }

before do
confirmation = DuplicateProfileConfirmation.find_by(
profile_id: user.active_profile.id,
)
confirmation.update!(
duplicate_profile_ids: [profile2.id, profile3.id],
)
user_session[:duplicate_profile_ids] = [profile2.id, profile3.id]
end

it 'should return multiple elements' do
Expand All @@ -32,6 +19,9 @@
end

context 'when a single duplicate profiles were found for user' do
before do
user_session[:duplicate_profile_ids] = [profile2.id]
end
it 'should return singular element' do
expect(presenter.duplicate_profiles.count).to eq(1)
end
Expand All @@ -43,12 +33,7 @@
let(:profile3) { create(:profile, :facial_match_proof) }

before do
confirmation = DuplicateProfileConfirmation.find_by(
profile_id: user.active_profile.id,
)
confirmation.update!(
duplicate_profile_ids: [profile2.id, profile3.id],
)
user_session[:duplicate_profile_ids] = [profile2.id, profile3.id]
end

it 'should return plural text' do
Expand All @@ -58,6 +43,9 @@
end

context 'when a single duplicate profiles were found for user' do
before do
user_session[:duplicate_profile_ids] = [profile2.id]
end
it 'should return singular text' do
expect(presenter.recognize_all_profiles)
.to eq(I18n.t('duplicate_profiles_detected.yes_single'))
Expand All @@ -70,12 +58,7 @@
let(:profile3) { create(:profile, :facial_match_proof) }

before do
confirmation = DuplicateProfileConfirmation.find_by(
profile_id: user.active_profile.id,
)
confirmation.update!(
duplicate_profile_ids: [profile2.id, profile3.id],
)
user_session[:duplicate_profile_ids] = [profile2.id, profile3.id]
end

it 'should return multiple text' do
Expand All @@ -85,6 +68,10 @@
end

context 'when a single duplicate profiles were found for user' do
before do
user_session[:duplicate_profile_ids] = [profile2.id]
end

it 'should return singular text' do
expect(presenter.dont_recognize_some_profiles)
.to eq(I18n.t('duplicate_profiles_detected.no_recognize_single'))
Expand Down
Loading