From 142f596402e95f5cfd64f1927243d34d0e486953 Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 12:36:14 -0700 Subject: [PATCH 01/12] Remove `FeatureManagement.document_capture_async_uploads_enabled?` method and specs Co-authored-by: John Maxwell --- .../idv/shared/_document_capture.html.erb | 4 +-- lib/feature_management.rb | 4 --- .../idv/document_capture_controller_spec.rb | 2 -- .../document_capture_controller_spec.rb | 3 -- spec/lib/feature_management_spec.rb | 14 -------- .../shared/_document_capture.html.erb_spec.rb | 32 ------------------- 6 files changed, 1 insertion(+), 58 deletions(-) diff --git a/app/views/idv/shared/_document_capture.html.erb b/app/views/idv/shared/_document_capture.html.erb index 17a14a21d83..b4915809d25 100644 --- a/app/views/idv/shared/_document_capture.html.erb +++ b/app/views/idv/shared/_document_capture.html.erb @@ -18,9 +18,7 @@ step: :document_capture, ), document_capture_session_uuid: document_capture_session_uuid, - endpoint: FeatureManagement.document_capture_async_uploads_enabled? ? - api_verify_v2_document_capture_url : - api_verify_images_url, + endpoint: api_verify_images_url, status_endpoint: nil, glare_threshold: IdentityConfig.store.doc_auth_client_glare_threshold, sharpness_threshold: IdentityConfig.store.doc_auth_client_sharpness_threshold, diff --git a/lib/feature_management.rb b/lib/feature_management.rb index ca69bdf75e7..961a1ad2dc5 100644 --- a/lib/feature_management.rb +++ b/lib/feature_management.rb @@ -105,10 +105,6 @@ def self.doc_capture_polling_enabled? IdentityConfig.store.doc_capture_polling_enabled end - def self.document_capture_async_uploads_enabled? - IdentityConfig.store.doc_auth_enable_presigned_s3_urls - end - def self.otp_expired_redirect_enabled? IdentityConfig.store.allow_otp_countdown_expired_redirect end diff --git a/spec/controllers/idv/document_capture_controller_spec.rb b/spec/controllers/idv/document_capture_controller_spec.rb index 0a78914e78a..f9cdbfca38e 100644 --- a/spec/controllers/idv/document_capture_controller_spec.rb +++ b/spec/controllers/idv/document_capture_controller_spec.rb @@ -117,8 +117,6 @@ end it 'does not raise an exception when stored_result is nil' do - allow(FeatureManagement).to receive(:document_capture_async_uploads_enabled?). - and_return(false) allow(subject).to receive(:stored_result).and_return(nil) put :update end diff --git a/spec/controllers/idv/hybrid_mobile/document_capture_controller_spec.rb b/spec/controllers/idv/hybrid_mobile/document_capture_controller_spec.rb index 1db190c44f2..bebc780ddf1 100644 --- a/spec/controllers/idv/hybrid_mobile/document_capture_controller_spec.rb +++ b/spec/controllers/idv/hybrid_mobile/document_capture_controller_spec.rb @@ -146,9 +146,6 @@ end it 'does not raise an exception when stored_result is nil' do - allow(FeatureManagement).to receive(:document_capture_async_uploads_enabled?). - and_return(false) - allow(subject).to receive(:stored_result).and_return(nil) put :update diff --git a/spec/lib/feature_management_spec.rb b/spec/lib/feature_management_spec.rb index 3a35ef7e26f..f01287d1dd0 100644 --- a/spec/lib/feature_management_spec.rb +++ b/spec/lib/feature_management_spec.rb @@ -311,20 +311,6 @@ end end - describe '#document_capture_async_uploads_enabled?' do - it 'returns true when IdentityConfig presigned S3 URL setting is true' do - allow(IdentityConfig.store).to receive(:doc_auth_enable_presigned_s3_urls) { true } - - expect(FeatureManagement.document_capture_async_uploads_enabled?).to eq(true) - end - - it 'returns false when IdentityConfig presigned S3 URL setting is false' do - allow(IdentityConfig.store).to receive(:doc_auth_enable_presigned_s3_urls) { false } - - expect(FeatureManagement.document_capture_async_uploads_enabled?).to eq(false) - end - end - describe 'log_to_stdout?' do context 'outside the test environment' do before { allow(Rails.env).to receive(:test?).and_return(false) } diff --git a/spec/views/idv/shared/_document_capture.html.erb_spec.rb b/spec/views/idv/shared/_document_capture.html.erb_spec.rb index 5fa68c60112..a0a8c3c9891 100644 --- a/spec/views/idv/shared/_document_capture.html.erb_spec.rb +++ b/spec/views/idv/shared/_document_capture.html.erb_spec.rb @@ -3,7 +3,6 @@ describe 'idv/shared/_document_capture.html.erb' do include Devise::Test::ControllerHelpers - let(:async_uploads_enabled) { false } let(:document_capture_session_uuid) { nil } let(:sp_name) { nil } let(:sp_issuer) { nil } @@ -28,8 +27,6 @@ allow(view).to receive(:decorated_session).and_return(decorated_session) allow(view).to receive(:url_for).and_return('https://example.com/') - allow(FeatureManagement).to receive(:document_capture_async_uploads_enabled?). - and_return(async_uploads_enabled) allow(Idv::InPersonConfig).to receive(:enabled_for_issuer?) do |issuer| if issuer.nil? in_person_proofing_enabled @@ -57,35 +54,6 @@ } end - describe 'async upload urls' do - context 'when async upload is disabled' do - let(:async_uploads_enabled) { false } - - it 'does not modify CSP connect_src headers' do - render_partial - - connect_src = controller.request.content_security_policy.connect_src - expect(connect_src).to eq( - ["'self'", '*.nr-data.net'], - ) - end - end - - context 'when async upload are enabled' do - let(:async_uploads_enabled) { true } - let(:front_image_upload_url) { 'https://s3.example.com/bucket/a?X-Amz-Security-Token=UAOL2' } - let(:back_image_upload_url) { 'https://s3.example.com/bucket/b?X-Amz-Security-Token=UAOL2' } - - it 'does modifies CSP connect_src headers to include upload urls' do - render_partial - - connect_src = controller.request.content_security_policy.connect_src - expect(connect_src).to include('https://s3.example.com/bucket/a') - expect(connect_src).to include('https://s3.example.com/bucket/b') - end - end - end - describe 'in person url' do context 'when in person proofing is disabled' do let(:in_person_proofing_enabled) { false } From 2cdeac69ca64342b8b6715027e6a46d0a17d73ba Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 13:00:19 -0700 Subject: [PATCH 02/12] Remove IdentityConfig.store.doc_auth_enable_presigned_s3_urls --- config/application.yml.default | 1 - lib/identity_config.rb | 1 - spec/features/idv/doc_auth/document_capture_spec.rb | 3 --- spec/features/idv/proofing_components_spec.rb | 3 --- 4 files changed, 8 deletions(-) diff --git a/config/application.yml.default b/config/application.yml.default index 3092565687a..e25143cd3e9 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -86,7 +86,6 @@ doc_auth_extend_timeout_by_minutes: 40 doc_capture_polling_enabled: true doc_auth_client_glare_threshold: 50 doc_auth_client_sharpness_threshold: 50 -doc_auth_enable_presigned_s3_urls: false doc_auth_s3_request_timeout: 5 doc_auth_error_dpi_threshold: 290 doc_auth_error_glare_threshold: 40 diff --git a/lib/identity_config.rb b/lib/identity_config.rb index 14188c0b757..af2cdb22aa0 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -156,7 +156,6 @@ def self.build_store(config_map) config.add(:doc_auth_attempt_window_in_minutes, type: :integer) config.add(:doc_auth_client_glare_threshold, type: :integer) config.add(:doc_auth_client_sharpness_threshold, type: :integer) - config.add(:doc_auth_enable_presigned_s3_urls, type: :boolean) config.add(:doc_auth_error_dpi_threshold, type: :integer) config.add(:doc_auth_error_glare_threshold, type: :integer) config.add(:doc_auth_error_sharpness_threshold, type: :integer) diff --git a/spec/features/idv/doc_auth/document_capture_spec.rb b/spec/features/idv/doc_auth/document_capture_spec.rb index 7a1fb912452..873ab3592fa 100644 --- a/spec/features/idv/doc_auth/document_capture_spec.rb +++ b/spec/features/idv/doc_auth/document_capture_spec.rb @@ -7,12 +7,9 @@ let(:max_attempts) { IdentityConfig.store.doc_auth_max_attempts } let(:user) { user_with_2fa } - let(:doc_auth_enable_presigned_s3_urls) { false } let(:fake_analytics) { FakeAnalytics.new } let(:sp_name) { 'Test SP' } before do - allow(IdentityConfig.store).to receive(:doc_auth_enable_presigned_s3_urls). - and_return(doc_auth_enable_presigned_s3_urls) allow(Identity::Hostdata::EC2).to receive(:load). and_return(OpenStruct.new(region: 'us-west-2', account_id: '123456789')) allow_any_instance_of(ApplicationController).to receive(:analytics).and_return(fake_analytics) diff --git a/spec/features/idv/proofing_components_spec.rb b/spec/features/idv/proofing_components_spec.rb index 6cab5c19fd9..3bd39f0e92d 100644 --- a/spec/features/idv/proofing_components_spec.rb +++ b/spec/features/idv/proofing_components_spec.rb @@ -12,8 +12,6 @@ before do allow(IdentityConfig.store).to receive(:ruby_workers_idv_enabled). and_return(ruby_workers_idv_enabled) - allow(IdentityConfig.store).to receive(:doc_auth_enable_presigned_s3_urls). - and_return(doc_auth_enable_presigned_s3_urls) visit_idp_from_sp_with_ial2(:oidc) register_user(email) @@ -28,7 +26,6 @@ context 'sync proofing', js: true do let(:ruby_workers_idv_enabled) { false } - let(:doc_auth_enable_presigned_s3_urls) { false } it 'records proofing components' do proofing_components = user.active_profile.proofing_components From afecd19cbed2e3faeadf6479613484df2f754a18 Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 13:59:18 -0700 Subject: [PATCH 03/12] Remove initializer to guard against turning on async doc capture --- config/initializers/async_exception.rb | 6 ----- .../initializers/async_exception_spec.rb | 27 ------------------- 2 files changed, 33 deletions(-) delete mode 100644 config/initializers/async_exception.rb delete mode 100644 spec/config/initializers/async_exception_spec.rb diff --git a/config/initializers/async_exception.rb b/config/initializers/async_exception.rb deleted file mode 100644 index 87ceeb0f116..00000000000 --- a/config/initializers/async_exception.rb +++ /dev/null @@ -1,6 +0,0 @@ -# Guards against accidentally turning on the broken asynchronous document capture -# feature in production. If that feature ever gets fixed, delete this file. - -if Rails.env.production? && IdentityConfig.store.doc_auth_enable_presigned_s3_urls - raise 'Cannot initialize identity-idp project with async upload turned on' -end diff --git a/spec/config/initializers/async_exception_spec.rb b/spec/config/initializers/async_exception_spec.rb deleted file mode 100644 index 9159d83b333..00000000000 --- a/spec/config/initializers/async_exception_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'rails_helper' - -RSpec.describe 'async_error' do - let(:enabled) { false } - subject do - load Rails.root.join('config', 'initializers', 'async_exception.rb').to_s - end - - before do - allow(Rails.env).to receive(:production?).and_return(true) - allow(IdentityConfig.store).to receive(:doc_auth_enable_presigned_s3_urls).and_return(enabled) - end - - context 'async uploads are not enabled' do - it 'does not raise an error' do - expect { subject }.not_to raise_error - end - end - - context 'async uploads are enabled' do - let(:enabled) { true } - - it 'does raise an error' do - expect { subject }.to raise_error - end - end -end From e4a70a3945051a61905f92bfaca143253a91c614 Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 14:14:02 -0700 Subject: [PATCH 04/12] Remove ImageUploadPresignedUrlGenerator and usage --- .../idv/document_capture_controller.rb | 11 ---- .../document_capture_controller.rb | 10 --- app/helpers/csp_helper.rb | 11 ---- .../image_upload_presigned_url_generator.rb | 22 ------- .../idv/doc_auth/document_capture.html.erb | 2 - app/views/idv/document_capture/show.html.erb | 2 - .../document_capture/show.html.erb | 2 - .../idv/shared/_document_capture.html.erb | 7 --- ...age_upload_presigned_url_generator_spec.rb | 61 ------------------- .../shared/_document_capture.html.erb_spec.rb | 4 -- 10 files changed, 132 deletions(-) delete mode 100644 app/helpers/csp_helper.rb delete mode 100644 app/services/image_upload_presigned_url_generator.rb delete mode 100644 spec/services/image_upload_presigned_url_generator_spec.rb diff --git a/app/controllers/idv/document_capture_controller.rb b/app/controllers/idv/document_capture_controller.rb index 1da8c6a0642..50f62cda427 100644 --- a/app/controllers/idv/document_capture_controller.rb +++ b/app/controllers/idv/document_capture_controller.rb @@ -36,22 +36,11 @@ def update end def extra_view_variables - url_builder = ImageUploadPresignedUrlGenerator.new - { document_capture_session_uuid: flow_session[:document_capture_session_uuid], flow_path: 'standard', sp_name: decorated_session.sp_name, failure_to_proof_url: return_to_sp_failure_to_proof_url(step: 'document_capture'), - - front_image_upload_url: url_builder.presigned_image_upload_url( - image_type: 'front', - transaction_id: flow_session[:document_capture_session_uuid], - ), - back_image_upload_url: url_builder.presigned_image_upload_url( - image_type: 'back', - transaction_id: flow_session[:document_capture_session_uuid], - ), }.merge( acuant_sdk_upgrade_a_b_testing_variables, in_person_cta_variant_testing_variables, diff --git a/app/controllers/idv/hybrid_mobile/document_capture_controller.rb b/app/controllers/idv/hybrid_mobile/document_capture_controller.rb index 80ffa3c2f1f..2ae28c72c13 100644 --- a/app/controllers/idv/hybrid_mobile/document_capture_controller.rb +++ b/app/controllers/idv/hybrid_mobile/document_capture_controller.rb @@ -36,20 +36,10 @@ def update end def extra_view_variables - url_builder = ImageUploadPresignedUrlGenerator.new - { flow_path: 'hybrid', document_capture_session_uuid: document_capture_session_uuid, failure_to_proof_url: return_to_sp_failure_to_proof_url(step: 'document_capture'), - front_image_upload_url: url_builder.presigned_image_upload_url( - image_type: 'front', - transaction_id: document_capture_session_uuid, - ), - back_image_upload_url: url_builder.presigned_image_upload_url( - image_type: 'back', - transaction_id: document_capture_session_uuid, - ), }.merge( native_camera_ab_testing_variables, acuant_sdk_upgrade_a_b_testing_variables, diff --git a/app/helpers/csp_helper.rb b/app/helpers/csp_helper.rb deleted file mode 100644 index 8c790226aad..00000000000 --- a/app/helpers/csp_helper.rb +++ /dev/null @@ -1,11 +0,0 @@ -module CspHelper - def add_document_capture_image_urls_to_csp(request, urls) - cleaned_urls = urls.compact.map do |url| - URI(url).tap { |uri| uri.query = nil }.to_s - end - - policy = request.content_security_policy.clone - policy.connect_src(*policy.connect_src, *cleaned_urls) - request.content_security_policy = policy - end -end diff --git a/app/services/image_upload_presigned_url_generator.rb b/app/services/image_upload_presigned_url_generator.rb deleted file mode 100644 index 7e00190eff4..00000000000 --- a/app/services/image_upload_presigned_url_generator.rb +++ /dev/null @@ -1,22 +0,0 @@ -class ImageUploadPresignedUrlGenerator - include AwsS3Helper - - def presigned_image_upload_url(image_type:, transaction_id:) - keyname = "#{transaction_id}-#{image_type}" - - if !IdentityConfig.store.doc_auth_enable_presigned_s3_urls - nil - elsif !Identity::Hostdata.in_datacenter? - Rails.application.routes.url_helpers.test_fake_s3_url(key: keyname) - else - s3_presigned_url( - bucket_prefix: bucket_prefix, - keyname: keyname, - ).to_s - end - end - - def bucket_prefix - 'login-gov-idp-doc-capture'.freeze - end -end diff --git a/app/views/idv/doc_auth/document_capture.html.erb b/app/views/idv/doc_auth/document_capture.html.erb index 19a7fbf9045..3fa7953f15a 100644 --- a/app/views/idv/doc_auth/document_capture.html.erb +++ b/app/views/idv/doc_auth/document_capture.html.erb @@ -4,8 +4,6 @@ flow_path: 'standard', sp_name: decorated_session.sp_name, failure_to_proof_url: idv_doc_auth_return_to_sp_url, - front_image_upload_url: front_image_upload_url, - back_image_upload_url: back_image_upload_url, acuant_sdk_upgrade_a_b_testing_enabled: acuant_sdk_upgrade_a_b_testing_enabled, use_alternate_sdk: use_alternate_sdk, acuant_version: acuant_version, diff --git a/app/views/idv/document_capture/show.html.erb b/app/views/idv/document_capture/show.html.erb index d760a1cc412..f43089f9d80 100644 --- a/app/views/idv/document_capture/show.html.erb +++ b/app/views/idv/document_capture/show.html.erb @@ -4,8 +4,6 @@ flow_path: 'standard', sp_name: decorated_session.sp_name, failure_to_proof_url: failure_to_proof_url, - front_image_upload_url: front_image_upload_url, - back_image_upload_url: back_image_upload_url, acuant_sdk_upgrade_a_b_testing_enabled: acuant_sdk_upgrade_a_b_testing_enabled, use_alternate_sdk: use_alternate_sdk, acuant_version: acuant_version, diff --git a/app/views/idv/hybrid_mobile/document_capture/show.html.erb b/app/views/idv/hybrid_mobile/document_capture/show.html.erb index 864995c91eb..13a6e24ebb4 100644 --- a/app/views/idv/hybrid_mobile/document_capture/show.html.erb +++ b/app/views/idv/hybrid_mobile/document_capture/show.html.erb @@ -4,8 +4,6 @@ flow_path: 'hybrid', sp_name: decorated_session.sp_name, failure_to_proof_url: idv_doc_auth_return_to_sp_url, - front_image_upload_url: front_image_upload_url, - back_image_upload_url: back_image_upload_url, acuant_sdk_upgrade_a_b_testing_enabled: acuant_sdk_upgrade_a_b_testing_enabled, use_alternate_sdk: use_alternate_sdk, acuant_version: acuant_version, diff --git a/app/views/idv/shared/_document_capture.html.erb b/app/views/idv/shared/_document_capture.html.erb index b4915809d25..a4260ea0a6f 100644 --- a/app/views/idv/shared/_document_capture.html.erb +++ b/app/views/idv/shared/_document_capture.html.erb @@ -4,11 +4,6 @@ <%= tag.meta name: 'acuant-sdk-initialization-creds', content: IdentityConfig.store.acuant_sdk_initialization_creds %> <%= stylesheet_link_tag 'document-capture' %> <% end %> -<% add_document_capture_image_urls_to_csp( - request, - [front_image_upload_url, back_image_upload_url], - ) -%> <%= tag.div id: 'document-capture-form', data: { app_name: APP_NAME, liveness_required: nil, @@ -33,8 +28,6 @@ flow_path: flow_path, cancel_url: idv_cancel_path, failure_to_proof_url: failure_to_proof_url, - front_image_upload_url: front_image_upload_url, - back_image_upload_url: back_image_upload_url, idv_in_person_url: Idv::InPersonConfig.enabled_for_issuer?(decorated_session.sp_issuer) ? idv_in_person_url : nil, security_and_privacy_how_it_works_url: MarketingSite.security_and_privacy_how_it_works_url, in_person_cta_variant_testing_enabled: IdentityConfig.store.in_person_cta_variant_testing_enabled, diff --git a/spec/services/image_upload_presigned_url_generator_spec.rb b/spec/services/image_upload_presigned_url_generator_spec.rb deleted file mode 100644 index 665805a1842..00000000000 --- a/spec/services/image_upload_presigned_url_generator_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'rails_helper' - -RSpec.describe ImageUploadPresignedUrlGenerator do - include Rails.application.routes.url_helpers - - subject(:generator) { ImageUploadPresignedUrlGenerator.new } - - describe '#presigned_image_upload_url' do - subject(:presigned_image_upload_url) do - generator.presigned_image_upload_url(image_type: image_type, transaction_id: transaction_id) - end - - let(:image_type) { 'front' } - let(:transaction_id) { SecureRandom.uuid } - - before do - expect(IdentityConfig.store). - to receive(:doc_auth_enable_presigned_s3_urls).and_return(doc_auth_enable_presigned_s3_urls) - end - - context 'when doc_auth_enable_presigned_s3_urls is disabled' do - let(:doc_auth_enable_presigned_s3_urls) { false } - - it 'is nil' do - expect(presigned_image_upload_url).to eq(nil) - end - end - - context 'when doc_auth_enable_presigned_s3_urls is enabled' do - let(:doc_auth_enable_presigned_s3_urls) { true } - - before do - expect(Identity::Hostdata).to receive(:in_datacenter?).and_return(in_datacenter) - end - - context 'when run locally' do - let(:in_datacenter) { false } - - it 'is a local fake S3 URL' do - expect(presigned_image_upload_url). - to eq(test_fake_s3_url(key: "#{transaction_id}-#{image_type}")) - end - end - - context 'when run in the datacenter' do - let(:in_datacenter) { true } - - let(:real_s3_url) { 'https://s3.example.com/key/id/1234' } - - it 'is a real S3 url' do - # from aws_s3_helper - expect(generator).to receive(:s3_presigned_url). - with(hash_including(keyname: "#{transaction_id}-#{image_type}")). - and_return(real_s3_url) - - expect(presigned_image_upload_url).to eq(real_s3_url) - end - end - end - end -end diff --git a/spec/views/idv/shared/_document_capture.html.erb_spec.rb b/spec/views/idv/shared/_document_capture.html.erb_spec.rb index a0a8c3c9891..383fc251d97 100644 --- a/spec/views/idv/shared/_document_capture.html.erb_spec.rb +++ b/spec/views/idv/shared/_document_capture.html.erb_spec.rb @@ -10,8 +10,6 @@ let(:failure_to_proof_url) { return_to_sp_failure_to_proof_path } let(:in_person_proofing_enabled) { false } let(:in_person_proofing_enabled_issuer) { nil } - let(:front_image_upload_url) { nil } - let(:back_image_upload_url) { nil } let(:acuant_sdk_upgrade_a_b_testing_enabled) { false } let(:use_alternate_sdk) { false } let(:acuant_version) { '1.3.3.7' } @@ -44,8 +42,6 @@ sp_name: sp_name, flow_path: flow_path, failure_to_proof_url: failure_to_proof_url, - front_image_upload_url: front_image_upload_url, - back_image_upload_url: back_image_upload_url, acuant_sdk_upgrade_a_b_testing_enabled: acuant_sdk_upgrade_a_b_testing_enabled, use_alternate_sdk: use_alternate_sdk, acuant_version: acuant_version, From b547c78a2a28a06850b098e14d841fdcb3531392 Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 14:38:41 -0700 Subject: [PATCH 05/12] Remove AwsS3Helper and associated Identity::Hostdata::EC2 in specs --- app/helpers/aws_s3_helper.rb | 26 ----- .../idv/doc_auth_controller_spec.rb | 2 - .../idv/doc_auth/document_capture_spec.rb | 2 - .../idv/hybrid_mobile/hybrid_mobile_spec.rb | 2 - spec/helpers/aws_s3_helper_spec.rb | 99 ------------------- 5 files changed, 131 deletions(-) delete mode 100644 app/helpers/aws_s3_helper.rb delete mode 100644 spec/helpers/aws_s3_helper_spec.rb diff --git a/app/helpers/aws_s3_helper.rb b/app/helpers/aws_s3_helper.rb deleted file mode 100644 index f8dd7958718..00000000000 --- a/app/helpers/aws_s3_helper.rb +++ /dev/null @@ -1,26 +0,0 @@ -module AwsS3Helper - def s3_presigned_url(...) - URI.parse(s3_object(...).presigned_url(:put, expires_in: presigned_url_expiration_in_seconds)) - end - - def s3_resource - Aws::S3::Resource.new(region: Identity::Hostdata.aws_region) - rescue Aws::Sigv4::Errors::MissingCredentialsError => aws_error - Rails.logger.info "Aws Missing CredentialsError!\n" + aws_error.message - nil - end - - def s3_object(bucket_prefix:, keyname:) - raise(ArgumentError, 'keyname is required') if keyname.blank? - raise(ArgumentError, 'bucket_prefix is required') if bucket_prefix.blank? - return if !s3_resource - - s3_resource.bucket( - Identity::Hostdata.bucket_name("#{bucket_prefix}-#{Identity::Hostdata.env}"), - ).object(keyname) - end - - def presigned_url_expiration_in_seconds - IdentityConfig.store.session_total_duration_timeout_in_minutes.minutes.seconds.to_i - end -end diff --git a/spec/controllers/idv/doc_auth_controller_spec.rb b/spec/controllers/idv/doc_auth_controller_spec.rb index 85a90a18336..50a1b1e45d4 100644 --- a/spec/controllers/idv/doc_auth_controller_spec.rb +++ b/spec/controllers/idv/doc_auth_controller_spec.rb @@ -27,8 +27,6 @@ stub_sign_in(user) if user stub_analytics allow(@analytics).to receive(:track_event) - allow(Identity::Hostdata::EC2).to receive(:load). - and_return(OpenStruct.new(region: 'us-west-2', domain: 'example.com')) end describe 'unauthenticated' do diff --git a/spec/features/idv/doc_auth/document_capture_spec.rb b/spec/features/idv/doc_auth/document_capture_spec.rb index 873ab3592fa..bfc16edd4fb 100644 --- a/spec/features/idv/doc_auth/document_capture_spec.rb +++ b/spec/features/idv/doc_auth/document_capture_spec.rb @@ -10,8 +10,6 @@ let(:fake_analytics) { FakeAnalytics.new } let(:sp_name) { 'Test SP' } before do - allow(Identity::Hostdata::EC2).to receive(:load). - and_return(OpenStruct.new(region: 'us-west-2', account_id: '123456789')) allow_any_instance_of(ApplicationController).to receive(:analytics).and_return(fake_analytics) allow_any_instance_of(ServiceProviderSessionDecorator).to receive(:sp_name).and_return(sp_name) diff --git a/spec/features/idv/hybrid_mobile/hybrid_mobile_spec.rb b/spec/features/idv/hybrid_mobile/hybrid_mobile_spec.rb index 24b5557ad68..e444817f816 100644 --- a/spec/features/idv/hybrid_mobile/hybrid_mobile_spec.rb +++ b/spec/features/idv/hybrid_mobile/hybrid_mobile_spec.rb @@ -9,8 +9,6 @@ before do allow(FeatureManagement).to receive(:doc_capture_polling_enabled?).and_return(true) - allow(Identity::Hostdata::EC2).to receive(:load). - and_return(OpenStruct.new(region: 'us-west-2', account_id: '123456789')) end before do diff --git a/spec/helpers/aws_s3_helper_spec.rb b/spec/helpers/aws_s3_helper_spec.rb deleted file mode 100644 index 6cc61c46d10..00000000000 --- a/spec/helpers/aws_s3_helper_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -require 'rails_helper' -describe 'AwsS3Helper' do - let(:session_uuid) { SecureRandom.uuid } - let(:env) { 'dev' } - let(:account_id) { '123456789' } - let(:region) { 'us-west-2' } - let(:prefix) { 'login-gov-idp-doc-capture' } - let(:image_type) { 'front' } - let(:bucket) { "#{prefix}-#{env}.#{account_id}-#{region}" } - let(:query_keys) do - %w[ - X-Amz-Algorithm - X-Amz-Credential - X-Amz-Date - X-Amz-Expires - X-Amz-SignedHeaders - X-Amz-Signature - ] - end - - before do - allow(Identity::Hostdata::EC2).to receive(:load). - and_raise(Net::OpenTimeout) - end - - describe '#s3_presigned_url' do - let(:client_stub) { Aws::S3::Client.new(region: region, stub_responses: true) } - - before do - client_stub.stub_responses(:list_buckets, { buckets: [{ name: bucket }] }) - resource_stub = Aws::S3::Resource.new(client: client_stub) - - allow(Identity::Hostdata).to receive(:env).and_return(env) - allow(Identity::Hostdata).to receive(:aws_region).and_return(region) - allow(Identity::Hostdata).to receive(:aws_account_id).and_return(account_id) - allow(helper).to receive(:s3_resource).and_return(resource_stub) - end - - it 'returns a URL' do - url = URI( - helper.s3_presigned_url( - bucket_prefix: prefix, - keyname: "#{session_uuid}-#{image_type}", - ), - ) - query = Hash[*url.query.split(/[&=]/)] - - expect(url.host).to eq("s3.#{region}.amazonaws.com") - expect(url.path).to eq("/#{bucket}/#{session_uuid}-#{image_type}") - expect(query['X-Amz-Algorithm']).to eq('AWS4-HMAC-SHA256') - expect(query.keys).to match_array(query_keys) - end - - it 'requires a keyname' do - expect { helper.s3_presigned_url(bucket_prefix: prefix, keyname: '') }. - to raise_error(ArgumentError, 'keyname is required') - end - - it 'requires a bucket_prefix' do - expect { helper.s3_presigned_url(bucket_prefix: '', keyname: 'image_type') }. - to raise_error(ArgumentError, 'bucket_prefix is required') - end - - it 'is created with an expiration' do - key = "#{session_uuid}-#{image_type}" - object = Aws::S3::Object.new(bucket_name: bucket, key: key, client: client_stub) - allow(helper).to receive(:s3_object).and_return(object) - expect(object).to receive(:presigned_url).with( - kind_of(Symbol), - hash_including(expires_in: helper.presigned_url_expiration_in_seconds), - ).and_call_original - - helper.s3_presigned_url( - bucket_prefix: prefix, - keyname: key, - ) - end - end - - describe '#s3_resource' do - context 'AWS credentials are not set' do - before do - allow(Identity::Hostdata).to receive(:aws_region).and_return(region) - allow(Aws::S3::Resource).to receive(:new). - and_raise(Aws::Sigv4::Errors::MissingCredentialsError, 'Credentials not set') - end - - it 'returns nil' do - expect(helper.s3_resource).to be_nil - end - end - end - - describe '#presigned_url_expiration_in_seconds' do - it 'returns a number' do - expect(helper.presigned_url_expiration_in_seconds).to be_a_kind_of(Numeric) - end - end -end From 43ed99c6f4f876e2bac307628c55e60af43be6b3 Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 14:48:44 -0700 Subject: [PATCH 06/12] Remove unused ApiDocumentVerificationStatusForm --- .../api_document_verification_status_form.rb | 53 ------------------- 1 file changed, 53 deletions(-) delete mode 100644 app/forms/idv/api_document_verification_status_form.rb diff --git a/app/forms/idv/api_document_verification_status_form.rb b/app/forms/idv/api_document_verification_status_form.rb deleted file mode 100644 index 414fa7e673b..00000000000 --- a/app/forms/idv/api_document_verification_status_form.rb +++ /dev/null @@ -1,53 +0,0 @@ -module Idv - class ApiDocumentVerificationStatusForm - include ActiveModel::Model - include ActionView::Helpers::TranslationHelper - - validate :timeout_error - validate :failed_result - validates_presence_of :document_capture_session - - def initialize(async_state:, document_capture_session:) - @async_state = async_state - @document_capture_session = document_capture_session - end - - def submit - FormResponse.new( - success: valid?, - errors: errors, - extra: { - remaining_attempts: remaining_attempts, - doc_auth_result: @async_state&.result&.[](:doc_auth_result), - }, - ) - end - - def remaining_attempts - return unless @document_capture_session - Throttle.new( - user: @document_capture_session.user, - throttle_type: :idv_doc_auth, - ).remaining_count - end - - def timeout_error - return unless @async_state.missing? - errors.add( - :timeout, t('errors.doc_auth.document_verification_timeout'), - type: :document_verification_timeout - ) - end - - def failed_result - return if !@async_state.done? || @async_state.result[:success] - @async_state.result[:errors].each do |key, error| - errors.add(key, error, type: error) - end - end - - private - - attr_reader :document_capture_session - end -end From 90a92b3978fec35973f90b0c4443d5e3408c3de4 Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 14:59:18 -0700 Subject: [PATCH 07/12] Remove Api::Verify::DocumentCaptureController and Forms::ApiDocumentVerificationForm --- .../api/verify/document_capture_controller.rb | 88 ----------- .../idv/api_document_verification_form.rb | 123 ---------------- config/routes.rb | 5 - .../document_capture_controller_spec.rb | 137 ------------------ .../api_document_verification_form_spec.rb | 115 --------------- 5 files changed, 468 deletions(-) delete mode 100644 app/controllers/api/verify/document_capture_controller.rb delete mode 100644 app/forms/idv/api_document_verification_form.rb delete mode 100644 spec/controllers/api/verify/document_capture_controller_spec.rb delete mode 100644 spec/forms/idv/api_document_verification_form_spec.rb diff --git a/app/controllers/api/verify/document_capture_controller.rb b/app/controllers/api/verify/document_capture_controller.rb deleted file mode 100644 index 1badfde7d0a..00000000000 --- a/app/controllers/api/verify/document_capture_controller.rb +++ /dev/null @@ -1,88 +0,0 @@ -module Api - module Verify - class DocumentCaptureController < BaseController - include ApplicationHelper - include EffectiveUser - - def create - result = Idv::ApiDocumentVerificationForm.new( - verify_params, - analytics: analytics, - irs_attempts_api_tracker: irs_attempts_api_tracker, - flow_path: params[:flow_path], - ).submit - - if result.success? - enqueue_job - - render json: { success: true, status: 'in_progress' }, status: :accepted - else - render_errors(result.errors) - end - end - - private - - def enqueue_job - verify_document_capture_session = DocumentCaptureSession. - find_by(uuid: params[:document_capture_session_uuid]) - verify_document_capture_session.requested_at = Time.zone.now - verify_document_capture_session.create_doc_auth_session - - applicant = { - user_uuid: effective_user.uuid, - uuid_prefix: current_sp&.app_id, - document_arguments: document_attributes, - } - Idv::Agent.new(applicant).proof_document( - verify_document_capture_session, - trace_id: amzn_trace_id, - image_metadata: image_metadata, - analytics_data: { - browser_attributes: analytics.browser_attributes, - }, - flow_path: params[:flow_path], - ) - nil - end - - def document_attributes - verify_params.slice( - :encryption_key, - :front_image_iv, - :back_image_iv, - :front_image_url, - :back_image_url, - ).to_h - end - - def verify_params - params.permit( - :encryption_key, - :front_image_iv, - :back_image_iv, - :front_image_url, - :back_image_url, - :document_capture_session_uuid, - :flow_path, - ) - end - - def image_metadata - params.permit(:front_image_metadata, :back_image_metadata). - to_h. - transform_values do |str| - JSON.parse(str, symbolize_names: true) - rescue JSON::ParserError - nil - end. - compact. - transform_keys { |key| key.gsub(/_image_metadata$/, '') } - end - - def user_authenticated_for_api? - !!effective_user - end - end - end -end diff --git a/app/forms/idv/api_document_verification_form.rb b/app/forms/idv/api_document_verification_form.rb deleted file mode 100644 index 83f6b9cc182..00000000000 --- a/app/forms/idv/api_document_verification_form.rb +++ /dev/null @@ -1,123 +0,0 @@ -module Idv - class ApiDocumentVerificationForm - include ActiveModel::Model - include ActionView::Helpers::TranslationHelper - - validates_presence_of :encryption_key - validate :validate_image_urls - validates_presence_of :document_capture_session - validates_presence_of :front_image_iv - validates_presence_of :back_image_iv - - validate :throttle_if_rate_limited - - def initialize( - params, - analytics:, - irs_attempts_api_tracker:, - flow_path: nil - ) - @params = params - @analytics = analytics - @irs_attempts_api_tracker = irs_attempts_api_tracker - @flow_path = flow_path - end - - def submit - increment_throttle! - - response = FormResponse.new( - success: valid?, - errors: errors, - extra: { - remaining_attempts: remaining_attempts, - flow_path: @flow_path, - }, - ) - - @analytics.idv_doc_auth_submitted_image_upload_form( - **response.to_h, - ) - - response - end - - def remaining_attempts - return unless document_capture_session - throttle.remaining_count - end - - def document_capture_session_uuid - params[:document_capture_session_uuid] - end - - def document_capture_session - @document_capture_session ||= DocumentCaptureSession.find_by( - uuid: document_capture_session_uuid, - ) - end - - private - - attr_reader :params - - def encryption_key - params[:encryption_key] - end - - def front_image_iv - params[:front_image_iv] - end - - def back_image_iv - params[:back_image_iv] - end - - def valid_url?(key) - uri = params[key] - parsed_uri = URI.parse(uri) - parsed_uri.scheme.present? && parsed_uri.host.present? - rescue URI::InvalidURIError - false - end - - def throttle_if_rate_limited - return unless @throttled - @analytics.throttler_rate_limit_triggered(throttle_type: :idv_doc_auth) - @irs_attempts_api_tracker.idv_document_upload_rate_limited - errors.add(:limit, t('errors.doc_auth.throttled_heading'), type: :throttled) - end - - def increment_throttle! - return unless document_capture_session - throttle.increment! - @throttled = throttle.throttled? - end - - def throttle - @throttle ||= Throttle.new( - user: document_capture_session.user, - throttle_type: :idv_doc_auth, - ) - end - - def validate_image_urls - unless valid_url?(:front_image_url) - errors.add( - :front_image_url, invalid_link, - type: :invalid_link - ) - end - unless valid_url?(:back_image_url) - errors.add( - :back_image_url, invalid_link, - type: :invalid_link - ) - end - end - - def invalid_link - t('doc_auth.errors.not_a_file') - end - end -end diff --git a/config/routes.rb b/config/routes.rb index 972a55e8161..686d061f278 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -390,11 +390,6 @@ post '/confirmations' => 'personal_key#update' end - namespace :api do - post '/verify/v2/document_capture' => 'verify/document_capture#create' - delete '/verify/v2/document_capture_errors' => 'verify/document_capture_errors#delete' - end - get '/account/verify' => 'idv/gpo_verify#index', as: :idv_gpo_verify post '/account/verify' => 'idv/gpo_verify#create' if FeatureManagement.gpo_verification_enabled? diff --git a/spec/controllers/api/verify/document_capture_controller_spec.rb b/spec/controllers/api/verify/document_capture_controller_spec.rb deleted file mode 100644 index fd398e70603..00000000000 --- a/spec/controllers/api/verify/document_capture_controller_spec.rb +++ /dev/null @@ -1,137 +0,0 @@ -require 'rails_helper' - -describe Api::Verify::DocumentCaptureController do - include PersonalKeyValidator - include SamlAuthHelper - - let(:encryption_key) { 'encryption-key' } - let(:front_image_url) { 'http://example.com/front' } - let(:front_image_iv) { 'front-iv' } - let(:back_image_url) { 'http://example.com/back' } - let(:back_image_iv) { 'back-iv' } - let(:front_image_metadata) do - { width: 40, height: 40, mimeType: 'image/png', source: 'upload' } - end - let(:back_image_metadata) do - { width: 20, height: 20, mimeType: 'image/png', source: 'upload' } - end - let(:image_metadata) { { front: front_image_metadata, back: back_image_metadata } } - let!(:document_capture_session) { DocumentCaptureSession.create!(user: create(:user)) } - let(:document_capture_session_uuid) { document_capture_session.uuid } - let(:password) { 'iambatman' } - let(:user) { create(:user, :fully_registered) } - let(:flow_path) { 'standard' } - let(:analytics_data) do - { browser_attributes: - { browser_bot: false, - browser_device_name: 'Unknown', - browser_mobile: false, - browser_name: 'Unknown Browser', - browser_platform_name: 'Unknown', - browser_platform_version: '0', - browser_version: '0.0', - user_agent: 'Rails Testing' } } - end - - before do - stub_sign_in(user) if user - end - - it 'extends behavior of base api class' do - expect(subject).to be_kind_of Api::Verify::BaseController - end - - describe '#create' do - it 'renders as bad request (400)' do - post :create - - expect(response.status).to eq(400) - end - - context 'signed out' do - let(:user) { nil } - - it 'renders as unauthorized (401)' do - post :create - - expect(response.status).to eq(401) - end - - context 'with hybrid effective user' do - before { session[:doc_capture_user_id] = create(:user).id } - - it 'renders as bad request (400)' do - post :create - - expect(response.status).to eq(400) - end - end - end - - context 'When user document is submitted to be verified' do - it 'returns inprogress status when create is called' do - agent = instance_double(Idv::Agent) - allow(Idv::Agent).to receive(:new).with( - { - user_uuid: user.uuid, - uuid_prefix: nil, - document_arguments: { - 'encryption_key' => encryption_key, - 'front_image_iv' => front_image_iv, - 'back_image_iv' => back_image_iv, - 'front_image_url' => front_image_url, - 'back_image_url' => back_image_url, - }, - }, - ).and_return(agent) - - expect(agent).to receive(:proof_document).with( - document_capture_session, - trace_id: nil, - image_metadata: image_metadata, - analytics_data: analytics_data, - flow_path: flow_path, - ) - - post :create, params: { - encryption_key: encryption_key, - front_image_iv: front_image_iv, - back_image_iv: back_image_iv, - front_image_url: front_image_url, - back_image_url: back_image_url, - front_image_metadata: front_image_metadata.to_json, - back_image_metadata: back_image_metadata.to_json, - document_capture_session_uuid: document_capture_session_uuid, - flow_path: flow_path, - } - expect(JSON.parse(response.body, symbolize_names: true)).to eq( - success: true, - status: 'in_progress', - ) - expect(response.status).to eq 202 - end - - context 'When the request does not have all the parameters' do - it 'returns 400 and gives error message' do - agent = instance_double(Idv::Agent) - allow(Idv::Agent).to receive(:new).and_return(agent) - expect(agent).to_not receive(:proof_document) - - post :create, params: { - encryption_key: encryption_key, - front_image_iv: nil, - back_image_iv: back_image_iv, - front_image_url: front_image_url, - back_image_url: back_image_url, - document_capture_session_uuid: document_capture_session_uuid, - } - - expect(JSON.parse(response.body)['errors'].keys.first).to eq('front_image_iv') - expect(JSON.parse(response.body)['errors']['front_image_iv'][0]). - to eq('Please fill in this field.') - expect(response.status).to eq 400 - end - end - end - end -end diff --git a/spec/forms/idv/api_document_verification_form_spec.rb b/spec/forms/idv/api_document_verification_form_spec.rb deleted file mode 100644 index dd5a30c203f..00000000000 --- a/spec/forms/idv/api_document_verification_form_spec.rb +++ /dev/null @@ -1,115 +0,0 @@ -require 'rails_helper' - -RSpec.describe Idv::ApiDocumentVerificationForm do - subject(:form) do - Idv::ApiDocumentVerificationForm.new( - { - encryption_key: encryption_key, - front_image_url: front_image_url, - front_image_iv: front_image_iv, - back_image_url: back_image_url, - back_image_iv: back_image_iv, - document_capture_session_uuid: document_capture_session_uuid, - }, - analytics: analytics, - irs_attempts_api_tracker: irs_attempts_api_tracker, - ) - end - - let(:encryption_key) { 'encryption-key' } - let(:front_image_url) { 'http://example.com/front' } - let(:front_image_iv) { 'front-iv' } - let(:back_image_url) { 'http://example.com/back' } - let(:back_image_iv) { 'back-iv' } - let!(:document_capture_session) { DocumentCaptureSession.create!(user: create(:user)) } - let(:document_capture_session_uuid) { document_capture_session.uuid } - let(:analytics) { FakeAnalytics.new } - let(:irs_attempts_api_tracker) { IrsAttemptsApiTrackingHelper::FakeAttemptsTracker.new } - - describe '#valid?' do - context 'with all valid images' do - it 'is valid' do - expect(form.valid?).to eq(true) - expect(form.errors).to be_blank - end - end - - context 'when iv is missing' do - let(:front_image_iv) { nil } - - it 'is not valid' do - expect(form.valid?).to eq(false) - expect(form.errors.attribute_names).to eq([:front_image_iv]) - expect(form.errors[:front_image_iv]).to eq(['Please fill in this field.']) - end - end - - context 'when encryption key is missing' do - let(:encryption_key) { nil } - - it 'is not valid' do - expect(form.valid?).to eq(false) - expect(form.errors.attribute_names).to eq([:encryption_key]) - expect(form.errors[:encryption_key]).to eq(['Please fill in this field.']) - end - end - - context 'when url is invalid' do - let(:front_image_url) { 'nonsense' } - - it 'is not valid' do - expect(form.valid?).to eq(false) - expect(form.errors.attribute_names).to eq([:front_image_url]) - expect(form.errors[:front_image_url]).to eq([t('doc_auth.errors.not_a_file')]) - end - end - - context 'when document_capture_session_uuid param is missing' do - let(:document_capture_session_uuid) { nil } - - it 'is not valid' do - expect(form.valid?).to eq(false) - expect(form.errors.attribute_names).to eq([:document_capture_session]) - expect(form.errors[:document_capture_session]).to eq(['Please fill in this field.']) - end - end - - context 'when document_capture_session_uuid does not correspond to a record' do - let(:document_capture_session_uuid) { 'unassociated-test-uuid' } - - it 'is not valid' do - expect(form.valid?).to eq(false) - expect(form.errors.attribute_names).to eq([:document_capture_session]) - expect(form.errors[:document_capture_session]).to eq(['Please fill in this field.']) - end - end - - context 'when throttled from submission' do - before do - Throttle.new( - throttle_type: :idv_doc_auth, - user: document_capture_session.user, - ).increment_to_throttled! - form.submit - end - - it 'is not valid' do - expect(irs_attempts_api_tracker).to receive(:idv_document_upload_rate_limited) - expect(form.valid?).to eq(false) - expect(form.errors.attribute_names).to eq([:limit]) - expect(form.errors[:limit]).to eq([I18n.t('errors.doc_auth.throttled_heading')]) - expect(analytics).to have_logged_event( - 'Throttler Rate Limit Triggered', - throttle_type: :idv_doc_auth, - ) - end - end - end - - describe '#submit' do - it 'includes remaining_attempts' do - response = form.submit - expect(response.extra[:remaining_attempts]).to be_a_kind_of(Numeric) - end - end -end From cb075fe12417f2776e6186f0ce80c50dd6ca4659 Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 15:01:03 -0700 Subject: [PATCH 08/12] Remove unused Api::Verify::DocumentCaptureErrorsController and BaseController --- app/controllers/api/verify/base_controller.rb | 25 ------- .../document_capture_errors_controller.rb | 27 ------- .../api/verify/base_controller_spec.rb | 39 ---------- ...document_capture_errors_controller_spec.rb | 71 ------------------- 4 files changed, 162 deletions(-) delete mode 100644 app/controllers/api/verify/base_controller.rb delete mode 100644 app/controllers/api/verify/document_capture_errors_controller.rb delete mode 100644 spec/controllers/api/verify/base_controller_spec.rb delete mode 100644 spec/controllers/api/verify/document_capture_errors_controller_spec.rb diff --git a/app/controllers/api/verify/base_controller.rb b/app/controllers/api/verify/base_controller.rb deleted file mode 100644 index 64d8f526df8..00000000000 --- a/app/controllers/api/verify/base_controller.rb +++ /dev/null @@ -1,25 +0,0 @@ -module Api - module Verify - class BaseController < ApplicationController - skip_before_action :verify_authenticity_token - - before_action :confirm_two_factor_authenticated_for_api - respond_to :json - - private - - def render_errors(errors, status: :bad_request) - render json: { errors: errors }, status: status - end - - def confirm_two_factor_authenticated_for_api - return if user_authenticated_for_api? - render_errors({ user: 'Unauthorized' }, status: :unauthorized) - end - - def user_authenticated_for_api? - user_fully_authenticated? - end - end - end -end diff --git a/app/controllers/api/verify/document_capture_errors_controller.rb b/app/controllers/api/verify/document_capture_errors_controller.rb deleted file mode 100644 index d454039ff66..00000000000 --- a/app/controllers/api/verify/document_capture_errors_controller.rb +++ /dev/null @@ -1,27 +0,0 @@ -module Api - module Verify - class DocumentCaptureErrorsController < BaseController - include EffectiveUser - - def delete - form = DocumentCaptureErrorsDeleteForm.new( - document_capture_session_uuid: params[:document_capture_session_uuid], - ) - result, document_capture_session = form.submit - - if result.success? - document_capture_session.update(ocr_confirmation_pending: false) - render json: {} - else - render json: { errors: result.errors }, status: :bad_request - end - end - - private - - def user_authenticated_for_api? - !!effective_user - end - end - end -end diff --git a/spec/controllers/api/verify/base_controller_spec.rb b/spec/controllers/api/verify/base_controller_spec.rb deleted file mode 100644 index af4e76511ac..00000000000 --- a/spec/controllers/api/verify/base_controller_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'rails_helper' - -describe Api::Verify::BaseController do - describe '#create' do - subject(:response) { post :create } - - controller Api::Verify::BaseController do - def create - render json: {} - end - end - - before { routes.draw { get '/' => 'api/verify/base#create' } } - - it 'renders as unauthorized (401)' do - expect(response.status).to eq(401) - end - - context 'with authenticated user' do - before { stub_sign_in } - - it 'renders as ok (200)' do - expect(response.status).to eq(200) - end - - context 'with request forgery protection enabled' do - around do |ex| - ActionController::Base.allow_forgery_protection = true - ex.run - ActionController::Base.allow_forgery_protection = false - end - - it 'renders as ok (200)' do - expect(response.status).to eq(200) - end - end - end - end -end diff --git a/spec/controllers/api/verify/document_capture_errors_controller_spec.rb b/spec/controllers/api/verify/document_capture_errors_controller_spec.rb deleted file mode 100644 index af2c39ee19f..00000000000 --- a/spec/controllers/api/verify/document_capture_errors_controller_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -require 'rails_helper' - -describe Api::Verify::DocumentCaptureErrorsController do - let(:user) { create(:user) } - - it 'extends behavior of base api class' do - expect(subject).to be_kind_of Api::Verify::BaseController - end - - describe '#delete' do - it 'renders as unauthorized (401)' do - delete :delete - - expect(response.status).to eq(401) - end - - shared_examples 'deleting document capture errors' do - let(:params) { nil } - - subject(:response) { delete :delete, params: params } - let(:parsed_body) { JSON.parse(response.body, symbolize_names: true) } - - it 'renders errors for missing fields' do - expect(response.status).to eq 400 - expect(parsed_body).to eq( - { errors: { document_capture_session_uuid: [t('errors.messages.blank')] } }, - ) - end - - context 'with invalid document capture session' do - let(:params) { { document_capture_session_uuid: 'invalid' } } - - it 'renders errors for invalid document capture session' do - expect(response.status).to eq 400 - expect(parsed_body).to eq( - { errors: { document_capture_session_uuid: ['Invalid document capture session'] } }, - ) - end - end - - context 'with valid document capture session' do - let(:document_capture_session) do - DocumentCaptureSession.create(user: user, ocr_confirmation_pending: true) - end - let(:params) { { document_capture_session_uuid: document_capture_session.uuid } } - - it 'deletes errors and renders successful response' do - expect { response }. - to change { document_capture_session.reload.ocr_confirmation_pending }. - from(true). - to(false) - - expect(response.status).to eq 200 - expect(parsed_body).to eq({}) - end - end - end - - context 'with signed in user' do - before { stub_sign_in(user) } - - it_behaves_like 'deleting document capture errors' - end - - context 'with hybrid effective user' do - before { session[:doc_capture_user_id] = user.id } - - it_behaves_like 'deleting document capture errors' - end - end -end From 84365baef9c7a8bc5a4163e9deb62468ded7833f Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 15:28:40 -0700 Subject: [PATCH 09/12] changelog changelog: Internal, Code Cleanup, remove async document capture code From b57b2df3d5292ebc2bbe7aa808dedb32bcf79e7e Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Wed, 10 May 2023 16:21:09 -0700 Subject: [PATCH 10/12] Remove translation tag document_verification_timeout --- config/locales/errors/en.yml | 1 - config/locales/errors/es.yml | 1 - config/locales/errors/fr.yml | 1 - 3 files changed, 3 deletions(-) diff --git a/config/locales/errors/en.yml b/config/locales/errors/en.yml index 5a82331d6c2..2d993ccfdce 100644 --- a/config/locales/errors/en.yml +++ b/config/locales/errors/en.yml @@ -23,7 +23,6 @@ en: consent_form: Before you can continue, you must give us permission. Please check the box below and then click continue. document_capture_cancelled: You have cancelled uploading photos of your ID on your phone. - document_verification_timeout: The server took too long to respond. Please try again. phone_step_incomplete: You must go to your phone and upload photos of your ID before continuing. We sent you a link with instructions. send_link_throttle: You tried too many times, please try again in %{timeout}. diff --git a/config/locales/errors/es.yml b/config/locales/errors/es.yml index 6c59bbb4ad7..74c565d0bd1 100644 --- a/config/locales/errors/es.yml +++ b/config/locales/errors/es.yml @@ -23,7 +23,6 @@ es: consent_form: Antes de continuar, debe darnos permiso. Marque la casilla a continuación y luego haga clic en continuar. document_capture_cancelled: Ha cancelado la carga de fotos de su identificación en este teléfono. - document_verification_timeout: El servidor tardó demasiado en responder. Inténtalo de nuevo. phone_step_incomplete: Debe ir a su teléfono y cargar fotos de su identificación antes de continuar. Te enviamos un enlace con instrucciones. send_link_throttle: Ha intentado demasiadas veces, por favor, inténtelo de nuevo diff --git a/config/locales/errors/fr.yml b/config/locales/errors/fr.yml index c83d9af23f8..5b5ab3a727b 100644 --- a/config/locales/errors/fr.yml +++ b/config/locales/errors/fr.yml @@ -26,7 +26,6 @@ fr: Veuillez cocher la case ci-dessous puis cliquez sur continuer. document_capture_cancelled: Vous avez annulé le téléchargement de vos photos d’identité sur votre téléphone. - document_verification_timeout: Le serveur a mis trop de temps à répondre. Veuillez réessayer. phone_step_incomplete: Vous devez aller sur votre téléphone et télécharger des photos de votre identifiant avant de continuer. Nous vous avons envoyé un lien avec des instructions. From d475f0aebb417895cf81aee325a1081cfceb7cfe Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Thu, 11 May 2023 14:11:39 -0700 Subject: [PATCH 11/12] Remove DocumentProofingJob --- app/jobs/document_proofing_job.rb | 165 ------------- app/services/idv/agent.rb | 21 -- spec/features/idv/analytics_spec.rb | 2 - spec/jobs/document_proofing_job_spec.rb | 305 ------------------------ 4 files changed, 493 deletions(-) delete mode 100644 app/jobs/document_proofing_job.rb delete mode 100644 spec/jobs/document_proofing_job_spec.rb diff --git a/app/jobs/document_proofing_job.rb b/app/jobs/document_proofing_job.rb deleted file mode 100644 index 8009426e42c..00000000000 --- a/app/jobs/document_proofing_job.rb +++ /dev/null @@ -1,165 +0,0 @@ -class DocumentProofingJob < ApplicationJob - include JobHelpers::StaleJobHelper - - queue_as :high_document_proofing - - discard_on JobHelpers::StaleJobHelper::StaleJobError - - def perform( - result_id:, - encrypted_arguments:, - trace_id:, - image_metadata:, - analytics_data:, - flow_path: - ) - timer = JobHelpers::Timer.new - - raise_stale_job! if stale_job?(enqueued_at) - - dcs = DocumentCaptureSession.find_by(result_id: result_id) - user = dcs.user - - decrypted_args = JSON.parse( - Encryption::Encryptors::BackgroundProofingArgEncryptor.new.decrypt(encrypted_arguments), - symbolize_names: true, - ) - document_args = decrypted_args[:document_arguments] - user_uuid = decrypted_args.fetch(:user_uuid, nil) - uuid_prefix = decrypted_args.fetch(:uuid_prefix, nil) - - encryption_key = Base64.decode64(document_args[:encryption_key].to_s) - front_image_iv = Base64.decode64(document_args[:front_image_iv].to_s) - back_image_iv = Base64.decode64(document_args[:back_image_iv].to_s) - front_image_url = document_args[:front_image_url] - back_image_url = document_args[:back_image_url] - - front_image = decrypt_image_from_s3( - timer: timer, name: :front, url: front_image_url, iv: front_image_iv, key: encryption_key, - ) - back_image = decrypt_image_from_s3( - timer: timer, name: :back, url: back_image_url, iv: back_image_iv, key: encryption_key, - ) - - analytics = build_analytics(dcs) - doc_auth_client = build_doc_auth_client(analytics, dcs) - - proofer_result = timer.time('proof_documents') do - doc_auth_client.post_images( - front_image: front_image, - back_image: back_image, - image_source: image_source(image_metadata), - user_uuid: user_uuid, - uuid_prefix: uuid_prefix, - ) - end - - dcs.store_doc_auth_result( - result: proofer_result.to_h, # pii_from_doc is excluded from to_h to stop accidental logging - pii: proofer_result.pii_from_doc, - ) - - throttle = Throttle.new(user: user, throttle_type: :idv_doc_auth) - - analytics.idv_doc_auth_submitted_image_upload_vendor( - **proofer_result.to_h.merge( - state: proofer_result.pii_from_doc[:state], - state_id_type: proofer_result.pii_from_doc[:state_id_type], - async: true, - attempts: throttle.attempts, - remaining_attempts: throttle.remaining_count, - client_image_metrics: image_metadata, - flow_path: flow_path, - ).merge(analytics_data), - ) - ensure - logger.info( - { - name: 'ProofDocument', - trace_id: trace_id, - success: proofer_result&.success?, - timing: timer.results, - }.to_json, - ) - end - - private - - def build_analytics(document_capture_session) - Analytics.new( - user: document_capture_session.user, - request: nil, - sp: document_capture_session.issuer, - session: {}, - ) - end - - def build_doc_auth_client(analytics, document_capture_session) - DocAuthRouter.client( - vendor_discriminator: document_capture_session.uuid, - warn_notifier: proc { |attrs| analytics.doc_auth_warning(**attrs) }, - ) - end - - def encryption_helper - @encryption_helper ||= JobHelpers::EncryptionHelper.new - end - - def image_source(image_metadata) - if acuant_sdk_capture?(image_metadata) - DocAuth::ImageSources::ACUANT_SDK - else - DocAuth::ImageSources::UNKNOWN - end - end - - def normalize_image_file(file_or_data_url) - return file_or_data_url if !file_or_data_url.start_with?('data:') - - data_url_image = Idv::DataUrlImage.new(file_or_data_url) - data_url_image.read - rescue Idv::DataUrlImage::InvalidUrlFormatError - file_or_data_url - end - - def acuant_sdk_capture?(image_metadata) - image_metadata.dig(:front, :source) == Idp::Constants::Vendors::ACUANT && - image_metadata.dig(:back, :source) == Idp::Constants::Vendors::ACUANT - end - - def s3_helper - @s3_helper ||= JobHelpers::S3Helper.new - end - - def decrypt_image_from_s3(timer:, name:, url:, iv:, key:) - encrypted_image = timer.time("download.#{name}") do - if s3_helper.s3_url?(url) - s3_helper.download(url) - else - build_faraday.get(url) do |req| - req.options.context = { service_name: 'document_proofing_image_download' } - end.body.b - end - end - decrypted = timer.time("decrypt.#{name}") do - encryption_helper.decrypt(data: encrypted_image, iv: iv, key: key) - end - timer.time("decode.#{name}") do - normalize_image_file(decrypted) - end - end - - # @return [Faraday::Connection] builds a Faraday instance with our defaults - def build_faraday - Faraday.new do |conn| - conn.options.timeout = IdentityConfig.store.doc_auth_s3_request_timeout - conn.options.read_timeout = IdentityConfig.store.doc_auth_s3_request_timeout - conn.options.open_timeout = IdentityConfig.store.doc_auth_s3_request_timeout - conn.options.write_timeout = IdentityConfig.store.doc_auth_s3_request_timeout - conn.request :instrumentation, name: 'request_log.faraday' - - # raises errors on 4XX or 5XX responses - conn.response :raise_error - end - end -end diff --git a/app/services/idv/agent.rb b/app/services/idv/agent.rb index 3bedd96cecf..f606ea173f0 100644 --- a/app/services/idv/agent.rb +++ b/app/services/idv/agent.rb @@ -57,26 +57,5 @@ def proof_address(document_capture_session, user_id:, issuer:, trace_id:) AddressProofingJob.perform_now(**job_arguments) end end - - def proof_document( - document_capture_session, - trace_id:, - image_metadata:, - analytics_data:, - flow_path: 'standard' - ) - encrypted_arguments = Encryption::Encryptors::BackgroundProofingArgEncryptor.new.encrypt( - @applicant.to_json, - ) - - DocumentProofingJob.perform_later( - encrypted_arguments: encrypted_arguments, - result_id: document_capture_session.result_id, - trace_id: trace_id, - image_metadata: image_metadata, - analytics_data: analytics_data, - flow_path: flow_path, - ) - end end end diff --git a/spec/features/idv/analytics_spec.rb b/spec/features/idv/analytics_spec.rb index d9c69b9f4c1..e76a31e1212 100644 --- a/spec/features/idv/analytics_spec.rb +++ b/spec/features/idv/analytics_spec.rb @@ -129,8 +129,6 @@ fake_analytics.user = controller.analytics_user fake_analytics end - allow_any_instance_of(DocumentProofingJob).to receive(:build_analytics). - and_return(fake_analytics) allow(IdentityConfig.store).to receive(:idv_acuant_sdk_upgrade_a_b_testing_enabled). and_return(false) end diff --git a/spec/jobs/document_proofing_job_spec.rb b/spec/jobs/document_proofing_job_spec.rb deleted file mode 100644 index e458eb28876..00000000000 --- a/spec/jobs/document_proofing_job_spec.rb +++ /dev/null @@ -1,305 +0,0 @@ -require 'rails_helper' - -RSpec.describe DocumentProofingJob, type: :job do - let(:front_image_url) { 'http://bucket.s3.amazonaws.com/bar1' } - let(:back_image_url) { 'http://bucket.s3.amazonaws.com/bar2' } - let(:encryption_key) { SecureRandom.random_bytes(32) } - let(:front_image_iv) { SecureRandom.random_bytes(12) } - let(:back_image_iv) { SecureRandom.random_bytes(12) } - let(:trace_id) { SecureRandom.uuid } - let(:source) { nil } - let(:front_image_metadata) { { mimeType: 'image/png', source: source } } - let(:back_image_metadata) { { mimeType: 'image/png', source: source } } - let(:image_metadata) { { front: front_image_metadata, back: back_image_metadata } } - - let(:applicant_pii) do - { - first_name: 'Johnny', - last_name: 'Appleseed', - uuid: SecureRandom.hex, - dob: '01/01/1970', - ssn: '123456789', - phone: '18888675309', - state: 'MT', - state_id_type: 'drivers_license', - } - end - - let(:body) { { document: applicant_pii }.to_json } - - before do - encrypt_and_stub_s3(body: body, url: front_image_url, iv: front_image_iv, key: encryption_key) - encrypt_and_stub_s3(body: body, url: back_image_url, iv: back_image_iv, key: encryption_key) - end - - let(:encrypted_arguments) do - Encryption::Encryptors::BackgroundProofingArgEncryptor.new.encrypt( - { - document_arguments: { - encryption_key: Base64.encode64(encryption_key), - front_image_iv: Base64.encode64(front_image_iv), - back_image_iv: Base64.encode64(back_image_iv), - front_image_url: front_image_url, - back_image_url: back_image_url, - }, - }.to_json, - ) - end - - let(:user) { create(:user) } - let(:analytics) { FakeAnalytics.new } - let(:document_capture_session) do - DocumentCaptureSession.create(user_id: user.id, result_id: SecureRandom.hex) - end - - describe '.perform_later' do - it 'stores results' do - DocumentProofingJob.perform_later( - result_id: document_capture_session.result_id, - encrypted_arguments: encrypted_arguments, - trace_id: trace_id, - image_metadata: image_metadata, - analytics_data: {}, - flow_path: 'standard', - ) - - result = document_capture_session.load_doc_auth_async_result - expect(result).to be_present - end - end - - describe '#perform' do - let(:job_analytics) { FakeAnalytics.new } - let(:instance) { DocumentProofingJob.new } - subject(:perform) do - instance.perform( - result_id: document_capture_session.result_id, - encrypted_arguments: encrypted_arguments, - trace_id: trace_id, - image_metadata: image_metadata, - analytics_data: {}, - flow_path: 'standard', - ) - end - - before do - allow(instance).to receive(:build_analytics). - with(document_capture_session).and_return(job_analytics) - end - - context 'with a successful response from the proofer' do - before do - expect(DocAuthRouter).to receive(:doc_auth_vendor).and_return('acuant') - - url = URI.join('https://example.com', '/AssureIDService/Document/Instance') - stub_request(:post, url).to_return(body: '"this-is-a-test-instance-id"') - doc_url = 'https://example.com/AssureIDService/Document/this-is-a-test-instance-id' - stub_request(:post, "#{doc_url}/Image?light=0&side=0").to_return(body: '') - stub_request(:post, "#{doc_url}/Image?light=0&side=1").to_return(body: '') - stub_request(:get, doc_url).to_return(body: '{"Result":1}') - stub_request(:get, "#{doc_url}/Field/Image?key=Photo").to_return(body: '') - stub_request(:post, 'https://example.login.gov/api/callbacks/proof-document/:token'). - to_return(body: '') - - allow_any_instance_of(DocAuth::Acuant::Responses::GetResultsResponse). - to receive(:pii_from_doc).and_return(applicant_pii) - end - - it 'returns a successful response' do - perform - - result = document_capture_session.load_doc_auth_async_result - - expect(result.result).to eq( - alert_failure_count: 0, - vendor: 'Acuant', - doc_auth_result: 'Passed', - billed: true, - errors: {}, - log_alert_results: {}, - attention_with_barcode: false, - image_metrics: {}, - processed_alerts: { failed: [], passed: [] }, - success: true, - exception: nil, - tamper_result: nil, - classification_info: nil, - address_line2_present: false, - ) - - expect(job_analytics).to have_logged_event( - 'IdV: doc auth image upload vendor submitted', - success: true, - errors: {}, - attention_with_barcode: false, - exception: nil, - vendor: 'Acuant', - billed: true, - doc_auth_result: 'Passed', - processed_alerts: { failed: [], passed: [] }, - alert_failure_count: 0, - image_metrics: {}, - state: 'MT', - state_id_type: 'drivers_license', - async: true, - attempts: 0, - remaining_attempts: IdentityConfig.store.doc_auth_max_attempts, - client_image_metrics: { - front: front_image_metadata, - back: back_image_metadata, - }, - tamper_result: nil, - flow_path: 'standard', - log_alert_results: {}, - classification_info: nil, - address_line2_present: false, - ) - - expect(result.pii_from_doc).to eq(applicant_pii) - end - - it 'logs the trace_id and timing info' do - expect(instance.logger).to receive(:info) do |message| - expect(JSON.parse(message, symbolize_names: true)).to include( - trace_id: trace_id, - timing: hash_including( - 'decrypt.back': kind_of(Float), - 'decrypt.front': kind_of(Float), - 'download.back': kind_of(Float), - 'download.front': kind_of(Float), - ), - ) - end - - perform - end - end - - context 'with local image URLs instead of S3 URLs' do - let(:front_image_url) { 'http://example.com/bar1' } - let(:back_image_url) { 'http://example.com/bar2' } - - before do - data = { document: applicant_pii }.to_json - encryption_helper = JobHelpers::EncryptionHelper.new - - stub_request(:get, front_image_url).to_return( - body: encryption_helper.encrypt(data: data, key: encryption_key, iv: front_image_iv), - ) - stub_request(:get, back_image_url).to_return( - body: encryption_helper.encrypt(data: data, key: encryption_key, iv: back_image_iv), - ) - end - - it 'still downloads and decrypts the content' do - perform - - expect(a_request(:get, front_image_url)).to have_been_made - expect(a_request(:get, back_image_url)).to have_been_made - end - end - - describe 'image source' do - let(:source) { nil } - let(:front_image_metadata) { { mimeType: 'image/png', source: source } } - let(:back_image_metadata) { { mimeType: 'image/png', source: source } } - let(:image_source) { nil } - - before do - expect_any_instance_of(DocAuth::Mock::DocAuthMockClient). - to receive(:post_images). - with(hash_including(image_source: image_source)). - and_call_original - end - - context 'manual uploads' do - let(:source) { 'upload' } - let(:image_source) { DocAuth::ImageSources::UNKNOWN } - - it 'sets image source to unknown' do - perform - end - end - - context 'mixed sources' do - let(:source) { 'upload' } - let(:back_image_metadata) do - { width: 20, height: 20, mimeType: 'image/png', source: 'acuant' }.to_json - end - let(:image_source) { DocAuth::ImageSources::UNKNOWN } - - it 'sets image source to unknown' do - perform - end - end - - context 'acuant images' do - let(:source) { 'acuant' } - let(:image_source) { DocAuth::ImageSources::ACUANT_SDK } - - it 'sets image source to acuant sdk' do - perform - end - end - - context 'malformed image metadata' do - let(:source) { 'upload' } - let(:front_image_metadata) { nil } - let(:image_source) { DocAuth::ImageSources::UNKNOWN } - - it 'sets image source to unknown' do - perform - end - end - end - - context 'a stale job' do - before { instance.enqueued_at = 10.minutes.ago } - - it 'bails and does not do any proofing' do - expect(DocAuthRouter).to_not receive(:doc_auth_vendor) - - expect { perform }.to raise_error(JobHelpers::StaleJobHelper::StaleJobError) - end - end - - context 'with data url body' do - let(:body) { DocAuthImageFixtures.document_front_image_data_uri } - - it 'decrypts the image correctly' do - expect_any_instance_of(DocAuth::Mock::DocAuthMockClient). - to receive(:post_images). - with(hash_including(front_image: DocAuthImageFixtures.document_front_image.b)). - and_call_original - - perform - end - end - - context 'with jpg file body' do - let(:body) { DocAuthImageFixtures.document_front_image } - - it 'decrypts the image correctly' do - expect_any_instance_of(DocAuth::Mock::DocAuthMockClient). - to receive(:post_images). - with(hash_including(front_image: DocAuthImageFixtures.document_front_image.b)). - and_call_original - - perform - end - end - - context 'with invalid data url body' do - let(:body) { 'data:"' } - - it 'gracefully degrades' do - expect_any_instance_of(DocAuth::Mock::DocAuthMockClient). - to receive(:post_images). - with(hash_including(front_image: nil)). - and_call_original - - perform - end - end - end -end From 6b5beaed19003bd73e89e9d22db36fd407fea9b3 Mon Sep 17 00:00:00 2001 From: Sonia Connolly Date: Thu, 11 May 2023 14:13:40 -0700 Subject: [PATCH 12/12] Remove DocumentCaptureErrorsDeleteForm --- .../document_capture_errors_delete_form.rb | 43 ---------------- ...ocument_capture_errors_delete_form_spec.rb | 49 ------------------- 2 files changed, 92 deletions(-) delete mode 100644 app/forms/api/verify/document_capture_errors_delete_form.rb delete mode 100644 spec/forms/api/verify/document_capture_errors_delete_form_spec.rb diff --git a/app/forms/api/verify/document_capture_errors_delete_form.rb b/app/forms/api/verify/document_capture_errors_delete_form.rb deleted file mode 100644 index 0d217ba7403..00000000000 --- a/app/forms/api/verify/document_capture_errors_delete_form.rb +++ /dev/null @@ -1,43 +0,0 @@ -module Api - module Verify - class DocumentCaptureErrorsDeleteForm - include ActiveModel::Model - - validates_presence_of :document_capture_session_uuid - validate :validate_document_capture_session - - attr_reader :document_capture_session_uuid - - def initialize(document_capture_session_uuid: nil) - @document_capture_session_uuid = document_capture_session_uuid - end - - def submit - result = FormResponse.new( - success: valid?, - errors: errors, - ) - - [result, document_capture_session] - end - - private - - def validate_document_capture_session - return if document_capture_session || !document_capture_session_uuid - errors.add( - :document_capture_session_uuid, - 'Invalid document capture session', - type: :invalid_document_capture_session, - ) - end - - def document_capture_session - return @document_capture_session if defined?(@document_capture_session) - @document_capture_session = DocumentCaptureSession.find_by( - uuid: document_capture_session_uuid, - ) - end - end - end -end diff --git a/spec/forms/api/verify/document_capture_errors_delete_form_spec.rb b/spec/forms/api/verify/document_capture_errors_delete_form_spec.rb deleted file mode 100644 index 799e333f295..00000000000 --- a/spec/forms/api/verify/document_capture_errors_delete_form_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'rails_helper' - -describe Api::Verify::DocumentCaptureErrorsDeleteForm do - let(:document_capture_session_uuid) { nil } - subject(:form) do - described_class.new(document_capture_session_uuid: document_capture_session_uuid) - end - - describe '#submit' do - context 'without a document capture session uuid' do - it 'is returns an unsuccessful form response' do - result, document_capture_session = form.submit - - expect(result.success?).to eq(false) - expect(result.errors).to eq( - { document_capture_session_uuid: ['Please fill in this field.'] }, - ) - expect(document_capture_session).to be_nil - end - end - - context 'with an invalid document capture session uuid' do - let(:document_capture_session_uuid) { 'wrong' } - - it 'is returns an unsuccessful form response' do - result, document_capture_session = form.submit - - expect(result.success?).to eq(false) - expect(result.errors).to eq( - { document_capture_session_uuid: ['Invalid document capture session'] }, - ) - expect(document_capture_session).to be_nil - end - end - - context 'with a valid document capture session uuid' do - let(:document_capture_session) { DocumentCaptureSession.create } - let(:document_capture_session_uuid) { document_capture_session.uuid } - - it 'is returns an successful form response' do - result, resolved_document_capture_session = form.submit - - expect(result.success?).to eq(true) - expect(result.errors).to eq({}) - expect(resolved_document_capture_session).to eq(document_capture_session) - end - end - end -end