<%= submit_tag(t('idv.buttons.send_confirmation_code'), class: 'usa-button usa-button--big usa-button--wide') %>
diff --git a/app/views/idv/phone/new.html.erb b/app/views/idv/phone/new.html.erb
index 14dcd6debf0..f65733d4750 100644
--- a/app/views/idv/phone/new.html.erb
+++ b/app/views/idv/phone/new.html.erb
@@ -56,7 +56,7 @@
) do |f| %>
<%= render PhoneInputComponent.new(
form: f,
- allowed_countries: ['US'],
+ allowed_countries: @idv_form.allowed_countries,
required: true,
class: 'margin-bottom-4',
) %>
diff --git a/config/application.yml.default b/config/application.yml.default
index e75c698e042..5d9ec142536 100644
--- a/config/application.yml.default
+++ b/config/application.yml.default
@@ -41,6 +41,7 @@ acuant_upload_image_timeout: 1.0
acuant_get_results_timeout: 1.0
acuant_create_document_timeout: 1.0
add_email_link_valid_for_hours: 24
+address_identity_proofing_supported_country_codes: '["AS", "GU", "MP", "PR", "US", "VI"]'
asset_host: ''
async_wait_timeout_seconds: 60
async_stale_job_timeout_seconds: 300
diff --git a/config/locales/errors/en.yml b/config/locales/errors/en.yml
index 1c887dbc1a7..a58141d4a61 100644
--- a/config/locales/errors/en.yml
+++ b/config/locales/errors/en.yml
@@ -67,15 +67,12 @@ en:
invalid_voice_number: Invalid phone number. Check that you’ve entered the
correct country code or area code.
missing_field: Please fill in this field.
- must_have_us_country_code: Invalid phone number. Please make sure you enter a
- phone number with a U.S. country code.
no_pending_profile: No profile is waiting for verification
not_a_number: is not a number
otp_failed: Your security code failed to send.
password_incorrect: Incorrect password
personal_key_incorrect: Incorrect personal key
phone_confirmation_throttled: You tried too many times, please try again in %{timeout}.
- phone_country_constraint_usa: Must be a U.S. phone number
phone_duplicate: This account is already using the phone number you entered as
an authenticator. Please use a different phone number.
phone_required: Phone number is required
diff --git a/config/locales/errors/es.yml b/config/locales/errors/es.yml
index 4304186aa3d..40842a7d7f5 100644
--- a/config/locales/errors/es.yml
+++ b/config/locales/errors/es.yml
@@ -69,15 +69,12 @@ es:
invalid_voice_number: Numero de telefono invalido. Verifique que haya ingresado
el código de país o de área correcto.
missing_field: Por favor, rellene este campo.
- must_have_us_country_code: Número de teléfono no válido. Asegúrate de introducir
- un número de teléfono con un código país de EE. UU.
no_pending_profile: Ningún perfil está esperando verificación
not_a_number: no es un número
otp_failed: Se produjo un error al enviar el código de seguridad.
password_incorrect: La contraseña es incorrecta
personal_key_incorrect: La clave personal es incorrecta
phone_confirmation_throttled: Lo intentaste muchas veces, vuelve a intentarlo en %{timeout}.
- phone_country_constraint_usa: Debe ser un número telefónico de los Estados Unidos
phone_duplicate: Esta cuenta ya está utilizando el número de teléfono que
ingresó como autenticador. Por favor, use un número de teléfono
diferente.
diff --git a/config/locales/errors/fr.yml b/config/locales/errors/fr.yml
index 62a2a1f873f..2a5a3597c3c 100644
--- a/config/locales/errors/fr.yml
+++ b/config/locales/errors/fr.yml
@@ -76,15 +76,12 @@ fr:
invalid_voice_number: Numéro de téléphone invalide. Vérifiez que vous avez entré
le bon indicatif international ou régional.
missing_field: Veuillez remplir ce champ.
- must_have_us_country_code: Numéro de téléphone non valide. Veuillez vous assurer
- de saisir un numéro de téléphone avec un code pays des États-Unis.
no_pending_profile: Aucun profil en attente de vérification
not_a_number: N’est pas un nombre
otp_failed: Échec de l’envoi de votre code de sécurité.
password_incorrect: Mot de passe incorrect
personal_key_incorrect: Clé personnelle incorrecte
phone_confirmation_throttled: Vous avez essayé plusieurs fois, essayez à nouveau dans %{timeout}.
- phone_country_constraint_usa: Dois être un numéro de téléphone américain
phone_duplicate: Ce compte utilise déjà le numéro de téléphone que vous avez
entré en tant qu’authentificateur. Veuillez utiliser un numéro de
téléphone différent.
diff --git a/lib/identity_config.rb b/lib/identity_config.rb
index f3549883d93..c6509c89a8a 100644
--- a/lib/identity_config.rb
+++ b/lib/identity_config.rb
@@ -100,6 +100,7 @@ def self.build_store(config_map)
config.add(:acuant_get_results_timeout, type: :float)
config.add(:acuant_create_document_timeout, type: :float)
config.add(:add_email_link_valid_for_hours, type: :integer)
+ config.add(:address_identity_proofing_supported_country_codes, type: :json)
config.add(:asset_host, type: :string)
config.add(:async_wait_timeout_seconds, type: :integer)
config.add(:async_stale_job_timeout_seconds, type: :integer)
diff --git a/spec/controllers/idv/phone_controller_spec.rb b/spec/controllers/idv/phone_controller_spec.rb
index 7224b4a5b63..e54240baf9c 100644
--- a/spec/controllers/idv/phone_controller_spec.rb
+++ b/spec/controllers/idv/phone_controller_spec.rb
@@ -143,14 +143,14 @@
it 'renders #new' do
put :create, params: { idv_phone_form: { phone: '703' } }
- expect(flash[:error]).to eq t('errors.messages.must_have_us_country_code')
+ expect(flash[:error]).to eq t('errors.messages.improbable_phone')
expect(response).to render_template(:new)
end
it 'disallows non-US numbers' do
put :create, params: { idv_phone_form: { phone: international_phone } }
- expect(flash[:error]).to eq t('errors.messages.must_have_us_country_code')
+ expect(flash[:error]).to eq t('errors.messages.improbable_phone')
expect(response).to render_template(:new)
end
@@ -162,10 +162,10 @@
result = {
success: false,
errors: {
- phone: [t('errors.messages.must_have_us_country_code')],
+ phone: [t('errors.messages.improbable_phone')],
},
error_details: {
- phone: [:must_have_us_country_code],
+ phone: [:improbable_phone],
},
pii_like_keypaths: [[:errors, :phone], [:error_details, :phone]],
country_code: nil,
@@ -189,7 +189,7 @@
success: false,
phone_number: '703',
failure_reason: {
- phone: [t('errors.messages.must_have_us_country_code')],
+ phone: [t('errors.messages.improbable_phone')],
},
)
end
@@ -314,6 +314,7 @@
end
it 'tracks event with valid phone' do
+ proofing_phone = Phonelib.parse(good_phone)
user = build(:user, with: { phone: '+1 (415) 555-0130', phone_confirmed_at: Time.zone.now })
stub_verify_steps_one_and_two(user)
@@ -324,6 +325,9 @@
success: true,
new_phone_added: true,
errors: {},
+ phone_fingerprint: Pii::Fingerprinter.fingerprint(proofing_phone.e164),
+ country_code: proofing_phone.country,
+ area_code: proofing_phone.area_code,
pii_like_keypaths: [[:errors, :phone], [:context, :stages, :address]],
vendor: {
vendor_name: 'AddressMock',
@@ -362,6 +366,7 @@
end
it 'tracks event with invalid phone' do
+ proofing_phone = Phonelib.parse(bad_phone)
user = build(:user, with: { phone: '+1 (415) 555-0130', phone_confirmed_at: Time.zone.now })
stub_verify_steps_one_and_two(user)
@@ -371,6 +376,9 @@
result = {
success: false,
new_phone_added: true,
+ phone_fingerprint: Pii::Fingerprinter.fingerprint(proofing_phone.e164),
+ country_code: proofing_phone.country,
+ area_code: proofing_phone.area_code,
errors: {
phone: ['The phone number could not be verified.'],
},
diff --git a/spec/features/idv/steps/phone_otp_delivery_selection_step_spec.rb b/spec/features/idv/steps/phone_otp_delivery_selection_step_spec.rb
index d1ebb9ea0f5..09f9f942a63 100644
--- a/spec/features/idv/steps/phone_otp_delivery_selection_step_spec.rb
+++ b/spec/features/idv/steps/phone_otp_delivery_selection_step_spec.rb
@@ -71,7 +71,7 @@
it 'displays an error message' do
expect(Telephony).to_not receive(:send_confirmation_otp)
- expect(page).to have_content(t('errors.messages.phone_country_constraint_usa'))
+ expect(page).to have_content(t('errors.messages.invalid_phone_number'))
expect(current_path).to eq(idv_phone_path)
end
end
diff --git a/spec/forms/idv/phone_form_spec.rb b/spec/forms/idv/phone_form_spec.rb
index ffdb92675c3..1b7fc5e6bd2 100644
--- a/spec/forms/idv/phone_form_spec.rb
+++ b/spec/forms/idv/phone_form_spec.rb
@@ -89,7 +89,7 @@
end
context 'with specific allowed countries' do
- let(:allowed_countries) { ['MP'] }
+ let(:allowed_countries) { ['MP', 'US'] }
it 'validates to only allow numbers from permitted countries' do
invalid_phones = ['+81 54 354 3643', '+12423270143']
@@ -116,7 +116,7 @@
result = subject.submit(phone: phone)
expect(result.success?).to eq(false)
- expect(result.errors[:phone]).to include(t('errors.messages.must_have_us_country_code'))
+ expect(result.errors[:phone]).to include(t('errors.messages.improbable_phone'))
end
valid_phones = ['7035551234']
valid_phones.each do |phone|
@@ -154,5 +154,44 @@
end
end
end
+
+ context 'with unsupported delivery method' do
+ let(:unsupported_delivery_methods) { [] }
+ let(:result) { subject.submit(params) }
+
+ before do
+ allow(subject).to receive(:unsupported_delivery_methods).
+ and_return(unsupported_delivery_methods)
+ end
+
+ context 'with one unsupported delivery method' do
+ let(:unsupported_delivery_methods) { [:sms] }
+
+ it 'is valid' do
+ expect(result.success?).to eq(true)
+ expect(result.errors).to eq({})
+ end
+ end
+
+ context 'with all delivery methods unsupported' do
+ let(:unsupported_delivery_methods) { [:sms, :voice] }
+
+ it 'is invalid' do
+ expect(result.success?).to eq(false)
+ expect(result.errors).to eq(
+ phone: [
+ t(
+ 'two_factor_authentication.otp_delivery_preference.sms_unsupported',
+ location: 'United States',
+ ),
+ t(
+ 'two_factor_authentication.otp_delivery_preference.voice_unsupported',
+ location: 'United States',
+ ),
+ ],
+ )
+ end
+ end
+ end
end
end
diff --git a/spec/services/idv/phone_step_spec.rb b/spec/services/idv/phone_step_spec.rb
index eb219503f70..42e004100b4 100644
--- a/spec/services/idv/phone_step_spec.rb
+++ b/spec/services/idv/phone_step_spec.rb
@@ -49,7 +49,11 @@
let(:throttle) { Throttle.new(throttle_type: :proof_address, user: user) }
it 'succeeds with good params' do
+ proofing_phone = Phonelib.parse(good_phone)
extra = {
+ phone_fingerprint: Pii::Fingerprinter.fingerprint(proofing_phone.e164),
+ country_code: proofing_phone.country,
+ area_code: proofing_phone.area_code,
vendor: {
vendor_name: 'AddressMock',
exception: nil,
@@ -78,7 +82,11 @@
end
it 'fails with bad params' do
+ proofing_phone = Phonelib.parse(bad_phone)
extra = {
+ phone_fingerprint: Pii::Fingerprinter.fingerprint(proofing_phone.e164),
+ country_code: proofing_phone.country,
+ area_code: proofing_phone.area_code,
vendor: {
vendor_name: 'AddressMock',
exception: nil,
diff --git a/spec/views/idv/otp_delivery_method/new.html.erb_spec.rb b/spec/views/idv/otp_delivery_method/new.html.erb_spec.rb
index 97b0accbd72..46d4585739d 100644
--- a/spec/views/idv/otp_delivery_method/new.html.erb_spec.rb
+++ b/spec/views/idv/otp_delivery_method/new.html.erb_spec.rb
@@ -3,8 +3,17 @@
describe 'idv/otp_delivery_method/new.html.erb' do
let(:gpo_letter_available) { false }
let(:step_indicator_steps) { Idv::Flows::DocAuthFlow::STEP_INDICATOR_STEPS }
+ let(:supports_sms) { true }
+ let(:supports_voice) { true }
before do
+ phone_number_capabilities = instance_double(
+ PhoneNumberCapabilities,
+ supports_sms?: supports_sms,
+ supports_voice?: supports_voice,
+ )
+
+ allow(view).to receive(:phone_number_capabilities).and_return(phone_number_capabilities)
allow(view).to receive(:user_signing_up?).and_return(false)
allow(view).to receive(:user_fully_authenticated?).and_return(true)
allow(view).to receive(:gpo_letter_available).and_return(gpo_letter_available)
@@ -46,4 +55,27 @@
expect(rendered).to have_field('otp_delivery_preference', with: :sms, disabled: true)
end
end
+
+ it 'renders sms and voice options' do
+ expect(rendered).to have_field('otp_delivery_preference', with: :voice)
+ expect(rendered).to have_field('otp_delivery_preference', with: :sms)
+ end
+
+ context 'without sms support' do
+ let(:supports_sms) { false }
+
+ it 'renders voice option' do
+ expect(rendered).to have_field('otp_delivery_preference', with: :voice)
+ expect(rendered).not_to have_field('otp_delivery_preference', with: :sms)
+ end
+ end
+
+ context 'without voice support' do
+ let(:supports_voice) { false }
+
+ it 'renders sms option' do
+ expect(rendered).not_to have_field('otp_delivery_preference', with: :voice)
+ expect(rendered).to have_field('otp_delivery_preference', with: :sms)
+ end
+ end
end