Skip to content
Merged
26 changes: 19 additions & 7 deletions app/forms/idv/api_image_upload_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def post_images_to_client
back_image: back_image_bytes,
selfie_image: liveness_checking_required ? selfie_image_bytes : nil,
image_source: image_source,
images_cropped: acuant_sdk_autocaptured_id?,
user_uuid: user_uuid,
uuid_prefix: uuid_prefix,
liveness_checking_required: liveness_checking_required,
Expand Down Expand Up @@ -205,7 +206,7 @@ def determine_response(form_response:, client_response:, doc_pii_response:)
end

def image_source
if acuant_sdk_capture?
if acuant_sdk_captured_id?
DocAuth::ImageSources::ACUANT_SDK
else
DocAuth::ImageSources::UNKNOWN
Expand Down Expand Up @@ -251,7 +252,7 @@ def validate_images
end

if !IdentityConfig.store.doc_auth_selfie_desktop_test_mode &&
liveness_checking_required && !acuant_sdk_capture?
liveness_checking_required && !acuant_sdk_captured?
errors.add(
:selfie, t('doc_auth.errors.not_a_file'),
type: :not_a_file
Expand Down Expand Up @@ -378,12 +379,23 @@ def acuant_sdk_upgrade_ab_test_data
}
end

def acuant_sdk_capture?
def acuant_sdk_captured?
acuant_sdk_captured_id? &&
(liveness_checking_required ? acuant_sdk_captured_selfie? : true)
end

def acuant_sdk_captured_id?
image_metadata.dig(:front, :source) == Idp::Constants::Vendors::ACUANT &&
image_metadata.dig(:back, :source) == Idp::Constants::Vendors::ACUANT &&
(liveness_checking_required ?
image_metadata.dig(:selfie, :source) == Idp::Constants::Vendors::ACUANT :
true)
image_metadata.dig(:back, :source) == Idp::Constants::Vendors::ACUANT
end

def acuant_sdk_captured_selfie?
image_metadata.dig(:selfie, :source) == Idp::Constants::Vendors::ACUANT
end

def acuant_sdk_autocaptured_id?
image_metadata.dig(:front, :acuantCaptureMode) == 'AUTO' &&
image_metadata.dig(:back, :acuantCaptureMode) == 'AUTO'
end

def image_metadata
Expand Down
1 change: 1 addition & 0 deletions app/services/doc_auth/acuant/acuant_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def post_images(
front_image:,
back_image:,
image_source:,
images_cropped: false,
Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, I don't think we need to update the AcuantClient, since we're already planning on removing it.

Copy link
Contributor Author

@amirbey amirbey Feb 28, 2024

Choose a reason for hiding this comment

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

@eileen-nava - i understand that we are not currently using acuant ... however, the the post_images method is polymorphic and wherever defined I think the signature should match. if acuant will be removed in a future sprint, I am missing the downside here 🤔

user_uuid: nil,
uuid_prefix: nil,
selfie_image: nil,
Expand Down
2 changes: 2 additions & 0 deletions app/services/doc_auth/lexis_nexis/lexis_nexis_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def post_images(
back_image:,
selfie_image: nil,
image_source: nil,
images_cropped: false,
user_uuid: nil,
uuid_prefix: nil,
liveness_checking_required: false
Expand All @@ -29,6 +30,7 @@ def post_images(
back_image: back_image,
selfie_image: selfie_image,
image_source: image_source,
images_cropped: images_cropped,
liveness_checking_required: liveness_checking_required,
).fetch
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ def initialize(
back_image:,
selfie_image: nil,
image_source: nil,
images_cropped: false,
liveness_checking_required: false
)
super(config: config, user_uuid: user_uuid, uuid_prefix: uuid_prefix)
@front_image = front_image
@back_image = back_image
@selfie_image = selfie_image
@image_source = image_source
@images_cropped = images_cropped
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Would it be worth adding an attr_reader for @images_cropped? Then you could just call images_cropped on line 75.

Copy link
Contributor

@dawei-nava dawei-nava Feb 28, 2024

Choose a reason for hiding this comment

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

@eileen-nava , if this prop not used by other classes, then I guess it's ok to use prop directly(especially not accessed multiple places in the owning class)?

Copy link
Contributor

Choose a reason for hiding this comment

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

@dawei-nava Hmmm, that's a good point. It does look like front_image, back_image, selfie_image, and liveness_checking_required are all accessed once in the owning class, too.

# when set to required, be sure to pass in selfie_image
@liveness_checking_required = liveness_checking_required
end
Expand Down Expand Up @@ -70,7 +72,7 @@ def password
end

def workflow
if acuant_sdk_source?
if @images_cropped
include_liveness? ?
config.trueid_liveness_nocropping_workflow :
config.trueid_noliveness_nocropping_workflow
Expand Down
1 change: 1 addition & 0 deletions app/services/doc_auth/mock/doc_auth_mock_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def post_images(
back_image:,
selfie_image: nil,
image_source: nil,
images_cropped: false,
user_uuid: nil,
uuid_prefix: nil,
liveness_checking_required: false
Expand Down
3 changes: 3 additions & 0 deletions spec/controllers/idv/image_uploads_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@
user_uuid: an_instance_of(String),
uuid_prefix: nil,
liveness_checking_required: true,
images_cropped: false,
).and_call_original

action
Expand All @@ -390,6 +391,7 @@
user_uuid: an_instance_of(String),
uuid_prefix: nil,
liveness_checking_required: false,
images_cropped: false,
).and_call_original

action
Expand Down Expand Up @@ -1288,6 +1290,7 @@
user_uuid: an_instance_of(String),
uuid_prefix: nil,
liveness_checking_required: true,
images_cropped: false,
).and_call_original

action
Expand Down
58 changes: 37 additions & 21 deletions spec/forms/idv/api_image_upload_form_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
ActionController::Parameters.new(
{
front: front_image,
front_image_metadata: front_image_metadata,
front_image_metadata: front_image_metadata.to_json,
back: back_image,
back_image_metadata: back_image_metadata,
back_image_metadata: back_image_metadata.to_json,
selfie: selfie_image,
selfie_image_metadata: selfie_image_metadata,
selfie_image_metadata: selfie_image_metadata.to_json,
document_capture_session_uuid: document_capture_session_uuid,
}.compact,
),
Expand All @@ -29,10 +29,10 @@
let(:selfie_image) { nil }
let(:liveness_checking_required) { false }
let(:front_image_metadata) do
{ width: 40, height: 40, mimeType: 'image/png', source: 'upload' }.to_json
{ width: 40, height: 40, mimeType: 'image/png', source: 'upload' }
end
let(:back_image_metadata) do
{ width: 20, height: 20, mimeType: 'image/png', source: 'upload' }.to_json
{ width: 20, height: 20, mimeType: 'image/png', source: 'upload' }
end
let(:selfie_image_metadata) { nil }
let!(:document_capture_session) { DocumentCaptureSession.create!(user: create(:user)) }
Expand Down Expand Up @@ -95,7 +95,7 @@

context 'validates image source' do
let(:selfie_image_metadata) do
{ width: 40, height: 40, mimeType: 'image/png', source: 'acuant' }.to_json
{ width: 40, height: 40, mimeType: 'image/png', source: 'acuant' }
end
before do
allow(IdentityConfig.store).to receive(:doc_auth_selfie_desktop_test_mode).
Expand All @@ -110,18 +110,18 @@

context 'images sourced by acuant sdk' do
let(:front_image_metadata) do
{ width: 40, height: 40, mimeType: 'image/png', source: 'acuant' }.to_json
{ width: 40, height: 40, mimeType: 'image/png', source: 'acuant' }
end
let(:back_image_metadata) do
{ width: 20, height: 20, mimeType: 'image/png', source: 'acuant' }.to_json
{ width: 20, height: 20, mimeType: 'image/png', source: 'acuant' }
end
it 'is valid' do
expect(form.valid?).to eq(true)
end

context 'selfie is uploaded' do
let(:selfie_image_metadata) do
{ width: 40, height: 40, mimeType: 'image/png', source: 'upload' }.to_json
{ width: 40, height: 40, mimeType: 'image/png', source: 'upload' }
end
it 'is invalid' do
expect(form.valid?).to eq(false)
Expand Down Expand Up @@ -243,7 +243,7 @@
let(:back_image) { DocAuthImageFixtures.portrait_match_success_yaml }
let(:selfie_image) { DocAuthImageFixtures.selfie_image_multipart }
let(:selfie_image_metadata) do
{ width: 10, height: 10, mimeType: 'image/png', source: 'upload' }.to_json
{ width: 10, height: 10, mimeType: 'image/png', source: 'upload' }
end

it 'logs analytics' do
Expand Down Expand Up @@ -697,17 +697,18 @@
describe 'image source' do
let(:source) { nil }
let(:front_image_metadata) do
{ width: 40, height: 40, mimeType: 'image/png', source: source }.to_json
{ width: 40, height: 40, mimeType: 'image/png', source: source }.compact
end
let(:back_image_metadata) do
{ width: 20, height: 20, mimeType: 'image/png', source: source }.to_json
{ width: 20, height: 20, mimeType: 'image/png', source: source }.compact
end
let(:image_source) { nil }
let(:images_cropped) { false }

before do
expect_any_instance_of(DocAuth::Mock::DocAuthMockClient).
to receive(:post_images).
with(hash_including(image_source: image_source)).
with(hash_including(image_source: image_source, images_cropped: images_cropped)).
and_call_original
end

Expand All @@ -723,7 +724,7 @@
context 'mixed sources' do
let(:source) { 'upload' }
let(:back_image_metadata) do
{ width: 20, height: 20, mimeType: 'image/png', source: 'acuant' }.to_json
{ width: 20, height: 20, mimeType: 'image/png', source: 'acuant' }
end
let(:image_source) { DocAuth::ImageSources::UNKNOWN }

Expand All @@ -736,16 +737,28 @@
let(:source) { 'acuant' }
let(:image_source) { DocAuth::ImageSources::ACUANT_SDK }

it 'sets image source to acuant sdk' do
form.submit
context 'when both images are captured via autocapture' do
let(:images_cropped) { true }
before do
front_image_metadata[:acuantCaptureMode] = 'AUTO'
back_image_metadata[:acuantCaptureMode] = 'AUTO'
end

it 'sets image source to acuant sdk' do
form.submit
end
end

context 'selfie is submitted' do
let(:liveness_checking_required) { true }
let(:selfie_image) { DocAuthImageFixtures.selfie_image_multipart }
context 'captured with acuant sdk' do
let(:selfie_image_metadata) do
{ width: 10, height: 10, mimeType: 'image/png', source: source }.to_json
{ width: 10, height: 10, mimeType: 'image/png', source: source }
end

before do
front_image_metadata.merge!(acuantCaptureMode: 'AUTO')
end

it 'sets image source to acuant sdk' do
Expand All @@ -755,11 +768,14 @@

context 'add using file upload' do
let(:selfie_image_metadata) do
{ width: 10, height: 10, mimeType: 'image/png', source: 'upload' }.to_json
{ width: 10, height: 10, mimeType: 'image/png', source: 'upload' }
end
let(:image_source) { DocAuth::ImageSources::UNKNOWN }

it 'sets image source to unknown' do
before do
back_image_metadata.merge!(acuantCaptureMode: 'AUTO')
end

it 'sets image source to acuant sdk' do
form.submit
end
end
Expand All @@ -768,7 +784,7 @@

context 'malformed image metadata' do
let(:source) { 'upload' }
let(:front_image_metadata) { nil.to_json }
let(:front_image_metadata) { nil }
let(:image_source) { DocAuth::ImageSources::UNKNOWN }

it 'sets image source to unknown' do
Expand Down
Loading