app/models/gpo_confirmation.rb
# frozen_string_literal: true
class GpoConfirmation < ApplicationRecord
self.table_name = 'usps_confirmations'
ENTRY_ATTRIBUTES = %i[otp address1 city state zipcode].freeze
ENTRY_ATTRIBUTES.each do |attr|
define_method(:"entry_#{attr}") do
entry[attr]
end
end
validates :entry, presence: true
validates :entry_otp, :entry_address1, :entry_city, :entry_state, :entry_zipcode, presence: true
validate :entry_zipcode_is_valid
ZIP_REGEX = /^(\d{5})[-+]?(\d+)?$/
# Store the pii as encrypted json
def entry=(entry_hash)
@entry = nil
self[:entry] = encryptor.encrypt(
entry_hash.
dup.
tap do |h|
h[:zipcode] = self.class.normalize_zipcode(h[:zipcode]) if h[:zipcode].present?
end.
to_json,
)
end
# Read the pii as a decrypted hash
def entry
@entry ||= JSON.parse(encryptor.decrypt(self[:entry]), symbolize_names: true)
end
def self.normalize_zipcode(zipcode)
_, zip, plus4 = ZIP_REGEX.match(zipcode&.gsub(/\s/, '')).to_a
if plus4&.length == 4
"#{zip}-#{plus4}"
else
zip
end
end
private
def encryptor
Encryption::Encryptors::BackgroundProofingArgEncryptor.new
end
def entry_zipcode_should_be_rejected_because_we_are_testing?
# We reserve a certain zipcode to be used to test this value in lower environments.
entry_zipcode.present? &&
entry_zipcode == IdentityConfig.store.invalid_gpo_confirmation_zipcode
end
def entry_zipcode_is_valid
normalized = self.class.normalize_zipcode(entry_zipcode)
if normalized.nil? || entry_zipcode_should_be_rejected_because_we_are_testing?
errors.add(:entry_zipcode, :invalid)
end
end
end