diff --git a/app/controllers/submit_form_controller.rb b/app/controllers/submit_form_controller.rb index 85a1c9ab..154930a5 100644 --- a/app/controllers/submit_form_controller.rb +++ b/app/controllers/submit_form_controller.rb @@ -106,7 +106,7 @@ class SubmitFormController < ApplicationController def fetch_ats_prefill_values_if_available # ATS passes values directly as Base64-encoded JSON parameters - return {} unless params[:ats_values].present? + return {} if params[:ats_values].blank? # Security: Limit input size to prevent DoS attacks (64KB limit) if params[:ats_values].bytesize > 65_536 @@ -129,8 +129,8 @@ class SubmitFormController < ApplicationController if ats_values.is_a?(Hash) # Audit logging: Log ATS prefill usage for security monitoring Rails.logger.info "ATS prefill values processed for submitter: #{@submitter&.slug || 'unknown'}, " \ - "field_count: #{ats_values.keys.length}, " \ - "account: #{@submitter&.account&.name || 'unknown'}" + "field_count: #{ats_values.keys.length}, " \ + "account: #{@submitter&.account&.name || 'unknown'}" ats_values else Rails.logger.warn "ATS prefill values not a hash: #{ats_values.class}" diff --git a/app/helpers/prefill_fields_helper.rb b/app/helpers/prefill_fields_helper.rb index 1f42c7c3..80608272 100644 --- a/app/helpers/prefill_fields_helper.rb +++ b/app/helpers/prefill_fields_helper.rb @@ -31,7 +31,7 @@ module PrefillFieldsHelper begin cached_result = Rails.cache.read(cache_key) return cached_result if cached_result - rescue StandardError => e + rescue StandardError # Continue with normal processing if cache read fails end @@ -49,14 +49,13 @@ module PrefillFieldsHelper cache_result(cache_key, valid_fields, ATS_FIELDS_CACHE_TTL) valid_fields - rescue StandardError => e + rescue StandardError # Cache empty result for failed parsing to avoid repeated failures cache_result(cache_key, [], 5.minutes) [] end end - # Merges ATS prefill values with existing submitter values # # This method combines ATS-provided prefill values with values already entered by submitters. @@ -93,9 +92,7 @@ module PrefillFieldsHelper next if matching_field_uuid.nil? # Only set if submitter hasn't already filled this field - if submitter_values[matching_field_uuid].blank? - submitter_values[matching_field_uuid] = value - end + submitter_values[matching_field_uuid] = value if submitter_values[matching_field_uuid].blank? end submitter_values @@ -129,7 +126,7 @@ module PrefillFieldsHelper def cache_result(cache_key, value, ttl) Rails.cache.write(cache_key, value, expires_in: ttl) - rescue StandardError => e + rescue StandardError # Continue execution even if caching fails end @@ -164,7 +161,7 @@ module PrefillFieldsHelper begin cached_lookup = Rails.cache.read(cache_key) return cached_lookup if cached_lookup - rescue StandardError => e + rescue StandardError # Continue with normal processing if cache read fails end @@ -173,15 +170,13 @@ module PrefillFieldsHelper prefill_name = field['prefill'] field_uuid = field['uuid'] - if prefill_name.present? && field_uuid.present? - hash[prefill_name] = field_uuid - end + hash[prefill_name] = field_uuid if prefill_name.present? && field_uuid.present? end # Cache the lookup with error handling begin Rails.cache.write(cache_key, lookup, expires_in: FIELD_LOOKUP_CACHE_TTL) - rescue StandardError => e + rescue StandardError # Continue execution even if caching fails end @@ -208,8 +203,6 @@ module PrefillFieldsHelper field_lookup[field_name] end - private - # Generates cache key for field lookup optimization def field_lookup_cache_key(template_fields) # Create a hash based on the structure of template fields for caching @@ -217,5 +210,4 @@ module PrefillFieldsHelper hash = Digest::SHA256.hexdigest(fields_signature) "field_lookup:#{hash}" end - end diff --git a/spec/helpers/prefill_fields_helper_spec.rb b/spec/helpers/prefill_fields_helper_spec.rb index 4ef177f8..90fa92d4 100644 --- a/spec/helpers/prefill_fields_helper_spec.rb +++ b/spec/helpers/prefill_fields_helper_spec.rb @@ -106,7 +106,7 @@ RSpec.describe PrefillFieldsHelper, type: :helper do 'field-1-uuid' => 'Existing First Name', # Should not be overwritten 'field-2-uuid' => 'Doe', # Should be set from ATS 'field-3-uuid' => 'john.doe@example.com', # Should be set from ATS - 'field-4-uuid' => 'Existing Signature' # Should remain unchanged + 'field-4-uuid' => 'Existing Signature' # Should remain unchanged ) end @@ -184,9 +184,13 @@ RSpec.describe PrefillFieldsHelper, type: :helper do it 'caches the result' do # The implementation uses a SHA256 hash for cache key, not the raw encoded string cache_key = helper.send(:ats_fields_cache_key, encoded_fields) - expect(Rails.cache).to receive(:read).with(cache_key).and_return(nil) - expect(Rails.cache).to receive(:write).with(cache_key, fields, expires_in: 1.hour) + allow(Rails.cache).to receive(:read).with(cache_key).and_return(nil) + allow(Rails.cache).to receive(:write).with(cache_key, fields, expires_in: 1.hour) + helper.extract_ats_prefill_fields + + expect(Rails.cache).to have_received(:read).with(cache_key) + expect(Rails.cache).to have_received(:write).with(cache_key, fields, expires_in: 1.hour) end end @@ -228,5 +232,4 @@ RSpec.describe PrefillFieldsHelper, type: :helper do expect(result).to eq(fields) end end - end diff --git a/spec/integration/ats_prefill_integration_spec.rb b/spec/integration/ats_prefill_integration_spec.rb index ad208116..ec45bb48 100644 --- a/spec/integration/ats_prefill_integration_spec.rb +++ b/spec/integration/ats_prefill_integration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe 'ATS Prefill Integration', type: :request do @@ -39,31 +41,28 @@ RSpec.describe 'ATS Prefill Integration', type: :request do let(:template) do create(:template, - account: account, - author: user, - folder: template_folder, - fields: template_fields, - submitters: [{ 'name' => 'First Party', 'uuid' => 'submitter-uuid-1' }] - ) + account: account, + author: user, + folder: template_folder, + fields: template_fields, + submitters: [{ 'name' => 'First Party', 'uuid' => 'submitter-uuid-1' }]) end let(:submission) do create(:submission, - template: template, - account: account, - created_by_user: user, - template_fields: template_fields, - template_submitters: [{ 'name' => 'First Party', 'uuid' => 'submitter-uuid-1' }] - ) + template: template, + account: account, + created_by_user: user, + template_fields: template_fields, + template_submitters: [{ 'name' => 'First Party', 'uuid' => 'submitter-uuid-1' }]) end let(:submitter) do create(:submitter, - submission: submission, - uuid: 'submitter-uuid-1', - name: 'John Doe', - email: 'john@example.com' - ) + submission: submission, + uuid: 'submitter-uuid-1', + name: 'John Doe', + email: 'john@example.com') end describe 'Controller ATS parameter processing' do @@ -76,8 +75,9 @@ RSpec.describe 'ATS Prefill Integration', type: :request do context 'when ATS fields and values are provided via Base64 parameters' do let(:test_params) do { - ats_fields: Base64.urlsafe_encode64(['employee_first_name', 'employee_last_name', 'employee_email'].to_json), - ats_values: Base64.urlsafe_encode64({ 'employee_first_name' => 'John', 'employee_last_name' => 'Smith', 'employee_email' => 'john.smith@company.com' }.to_json) + ats_fields: Base64.urlsafe_encode64(%w[employee_first_name employee_last_name employee_email].to_json), + ats_values: Base64.urlsafe_encode64({ 'employee_first_name' => 'John', 'employee_last_name' => 'Smith', + 'employee_email' => 'john.smith@company.com' }.to_json) } end @@ -85,10 +85,10 @@ RSpec.describe 'ATS Prefill Integration', type: :request do result = controller.send(:fetch_ats_prefill_values_if_available) expect(result).to eq({ - 'employee_first_name' => 'John', - 'employee_last_name' => 'Smith', - 'employee_email' => 'john.smith@company.com' - }) + 'employee_first_name' => 'John', + 'employee_last_name' => 'Smith', + 'employee_email' => 'john.smith@company.com' + }) end end @@ -165,9 +165,9 @@ RSpec.describe 'ATS Prefill Integration', type: :request do result = merge_ats_prefill_values(existing_values, ats_values, template_fields) expect(result).to eq({ - 'field-1-uuid' => 'Existing John', # Should not override existing value - 'field-2-uuid' => 'ATS Smith' # Should add new ATS value - }) + 'field-1-uuid' => 'Existing John', # Should not override existing value + 'field-2-uuid' => 'ATS Smith' # Should add new ATS value + }) end it 'handles empty ATS values gracefully' do @@ -177,8 +177,8 @@ RSpec.describe 'ATS Prefill Integration', type: :request do result = merge_ats_prefill_values(existing_values, ats_values, template_fields) expect(result).to eq({ - 'field-1-uuid' => 'Existing John' - }) + 'field-1-uuid' => 'Existing John' + }) end it 'handles missing template fields gracefully' do @@ -197,10 +197,22 @@ RSpec.describe 'ATS Prefill Integration', type: :request do it 'processes complete ATS prefill workflow from parameters to merged values' do # Step 1: Simulate controller parameter processing controller = SubmitFormController.new - allow(controller).to receive(:params).and_return(ActionController::Parameters.new({ - ats_fields: Base64.urlsafe_encode64(['employee_first_name', 'employee_last_name', 'employee_email'].to_json), - ats_values: Base64.urlsafe_encode64({ 'employee_first_name' => 'John', 'employee_last_name' => 'Smith', 'employee_email' => 'john.smith@company.com' }.to_json) - })) + ats_fields_data = %w[employee_first_name employee_last_name employee_email] + ats_values_data = { + 'employee_first_name' => 'John', + 'employee_last_name' => 'Smith', + 'employee_email' => 'john.smith@company.com' + } + + encoded_fields = Base64.urlsafe_encode64(ats_fields_data.to_json) + encoded_values = Base64.urlsafe_encode64(ats_values_data.to_json) + + params = ActionController::Parameters.new({ + ats_fields: encoded_fields, + ats_values: encoded_values + }) + + allow(controller).to receive(:params).and_return(params) ats_values = controller.send(:fetch_ats_prefill_values_if_available) @@ -212,10 +224,10 @@ RSpec.describe 'ATS Prefill Integration', type: :request do # Step 4: Verify final result expect(final_values).to eq({ - 'field-1-uuid' => 'Existing John', # Existing value preserved - 'field-2-uuid' => 'Smith', # ATS value applied - 'field-3-uuid' => 'john.smith@company.com' # ATS value applied - }) + 'field-1-uuid' => 'Existing John', # Existing value preserved + 'field-2-uuid' => 'Smith', # ATS value applied + 'field-3-uuid' => 'john.smith@company.com' # ATS value applied + }) end end end