Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions app/controllers/concerns/phone_confirmation.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
module PhoneConfirmation
def prompt_to_confirm_phone(phone:, context: 'confirmation')
def prompt_to_confirm_phone(phone:, context: 'confirmation', selected_delivery_method: nil)
user_session[:unconfirmed_phone] = phone
user_session[:context] = context

redirect_to otp_send_path(
otp_delivery_selection_form: { otp_delivery_preference: otp_delivery_method(phone) }
otp_delivery_selection_form: {
otp_delivery_preference: otp_delivery_method(phone, selected_delivery_method),
}
)
end

private

def otp_delivery_method(phone)
if PhoneNumberCapabilities.new(phone).sms_only?
:sms
else
current_user.otp_delivery_preference
end
def otp_delivery_method(phone, selected_delivery_method)
return :sms if PhoneNumberCapabilities.new(phone).sms_only?
return selected_delivery_method if selected_delivery_method.present?
current_user.otp_delivery_preference
end
end
19 changes: 10 additions & 9 deletions app/controllers/users/two_factor_authentication_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ def show
end

def send_code
@otp_delivery_selection_form = OtpDeliverySelectionForm.new(current_user, phone_to_deliver_to)
result = otp_delivery_selection_form.submit(delivery_params)

result = @otp_delivery_selection_form.submit(delivery_params)

track_otp_delivery_selection_event(result)
analytics.track_event(Analytics::OTP_DELIVERY_SELECTION, result.to_h)

if result.success?
handle_valid_otp_delivery_preference(user_selected_otp_delivery_preference)
Expand All @@ -29,6 +27,14 @@ def send_code

private

def otp_delivery_selection_form
OtpDeliverySelectionForm.new(
current_user,
phone_to_deliver_to,
context
)
end

def reauthn_param
otp_form = params.permit(otp_delivery_selection_form: [:reauthn])
super || otp_form.dig(:otp_delivery_selection_form, :reauthn)
Expand Down Expand Up @@ -61,11 +67,6 @@ def send_user_otp(method)
)
end

def track_otp_delivery_selection_event(result)
attributes = result.to_h.merge(context: context)
analytics.track_event(Analytics::OTP_DELIVERY_SELECTION, attributes)
end

def user_selected_otp_delivery_preference
delivery_params[:otp_delivery_preference]
end
Expand Down
57 changes: 57 additions & 0 deletions app/controllers/verify/otp_delivery_method_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module Verify
class OtpDeliveryMethodController < ApplicationController
include IdvSession
include PhoneConfirmation

before_action :confirm_phone_step_complete
before_action :confirm_step_needed
before_action :set_otp_delivery_method_presenter
before_action :set_otp_delivery_selection_form

def new; end

def create
result = @otp_delivery_selection_form.submit(otp_delivery_selection_params)
if result.success?
prompt_to_confirm_phone(
phone: idv_session.params[:phone],
context: 'idv',
selected_delivery_method: @otp_delivery_selection_form.otp_delivery_preference
)
else
render :new
end
end

private

def confirm_phone_step_complete
redirect_to verify_review_path if idv_session.vendor_phone_confirmation != true
end

def confirm_step_needed
redirect_to verify_review_path if idv_session.address_verification_mechanism != 'phone' ||
idv_session.user_phone_confirmation == true
end

def otp_delivery_selection_params
params.require(:otp_delivery_selection_form).permit(
:otp_delivery_preference
)
end

def set_otp_delivery_method_presenter
@set_otp_delivery_method_presenter = OtpDeliveryMethodPresenter.new(
idv_session.params[:phone]
)
end

def set_otp_delivery_selection_form
@otp_delivery_selection_form = OtpDeliverySelectionForm.new(
current_user,
idv_session.params[:phone],
'idv'
)
end
end
end
3 changes: 1 addition & 2 deletions app/controllers/verify/phone_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module Verify
class PhoneController < ApplicationController
include IdvStepConcern
include IdvFailureConcern
include PhoneConfirmation

before_action :confirm_step_needed
before_action :confirm_step_allowed
Expand Down Expand Up @@ -43,7 +42,7 @@ def show

def redirect_to_next_step
if phone_confirmation_required?
prompt_to_confirm_phone(phone: idv_session.params[:phone], context: 'idv')
redirect_to verify_otp_delivery_method_url
else
redirect_to verify_review_url
end
Expand Down
16 changes: 13 additions & 3 deletions app/forms/otp_delivery_selection_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ class OtpDeliverySelectionForm

validates :otp_delivery_preference, inclusion: { in: %w[sms voice] }

def initialize(user, phone_to_deliver_to)
def initialize(user, phone_to_deliver_to, context)
@user = user
@phone_to_deliver_to = phone_to_deliver_to
@context = context
end

def submit(params)
Expand All @@ -16,7 +17,7 @@ def submit(params)

@success = valid?

if success && otp_delivery_preference_changed?
if should_update_user?
user_attributes = { otp_delivery_preference: otp_delivery_preference }
UpdateUser.new(user: user, attributes: user_attributes).call
end
Expand All @@ -28,18 +29,27 @@ def submit(params)

attr_writer :otp_delivery_preference
attr_accessor :resend
attr_reader :success, :user, :phone_to_deliver_to
attr_reader :success, :user, :phone_to_deliver_to, :context

def idv_context?
context == 'idv'
end

def otp_delivery_preference_changed?
otp_delivery_preference != user.otp_delivery_preference
end

def should_update_user?
success && otp_delivery_preference_changed? && !idv_context?
end

def extra_analytics_attributes
{
otp_delivery_preference: otp_delivery_preference,
resend: resend,
country_code: parsed_phone.country_code,
area_code: parsed_phone.area_code,
context: context,
}
end

Expand Down
24 changes: 24 additions & 0 deletions app/presenters/verify/otp_delivery_method_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Verify
class OtpDeliveryMethodPresenter
attr_reader :phone

delegate :sms_only?, to: :phone_number_capabilites

def initialize(phone)
@phone = PhoneFormatter.new.format(phone)
end

def phone_unsupported_message
I18n.t(
'devise.two_factor_authentication.otp_delivery_preference.phone_unsupported',
location: phone_number_capabilites.unsupported_location
)
end

private

def phone_number_capabilites
@phone_number_capabilites ||= PhoneNumberCapabilities.new(phone)
end
end
end
33 changes: 33 additions & 0 deletions app/views/verify/otp_delivery_method/new.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
h1.h3.my0 = t('idv.titles.otp_delivery_method')
p = t('idv.messages.otp_delivery_method.phone_number_html',
phone: @set_otp_delivery_method_presenter.phone)
= simple_form_for(@otp_delivery_selection_form, url: verify_otp_delivery_method_url,
html: { autocomplete: 'off', method: 'put', role: 'form', class: 'mt2' }) do |f|
fieldset.mb3.p0.border-none
legend.mb1.h4.serif.bold = t('devise.two_factor_authentication.otp_delivery_preference.title')
label.btn-border.col-12.sm-col-5.sm-mr2.mb2.sm-mb0
.radio
= radio_button_tag 'otp_delivery_selection_form[otp_delivery_preference]', :sms, true,
class: :otp_delivery_preference_sms
span.indicator
= t('devise.two_factor_authentication.otp_delivery_preference.sms')
- if @set_otp_delivery_method_presenter.sms_only?
label.btn-border.col-12.sm-col-5.btn-disabled
.radio
= radio_button_tag 'otp_delivery_selection_form[otp_delivery_preference]', :voice, false,
disabled: true,
class: :otp_delivery_preference_voice
span.indicator
= t('devise.two_factor_authentication.otp_delivery_preference.voice')
p.mt2.mb0 = @set_otp_delivery_method_presenter.phone_unsupported_message
- else
label.btn-border.col-12.sm-col-5
.radio
= radio_button_tag 'otp_delivery_selection_form[otp_delivery_preference]', :voice, false,
class: :otp_delivery_preference_voice
span.indicator
= t('devise.two_factor_authentication.otp_delivery_preference.voice')
= f.submit t('idv.buttons.send_confirmation_code'), type: :submit, class: 'btn btn-primary'
.mt2.pt1.border-top
= t('instructions.mfa.wrong_number_html',
link: link_to(t('forms.two_factor.try_again'), verify_phone_path))
4 changes: 4 additions & 0 deletions config/locales/idv/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ en:
send: Send a letter
return_to_account: Return to account
return_to_sp: Return to %{sp}
send_confirmation_code: Send confirmation code
cancel:
modal_header: Are you sure you want to cancel?
warning_header: If you cancel now
Expand Down Expand Up @@ -126,6 +127,8 @@ en:
help_center: Visit our Help Center to learn more about verifying your account.
loading: Verifying your identity
mail_sent: Your letter is on its way
otp_delivery_method:
phone_number_html: We will send a code to <strong>%{phone}</strong>
personal_details_verified: Personal details verified!
personal_key: This is your new personal key. Write it down and keep it in a
safe place. You will need it if you ever lose your password.
Expand Down Expand Up @@ -205,6 +208,7 @@ en:
mail:
resend: Want another letter?
verify: Want a letter?
otp_delivery_method: Get a code by phone
phone: Phone number of record
review: Review and submit
select_verification: Activate your account
Expand Down
4 changes: 4 additions & 0 deletions config/locales/idv/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ es:
send: Enviar una carta
return_to_account: NOT TRANSLATED YET
return_to_sp: NOT TRANSLATED YET
send_confirmation_code: NOT TRANSLATED YET
cancel:
modal_header: "¿Está seguro que desea cancelar?"
warning_header: Si usted cancela ahora
Expand Down Expand Up @@ -128,6 +129,8 @@ es:
la verificación de su cuenta.
loading: NOT TRANSLATED YET
mail_sent: Su carta está en camino
otp_delivery_method:
phone_number_html: NOT TRANSLATED YET
personal_details_verified: "¡Detalles personales verificados!"
personal_key: Esta es su nueva clave personal. Escríbala y guárdela en un lugar
seguro. La necesitará si pierde su contraseña.
Expand Down Expand Up @@ -211,6 +214,7 @@ es:
mail:
resend: "¿Desea otra carta?"
verify: "¿Desea una carta?"
otp_delivery_method: NOT TRANSLATED YET
phone: Número de teléfono del registro
review: Revise y envíe
select_verification: Active su cuenta
Expand Down
4 changes: 4 additions & 0 deletions config/locales/idv/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ fr:
send: Envoyer une lettre
return_to_account: NOT TRANSLATED YET
return_to_sp: NOT TRANSLATED YET
send_confirmation_code: NOT TRANSLATED YET
cancel:
modal_header: Souhaitez-vous vraiment annuler?
warning_header: Si vous annulez maintenant
Expand Down Expand Up @@ -136,6 +137,8 @@ fr:
façon dont nous vérifions votre compte.
loading: NOT TRANSLATED YET
mail_sent: Votre lettre est en route
otp_delivery_method:
phone_number_html: NOT TRANSLATED YET
personal_details_verified: Information personnelle vérifiée!
personal_key: Il s'agit de votre nouvelle clé personnelle. Notez-la et conservez-la
dans un endroit sécuritaire. Vous en aurez besoin si vous perdez votre mot
Expand Down Expand Up @@ -223,6 +226,7 @@ fr:
mail:
resend: Vous voulez une autre lettre?
verify: Vous voulez une lettre?
otp_delivery_method: NOT TRANSLATED YET
phone: Numéro de téléphone enregistré
review: Réviser et soumettre
select_verification: Activer votre compte
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@
put '/verify/finance' => 'verify/finance#create'
get '/verify/finance/other' => 'verify/finance_other#new'
get '/verify/finance/result' => 'verify/finance#show'
get '/verify/otp_delivery_method' => 'verify/otp_delivery_method#new'
put '/verify/otp_delivery_method' => 'verify/otp_delivery_method#create'
get '/verify/phone' => 'verify/phone#new'
put '/verify/phone' => 'verify/phone#create'
get '/verify/phone/result' => 'verify/phone#show'
Expand Down
Loading