From 53325c2c7b6d8a14bdbee1efdb729db79f1892d3 Mon Sep 17 00:00:00 2001 From: Richard Davis Date: Fri, 15 Mar 2024 11:46:44 -0400 Subject: [PATCH 1/7] Adds error handling to VA Profile v3 service --- config/database.yml | 4 +- lib/va_profile/profile/v3/service.rb | 6 +- .../lib/va_profile/profile/v3/service_spec.rb | 50 +++++++++++---- .../profile/v3/health_benefit_bio_500.yml | 61 +++++++++++++++++++ 4 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 spec/support/vcr_cassettes/va_profile/profile/v3/health_benefit_bio_500.yml diff --git a/config/database.yml b/config/database.yml index 70dd7f004cc..019a51ec7d4 100644 --- a/config/database.yml +++ b/config/database.yml @@ -6,7 +6,7 @@ default: &default pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %> development: - url: <%= Settings.database_url %> + url: postgis://postgres:password@localhost:5432/vets_api_development # The specified database role being used to connect to postgres. # To create additional roles in postgres see `$ createuser --help`. @@ -39,7 +39,7 @@ development: # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - url: <%= Settings.test_database_url %><%= ENV['TEST_ENV_NUMBER'] %> + url: postgis://postgres:password@localhost:5432/vets_api_test # As with config/secrets.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is diff --git a/lib/va_profile/profile/v3/service.rb b/lib/va_profile/profile/v3/service.rb index 8c26e61e49f..2eee7fbd6de 100644 --- a/lib/va_profile/profile/v3/service.rb +++ b/lib/va_profile/profile/v3/service.rb @@ -10,7 +10,7 @@ module Profile module V3 # NOTE: This controller is used for discovery purposes. # Please contact the Authenticated Experience Profile team before using. - class Service < Common::Client::Base + class Service < VAProfile::Service configuration VAProfile::Profile::V3::Configuration OID = '2.16.840.1.113883.3.42.10001.100001.12' @@ -20,7 +20,7 @@ class Service < Common::Client::Base def initialize(user) @user = user - super() + super(user) end def get_health_benefit_bio @@ -28,6 +28,8 @@ def get_health_benefit_bio path = "#{oid}/#{ERB::Util.url_encode(icn_with_aaid)}" response = perform(:post, path, { bios: [{ bioPath: 'healthBenefit' }] }) VAProfile::Profile::V3::HealthBenefitBioResponse.new(response) + rescue => e + handle_error(e) end def get_military_info diff --git a/spec/lib/va_profile/profile/v3/service_spec.rb b/spec/lib/va_profile/profile/v3/service_spec.rb index ddcae4f7b05..3726e2182af 100644 --- a/spec/lib/va_profile/profile/v3/service_spec.rb +++ b/spec/lib/va_profile/profile/v3/service_spec.rb @@ -55,30 +55,54 @@ describe '#get_health_benefit_bio' do let(:user) { build(:user, :loa3, idme_uuid:) } + around do |ex| + VCR.use_cassette(cassette) { ex.run } + end + context '200 response' do let(:idme_uuid) { 'dd681e7d6dea41ad8b80f8d39284ef29' } + let(:cassette) { 'va_profile/profile/v3/health_benefit_bio_200' } it 'returns the contacts (aka associated_persons) for a user, sorted' do - VCR.use_cassette('va_profile/profile/v3/health_benefit_bio_200') do - response = subject.get_health_benefit_bio - expect(response.status).to eq(200) - expect(response.contacts.size).to eq(4) - types = response.contacts.map(&:contact_type) - expect(types).to match_array(VAProfile::Models::AssociatedPerson::CONTACT_TYPES) - end + response = subject.get_health_benefit_bio + expect(response.status).to eq(200) + expect(response.contacts.size).to eq(4) + types = response.contacts.map(&:contact_type) + expect(types).to match_array(VAProfile::Models::AssociatedPerson::CONTACT_TYPES) end end context '404 response' do let(:idme_uuid) { '88f572d4-91af-46ef-a393-cba6c351e252' } + let(:cassette) { 'va_profile/profile/v3/health_benefit_bio_404' } it 'includes messages recieved from the api' do - VCR.use_cassette('va_profile/profile/v3/health_benefit_bio_404') do - response = subject.get_health_benefit_bio - expect(response.status).to eq(404) - expect(response.contacts.size).to eq(0) - expect(response.messages.size).to eq(1) - end + response = subject.get_health_benefit_bio + expect(response.status).to eq(404) + expect(response.contacts.size).to eq(0) + expect(response.messages.size).to eq(1) + end + end + + context '500 response' do + let(:idme_uuid) { '88f572d4-91af-46ef-a393-cba6c351e252' } + let(:cassette) { 'va_profile/profile/v3/health_benefit_bio_500' } + + it 'includes messages recieved from the api' do + response = subject.get_health_benefit_bio + expect(response.status).to eq(500) + expect(response.contacts.size).to eq(0) + expect(response.messages.size).to eq(1) + end + end + + context 'api timeout' do + let(:idme_uuid) { '88f572d4-91af-46ef-a393-cba6c351e252' } + let(:cassette) { 'va_profile/profile/v3/health_benefit_bio_500' } + + it 'raises an error' do + allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::TimeoutError) + expect { subject.get_health_benefit_bio }.to raise_error( Common::Exceptions::GatewayTimeout) end end end diff --git a/spec/support/vcr_cassettes/va_profile/profile/v3/health_benefit_bio_500.yml b/spec/support/vcr_cassettes/va_profile/profile/v3/health_benefit_bio_500.yml new file mode 100644 index 00000000000..66944f355f2 --- /dev/null +++ b/spec/support/vcr_cassettes/va_profile/profile/v3/health_benefit_bio_500.yml @@ -0,0 +1,61 @@ +--- +http_interactions: +- request: + method: post + uri: https://int.vet360.va.gov/profile-service/profile/v3/2.16.840.1.113883.4.349/88f572d4-91af-46ef-a393-cba6c351e252%5EPN%5E200VIDM%5EUSDVA + body: + encoding: UTF-8 + string: '{"bios":[{"bioPath":"healthBenefit"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - Vets.gov Agent + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 500 + message: Internal Server Error + headers: + X-Oneagent-Js-Injection: + - 'true' + Server-Timing: + - dtRpid;desc="-552585048", dtSInfo;desc="0" + - dtRpid;desc="667499283", dtSInfo;desc="0" + Vaprofiletxauditid: + - ab45e9d3-6491-4062-8384-40d23135d252 + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - '0' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Pragma: + - no-cache + Expires: + - '0' + X-Frame-Options: + - DENY + Content-Security-Policy: + - 'default-src ''self'' ''unsafe-eval'' ''unsafe-inline'' data: filesystem: + about: blob: ws: wss:' + Date: + - Mon, 05 Feb 2024 22:13:44 GMT + Referrer-Policy: + - no-referrer + Content-Type: + - application/json + Content-Length: + - '184' + Strict-Transport-Security: + - max-age=16000000; includeSubDomains; preload; + body: + encoding: UTF-8 + string: '{"messages":[{"code":"MVI203","key":"MviResponseError","text":"MVI returned + acknowledgement error code AE with error detail: More Than One Active Correlation + Exists","severity":"FATAL"}]}' + recorded_at: Mon, 05 Feb 2024 22:13:44 GMT +recorded_with: VCR 6.2.0 From 7abb298600cf3bc2786d0fcd66ed26afea8e7216 Mon Sep 17 00:00:00 2001 From: Richard Davis Date: Fri, 15 Mar 2024 11:54:11 -0400 Subject: [PATCH 2/7] Revert change to database.yml --- config/database.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/database.yml b/config/database.yml index 019a51ec7d4..70dd7f004cc 100644 --- a/config/database.yml +++ b/config/database.yml @@ -6,7 +6,7 @@ default: &default pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %> development: - url: postgis://postgres:password@localhost:5432/vets_api_development + url: <%= Settings.database_url %> # The specified database role being used to connect to postgres. # To create additional roles in postgres see `$ createuser --help`. @@ -39,7 +39,7 @@ development: # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - url: postgis://postgres:password@localhost:5432/vets_api_test + url: <%= Settings.test_database_url %><%= ENV['TEST_ENV_NUMBER'] %> # As with config/secrets.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is From 151505e875cc274a4b54cbfd6d85958f1cb8714e Mon Sep 17 00:00:00 2001 From: Richard Davis Date: Fri, 15 Mar 2024 11:58:58 -0400 Subject: [PATCH 3/7] Removes space --- spec/lib/va_profile/profile/v3/service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/va_profile/profile/v3/service_spec.rb b/spec/lib/va_profile/profile/v3/service_spec.rb index 3726e2182af..cc7f96f57b2 100644 --- a/spec/lib/va_profile/profile/v3/service_spec.rb +++ b/spec/lib/va_profile/profile/v3/service_spec.rb @@ -102,7 +102,7 @@ it 'raises an error' do allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::TimeoutError) - expect { subject.get_health_benefit_bio }.to raise_error( Common::Exceptions::GatewayTimeout) + expect { subject.get_health_benefit_bio }.to raise_error(Common::Exceptions::GatewayTimeout) end end end From 3e9c6e1a01d552b403b239a34f1a25a87df1c2bb Mon Sep 17 00:00:00 2001 From: Richard Davis Date: Mon, 25 Mar 2024 10:32:16 -0400 Subject: [PATCH 4/7] Selects only valid contact types --- .../profile/v3/health_benefit_bio_response.rb | 44 ++++++++----- .../v3/health_benefit_bio_response_spec.rb | 62 +++++++++++++++++++ 2 files changed, 92 insertions(+), 14 deletions(-) create mode 100644 spec/lib/va_profile/profile/v3/health_benefit_bio_response_spec.rb diff --git a/lib/va_profile/profile/v3/health_benefit_bio_response.rb b/lib/va_profile/profile/v3/health_benefit_bio_response.rb index ffea96f8731..1dde3fb9f89 100644 --- a/lib/va_profile/profile/v3/health_benefit_bio_response.rb +++ b/lib/va_profile/profile/v3/health_benefit_bio_response.rb @@ -4,23 +4,39 @@ require 'va_profile/models/associated_person' require 'va_profile/models/message' -module VAProfile::Profile::V3 - class HealthBenefitBioResponse < VAProfile::Response - attr_reader :body +module VAProfile + module Profile + module V3 + class HealthBenefitBioResponse < VAProfile::Response + attr_reader :body - attribute :contacts, Array[VAProfile::Models::AssociatedPerson] - attribute :messages, Array[VAProfile::Models::Message] + attribute :contacts, Array[VAProfile::Models::AssociatedPerson] + attribute :messages, Array[VAProfile::Models::Message] - def initialize(response) - @body = response.body - contacts = body.dig('profile', 'health_benefit', 'associated_persons') - &.sort_by { |p| VAProfile::Models::AssociatedPerson::CONTACT_TYPES.index(p['contact_type']) } - messages = body['messages'] - super(response.status, { contacts:, messages: }) - end + def initialize(response) + @body = response.body + contacts = body.dig('profile', 'health_benefit', 'associated_persons') + &.select { |p| valid_contact_types.include?(p['contact_type']) } + &.sort_by { |p| valid_contact_types.index(p['contact_type']) } + messages = body['messages'] + super(response.status, { contacts:, messages: }) + end + + def metadata + { status:, messages: } + end + + private - def metadata - { status:, messages: } + def valid_contact_types + [ + VAProfile::Models::AssociatedPerson::EMERGENCY_CONTACT, + VAProfile::Models::AssociatedPerson::OTHER_EMERGENCY_CONTACT, + VAProfile::Models::AssociatedPerson::PRIMARY_NEXT_OF_KIN, + VAProfile::Models::AssociatedPerson::OTHER_NEXT_OF_KIN + ] + end + end end end end diff --git a/spec/lib/va_profile/profile/v3/health_benefit_bio_response_spec.rb b/spec/lib/va_profile/profile/v3/health_benefit_bio_response_spec.rb new file mode 100644 index 00000000000..1cf69f17ecf --- /dev/null +++ b/spec/lib/va_profile/profile/v3/health_benefit_bio_response_spec.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require 'rails_helper' +require 'va_profile/profile/v3/health_benefit_bio_response' + +describe VAProfile::Profile::V3::HealthBenefitBioResponse do + subject { described_class.new(response) } + + let(:response) do + double('Faraday::Response', + status: 200, + body: { + 'profile' => { + 'health_benefit' => { + 'associated_persons' => [{ + 'contact_type' => contact_type + }] + } + } + }) + end + + describe 'Emergency contact' do + let(:contact_type) { 'Emergency Contact' } + + it 'includes contact' do + expect(subject.contacts).not_to be_empty + end + end + + describe 'Other emergency contact' do + let(:contact_type) { 'Other emergency contact' } + + it 'includes contact' do + expect(subject.contacts).not_to be_empty + end + end + + describe 'Primary Next of Kin' do + let(:contact_type) { 'Primary Next of Kin' } + + it 'includes contact' do + expect(subject.contacts).not_to be_empty + end + end + + describe 'Other Next of Kin' do + let(:contact_type) { 'Other Next of Kin' } + + it 'includes contact' do + expect(subject.contacts).not_to be_empty + end + end + + describe 'Invalid contact type' do + let(:contact_type) { 'Invalid type' } + + it 'includes contact' do + expect(subject.contacts).to be_empty + end + end +end From c97180f4e1fc1ca68a2936e517047bce1282a7c3 Mon Sep 17 00:00:00 2001 From: Richard Davis Date: Mon, 25 Mar 2024 13:02:42 -0400 Subject: [PATCH 5/7] Updates --- lib/va_profile/profile/v3/service.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/va_profile/profile/v3/service.rb b/lib/va_profile/profile/v3/service.rb index 2eee7fbd6de..8c26e61e49f 100644 --- a/lib/va_profile/profile/v3/service.rb +++ b/lib/va_profile/profile/v3/service.rb @@ -10,7 +10,7 @@ module Profile module V3 # NOTE: This controller is used for discovery purposes. # Please contact the Authenticated Experience Profile team before using. - class Service < VAProfile::Service + class Service < Common::Client::Base configuration VAProfile::Profile::V3::Configuration OID = '2.16.840.1.113883.3.42.10001.100001.12' @@ -20,7 +20,7 @@ class Service < VAProfile::Service def initialize(user) @user = user - super(user) + super() end def get_health_benefit_bio @@ -28,8 +28,6 @@ def get_health_benefit_bio path = "#{oid}/#{ERB::Util.url_encode(icn_with_aaid)}" response = perform(:post, path, { bios: [{ bioPath: 'healthBenefit' }] }) VAProfile::Profile::V3::HealthBenefitBioResponse.new(response) - rescue => e - handle_error(e) end def get_military_info From 974b36dee307604df542fbc07513f5f2adc31e4a Mon Sep 17 00:00:00 2001 From: Richard Davis Date: Mon, 25 Mar 2024 13:09:09 -0400 Subject: [PATCH 6/7] Updates specs --- spec/lib/va_profile/profile/v3/service_spec.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/spec/lib/va_profile/profile/v3/service_spec.rb b/spec/lib/va_profile/profile/v3/service_spec.rb index cc7f96f57b2..a34629b418f 100644 --- a/spec/lib/va_profile/profile/v3/service_spec.rb +++ b/spec/lib/va_profile/profile/v3/service_spec.rb @@ -68,7 +68,13 @@ expect(response.status).to eq(200) expect(response.contacts.size).to eq(4) types = response.contacts.map(&:contact_type) - expect(types).to match_array(VAProfile::Models::AssociatedPerson::CONTACT_TYPES) + valid_contact_types = [ + VAProfile::Models::AssociatedPerson::EMERGENCY_CONTACT, + VAProfile::Models::AssociatedPerson::OTHER_EMERGENCY_CONTACT, + VAProfile::Models::AssociatedPerson::PRIMARY_NEXT_OF_KIN, + VAProfile::Models::AssociatedPerson::OTHER_NEXT_OF_KIN + ] + expect(types).to match_array(valid_contact_types) end end From d4c69531aeba5d1c9b46f6b365f84abd56dd16f8 Mon Sep 17 00:00:00 2001 From: Richard Davis Date: Mon, 25 Mar 2024 14:11:55 -0400 Subject: [PATCH 7/7] Updates --- .../va_profile/profile/v3/health_benefit_bio_response_spec.rb | 2 +- spec/lib/va_profile/profile/v3/service_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/lib/va_profile/profile/v3/health_benefit_bio_response_spec.rb b/spec/lib/va_profile/profile/v3/health_benefit_bio_response_spec.rb index 1cf69f17ecf..70f51f3ed61 100644 --- a/spec/lib/va_profile/profile/v3/health_benefit_bio_response_spec.rb +++ b/spec/lib/va_profile/profile/v3/health_benefit_bio_response_spec.rb @@ -55,7 +55,7 @@ describe 'Invalid contact type' do let(:contact_type) { 'Invalid type' } - it 'includes contact' do + it 'does not include contact' do expect(subject.contacts).to be_empty end end diff --git a/spec/lib/va_profile/profile/v3/service_spec.rb b/spec/lib/va_profile/profile/v3/service_spec.rb index a34629b418f..da5ec7b9b89 100644 --- a/spec/lib/va_profile/profile/v3/service_spec.rb +++ b/spec/lib/va_profile/profile/v3/service_spec.rb @@ -82,7 +82,7 @@ let(:idme_uuid) { '88f572d4-91af-46ef-a393-cba6c351e252' } let(:cassette) { 'va_profile/profile/v3/health_benefit_bio_404' } - it 'includes messages recieved from the api' do + it 'includes messages received from the api' do response = subject.get_health_benefit_bio expect(response.status).to eq(404) expect(response.contacts.size).to eq(0)