diff --git a/Gemfile.lock b/Gemfile.lock index d2e0ac53785..9356ece95a3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -150,7 +150,7 @@ GEM GEM remote: https://rubygems.org/ specs: - Ascii85 (1.1.0) + Ascii85 (2.0.1) aasm (5.5.0) concurrent-ruby (~> 1.0) actioncable (7.2.2.1) @@ -531,14 +531,9 @@ GEM google-cloud-env (2.2.1) faraday (>= 1.0, < 3.a) google-logging-utils (0.1.0) - google-protobuf (4.28.3) + google-protobuf (4.29.2) bigdecimal rake (>= 13) - google-protobuf (4.28.3-java) - bigdecimal - ffi (~> 1) - ffi-compiler (~> 1) - rake (>= 13) googleauth (1.12.2) faraday (>= 1.0, < 3.a) google-cloud-env (~> 2.2) @@ -761,8 +756,8 @@ GEM safe_shell (>= 1.0.3, < 2.0) pdf-inspector (1.3.0) pdf-reader (>= 1.0, < 3.0.a) - pdf-reader (2.12.0) - Ascii85 (~> 1.0) + pdf-reader (2.13.0) + Ascii85 (>= 1.0, < 3.0, != 2.0.0) afm (~> 0.2.1) hashery (~> 2.0) ruby-rc4 diff --git a/app/models/health_care_application.rb b/app/models/health_care_application.rb index 090b2ea5f55..8ee3f4d5e2f 100644 --- a/app/models/health_care_application.rb +++ b/app/models/health_care_application.rb @@ -315,8 +315,16 @@ def send_failure_email def form_matches_schema if form.present? - JSON::Validator.fully_validate(VetsJsonSchema::SCHEMAS[self.class::FORM_ID], parsed_form).each do |v| - errors.add(:form, v.to_s) + schema = VetsJsonSchema::SCHEMAS[self.class::FORM_ID] + begin + JSON::Validator.fully_validate(schema, parsed_form).each do |v| + errors.add(:form, v.to_s) + end + rescue => e + PersonalInformationLog.create(data: { schema:, parsed_form: }, + error_class: 'HealthCareApplication FormValidationError') + Rails.logger.error("[#{FORM_ID}] Error during schema validation!", { error: e.message, schema: }) + raise end end end diff --git a/db/schema.rb b/db/schema.rb index 09c8727634f..afbf63271f4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_12_20_164548) do +ActiveRecord::Schema[7.2].define(version: 2024_12_27_213059) do # These are extensions that must be enabled in order to support this database enable_extension "btree_gin" enable_extension "fuzzystrmatch" @@ -273,12 +273,14 @@ t.uuid "power_of_attorney_request_id", null: false t.text "encrypted_kms_key" t.text "data_ciphertext", null: false - t.string "city_bidx", null: false - t.string "state_bidx", null: false - t.string "zipcode_bidx", null: false - t.index ["city_bidx", "state_bidx", "zipcode_bidx"], name: "idx_on_city_bidx_state_bidx_zipcode_bidx_a85b76f9bc" + t.string "claimant_city_ciphertext", null: false + t.string "claimant_city_bidx", null: false + t.string "claimant_state_code_ciphertext", null: false + t.string "claimant_state_code_bidx", null: false + t.string "claimant_zip_code_ciphertext", null: false + t.string "claimant_zip_code_bidx", null: false + t.index ["claimant_city_bidx", "claimant_state_code_bidx", "claimant_zip_code_bidx"], name: "idx_on_claimant_city_bidx_claimant_state_code_bidx__11e9adbe25" t.index ["power_of_attorney_request_id"], name: "idx_on_power_of_attorney_request_id_fc59a0dabc", unique: true - t.index ["zipcode_bidx"], name: "index_ar_power_of_attorney_forms_on_zipcode_bidx" end create_table "ar_power_of_attorney_request_decisions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| @@ -304,6 +306,7 @@ create_table "ar_power_of_attorney_requests", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "claimant_id", null: false t.datetime "created_at", null: false + t.string "claimant_type", null: false t.index ["claimant_id"], name: "index_ar_power_of_attorney_requests_on_claimant_id" end diff --git a/modules/accredited_representative_portal/db/migrate/20241227212839_remove_old_indices_from_poa_forms.rb b/modules/accredited_representative_portal/db/migrate/20241227212839_remove_old_indices_from_poa_forms.rb new file mode 100644 index 00000000000..e0d142fcf36 --- /dev/null +++ b/modules/accredited_representative_portal/db/migrate/20241227212839_remove_old_indices_from_poa_forms.rb @@ -0,0 +1,6 @@ +class RemoveOldIndicesFromPoaForms < ActiveRecord::Migration[7.1] + def change + remove_index :ar_power_of_attorney_forms, name: 'idx_on_city_bidx_state_bidx_zipcode_bidx_a85b76f9bc', column: [:city_bidx, :state_bidx, :zipcode_bidx] + remove_index :ar_power_of_attorney_forms, name: 'index_ar_power_of_attorney_forms_on_zipcode_bidx', column: :zipcode_bidx + end +end diff --git a/modules/accredited_representative_portal/db/migrate/20241227212922_remove_columns_from_poa_forms.rb b/modules/accredited_representative_portal/db/migrate/20241227212922_remove_columns_from_poa_forms.rb new file mode 100644 index 00000000000..980aa3c57db --- /dev/null +++ b/modules/accredited_representative_portal/db/migrate/20241227212922_remove_columns_from_poa_forms.rb @@ -0,0 +1,5 @@ +class RemoveColumnsFromPoaForms < ActiveRecord::Migration[7.1] + def change + safety_assured { remove_columns :ar_power_of_attorney_forms, :city_bidx, :state_bidx, :zipcode_bidx, type: :string } + end +end diff --git a/modules/accredited_representative_portal/db/migrate/20241227212942_add_columns_to_poa_forms.rb b/modules/accredited_representative_portal/db/migrate/20241227212942_add_columns_to_poa_forms.rb new file mode 100644 index 00000000000..eb6ccded31c --- /dev/null +++ b/modules/accredited_representative_portal/db/migrate/20241227212942_add_columns_to_poa_forms.rb @@ -0,0 +1,12 @@ +class AddColumnsToPoaForms < ActiveRecord::Migration[7.1] + def change + add_column :ar_power_of_attorney_forms, :claimant_city_ciphertext, :string, null: false + add_column :ar_power_of_attorney_forms, :claimant_city_bidx, :string, null: false + + add_column :ar_power_of_attorney_forms, :claimant_state_code_ciphertext, :string, null: false + add_column :ar_power_of_attorney_forms, :claimant_state_code_bidx, :string, null: false + + add_column :ar_power_of_attorney_forms, :claimant_zip_code_ciphertext, :string, null: false + add_column :ar_power_of_attorney_forms, :claimant_zip_code_bidx, :string, null: false + end +end diff --git a/modules/accredited_representative_portal/db/migrate/20241227213018_add_new_index_to_poa_forms.rb b/modules/accredited_representative_portal/db/migrate/20241227213018_add_new_index_to_poa_forms.rb new file mode 100644 index 00000000000..27421549c74 --- /dev/null +++ b/modules/accredited_representative_portal/db/migrate/20241227213018_add_new_index_to_poa_forms.rb @@ -0,0 +1,9 @@ +class AddNewIndexToPoaForms < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + add_index :ar_power_of_attorney_forms, + [:claimant_city_bidx, :claimant_state_code_bidx, :claimant_zip_code_bidx], + algorithm: :concurrently + end +end diff --git a/modules/accredited_representative_portal/db/migrate/20241227213059_add_claimant_type_to_poa_requests.rb b/modules/accredited_representative_portal/db/migrate/20241227213059_add_claimant_type_to_poa_requests.rb new file mode 100644 index 00000000000..b8f1ae170bf --- /dev/null +++ b/modules/accredited_representative_portal/db/migrate/20241227213059_add_claimant_type_to_poa_requests.rb @@ -0,0 +1,5 @@ +class AddClaimantTypeToPoaRequests < ActiveRecord::Migration[7.1] + def change + add_column :ar_power_of_attorney_requests, :claimant_type, :string, null: false + end +end diff --git a/spec/models/health_care_application_spec.rb b/spec/models/health_care_application_spec.rb index d782813e331..6cc0f43e415 100644 --- a/spec/models/health_care_application_spec.rb +++ b/spec/models/health_care_application_spec.rb @@ -363,6 +363,32 @@ expect_attr_valid(health_care_application, attr) end end + + context 'schema validation raises an exception' do + let(:health_care_application) { build(:health_care_application) } + let(:exception) { StandardError.new('Some exception') } + + before do + allow(PersonalInformationLog).to receive(:create) + allow(JSON::Validator).to receive(:fully_validate).and_raise(exception) + end + + it 'logs exception and raises exception' do + expect(PersonalInformationLog).to receive(:create).with( + data: { + schema: VetsJsonSchema::SCHEMAS[form_id], + parsed_form: health_care_application.parsed_form + }, + error_class: 'HealthCareApplication FormValidationError' + ) + expect(Rails.logger).to receive(:error) + .with("[#{form_id}] Error during schema validation!", { + error: exception.message, + schema: VetsJsonSchema::SCHEMAS[form_id] + }) + expect { health_care_application.valid? }.to raise_error(exception.class, exception.message) + end + end end describe '#process!' do