Skip to content
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
89eebd0
Disable options on MFA setup screen
aduth Oct 27, 2021
e3c007c
Handle vendor outage for setup, sign-in MFA
aduth Oct 27, 2021
d7aa6ca
Handle full outage for IDV phone verification
aduth Oct 27, 2021
4b08e93
Move phone controller redirect to before_action
aduth Nov 2, 2021
e089885
Simplify / remove memoization for gpo_letter_available?
aduth Nov 9, 2021
6d82ce0
Update alert partial to component
aduth Nov 9, 2021
8b3df07
Add "Get Updates" text
aduth Nov 9, 2021
4e2ef25
Show single vendor outage status on phone setup page
aduth Nov 9, 2021
e7a614c
try a VendorOutageAlertComponent component
aduth Nov 9, 2021
d7d7ae9
Fix missing &&
aduth Nov 10, 2021
0bbd8b7
Update MFA to use VendorOutageAlertComponent
aduth Nov 10, 2021
739e83e
Update MFA setup to use VnedorOutageAlertComponent
aduth Nov 10, 2021
acaf598
Update phone setup to use VnedorOutageAlertComponent
aduth Nov 10, 2021
5177b4a
Remove lingering TranslationHelper
aduth Nov 10, 2021
9ad0dda
Restore show_security_level?
aduth Nov 10, 2021
25cf77a
Fix VendorStatus#outage_message errors
aduth Nov 10, 2021
f4cc785
Redirect UsersPhoneController on full phone outage
aduth Nov 10, 2021
e0c9339
Move outages sort to content
aduth Nov 10, 2021
396eb76
Fix Spanish, French vendor outage string nesting
aduth Nov 10, 2021
db7e8fd
Disable options on IAL2 phone OTP verify step
aduth Nov 10, 2021
e0b6012
Update full outage IAL2 message
aduth Nov 10, 2021
faffb76
Add missing sms default alerts translations
aduth Nov 10, 2021
3ea2c0f
Normalize YAML
aduth Nov 10, 2021
41f444a
Show IAL2 welcome page alert on combined full outage
aduth Nov 10, 2021
099a529
Show sign-in alert on combined full phone outage
aduth Nov 10, 2021
fea280d
Add default blocked phone translations
aduth Nov 10, 2021
98fef67
Disable phone mfa option when "phone" type outage
aduth Nov 10, 2021
2e9639b
Use all_phone_vendor_outage? convenience method
aduth Nov 10, 2021
16b7e76
Ensure same page before pulling error from FormStepsWait
aduth Nov 10, 2021
5a98c26
Remove alert banner from MFA setup page during combined outage
aduth Nov 15, 2021
3a488af
Remove alert banner from IAL2 sign in page
aduth Nov 15, 2021
4e980df
Update alert banner text for voice outage
aduth Nov 15, 2021
a376be0
Show alert banner on MFA setup page, only during combined outage
aduth Nov 15, 2021
9eb3029
Add specs for VendorOutageAlertComponent
aduth Nov 15, 2021
f7fec66
Fix parameter only_if_both -> only_if_all
aduth Nov 15, 2021
b1663e1
Redirect to MFA setup only if MFA not yet set up
aduth Nov 15, 2021
13437c9
Explicitly mark contextual translated keys
aduth Nov 15, 2021
3d8e2fb
make grammer good
aduth Nov 15, 2021
15ba6ec
Update tests for FormStepsWait redirect with error
aduth Nov 15, 2021
99f7358
Redirect phone IDV to vendor outage page as part of redirect_to_next_…
aduth Nov 15, 2021
b158d7a
Test VendorOutageController show_gpo_option assignment
aduth Nov 15, 2021
16167d0
Test UsersPhonesController#add redirect on vendor outage
aduth Nov 15, 2021
8079234
Test TwoFactorAuthenticationController
aduth Nov 15, 2021
29fc3b3
Test NewPhoneForm
aduth Nov 15, 2021
ba474d3
Implement disabled in specific selection presenters
aduth Nov 15, 2021
8ede032
Test TwoFactorLoginOptionsPresenter#first_enabled_option_index
aduth Nov 15, 2021
e3b7693
Test new VendorStatus methods
aduth Nov 15, 2021
720604c
Rename IAL2 outage messages to IDV
aduth Nov 15, 2021
402e629
Test IAL2 Welcome step alert
aduth Nov 15, 2021
726c98c
Test IDV OTP delivery method alert, disabled options
aduth Nov 15, 2021
3dab1d0
Test 2FA options alert, disabled options
aduth Nov 15, 2021
8cf4bfa
Test phone setup phone outage alert
aduth Nov 15, 2021
0829157
Test add phone outage alert
aduth Nov 15, 2021
fa5a215
Test _otp_delivery_preference_selection
aduth Nov 15, 2021
9b7f6fc
Test two_factor_authentication_setup/index
aduth Nov 15, 2021
dbe8a6b
Test vendor_outage/show
aduth Nov 15, 2021
76235ef
Add missing "Get Updates" translations
aduth Nov 16, 2021
2b225bf
Add spec for fallback alert message behavior
aduth Nov 16, 2021
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
6 changes: 6 additions & 0 deletions app/components/vendor_outage_alert_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<% if content %>
<%= render(AlertComponent.new(type: :error, class: 'margin-bottom-4')) do %>
<%= content %>
<%= new_window_link_to t('vendor_outage.get_updates'), StatusPage.base_url %>
<% end %>
<% end %>
42 changes: 42 additions & 0 deletions app/components/vendor_outage_alert_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
class VendorOutageAlertComponent < BaseComponent
include LinkHelper

def initialize(vendors:, only_if_all: false, context: 'default')
@vendors = vendors
@only_if_all = only_if_all
@context = context
Comment thread
aduth marked this conversation as resolved.
end

def content
case outages.sort
Comment thread
aduth marked this conversation as resolved.
when [:sms, :voice]
# i18n-tasks-use t('vendor_outage.alerts.phone.default')
# i18n-tasks-use t('vendor_outage.alerts.phone.idv')
t(context, scope: 'vendor_outage.alerts.phone', default: :default)
when [:sms]
# i18n-tasks-use t('vendor_outage.alerts.sms.default')
# i18n-tasks-use t('vendor_outage.alerts.sms.idv')
t(context, scope: 'vendor_outage.alerts.sms', default: :default)
when [:voice]
# i18n-tasks-use t('vendor_outage.alerts.voice.default')
# i18n-tasks-use t('vendor_outage.alerts.voice.idv')
t(context, scope: 'vendor_outage.alerts.voice', default: :default)
end
end

private

attr_reader :vendors, :only_if_all, :context

def outages
if only_if_all
vendor_status.all_vendor_outage?(vendors) ? vendors : []
else
vendors.select { |vendor| vendor_status.vendor_outage?(vendor) }
end
end

def vendor_status
@vendor_status ||= VendorStatus.new
end
end
6 changes: 5 additions & 1 deletion app/controllers/idv/phone_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ def max_attempts_reached

def redirect_to_next_step
if phone_confirmation_required?
redirect_to idv_otp_delivery_method_url
if VendorStatus.new.all_phone_vendor_outage?
redirect_to vendor_outage_path(from: :idv_phone)
else
redirect_to idv_otp_delivery_method_url
end
else
redirect_to idv_review_url
end
Expand Down
6 changes: 6 additions & 0 deletions app/controllers/users/phones_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class PhonesController < ReauthnRequiredController
include PhoneConfirmation

before_action :confirm_two_factor_authenticated
before_action :redirect_if_phone_vendor_outage

def add
user_session[:phone_id] = nil
Expand All @@ -21,6 +22,11 @@ def create

private

def redirect_if_phone_vendor_outage
return unless VendorStatus.new.all_phone_vendor_outage?
redirect_to vendor_outage_path(from: :users_phones)
end

def user_params
params.require(:new_phone_form).permit(
:phone, :international_code,
Expand Down
20 changes: 18 additions & 2 deletions app/controllers/users/two_factor_authentication_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class TwoFactorAuthenticationController < ApplicationController
include TwoFactorAuthenticatable

before_action :check_remember_device_preference
before_action :redirect_to_vendor_outage_if_phone_only, only: [:show]

def show
service_provider_mfa_requirement_redirect || non_phone_redirect || phone_redirect ||
Expand Down Expand Up @@ -33,7 +34,7 @@ def non_phone_redirect
end

def phone_redirect
return unless phone_enabled?
return unless phone_enabled? && !VendorStatus.new.any_phone_vendor_outage?
validate_otp_delivery_preference_and_send_code
true
end
Expand All @@ -44,7 +45,15 @@ def backup_code_redirect
end

def redirect_on_nothing_enabled
redirect_to two_factor_options_url
# "Nothing enabled" can mean one of two things:
# 1. The user hasn't yet set up MFA, and should be redirected to setup path.
# 2. The user has set up MFA, but none of the redirect options are currently available (e.g.
# vendor outage), and they should be sent to the MFA selection path.
if MfaPolicy.new(current_user).two_factor_enabled?
redirect_to login_two_factor_options_path
else
redirect_to two_factor_options_url
end
end

def phone_enabled?
Expand Down Expand Up @@ -117,6 +126,13 @@ def redirect_to_otp_verification_with_error
)
end

def redirect_to_vendor_outage_if_phone_only
return unless VendorStatus.new.all_phone_vendor_outage? &&
phone_enabled? &&
!MfaPolicy.new(current_user).multiple_factors_enabled?
redirect_to vendor_outage_path(from: :two_factor_authentication)
end

def capture_analytics_for_exception(telephony_error)
attributes = {
error: telephony_error.class.to_s,
Expand Down
13 changes: 13 additions & 0 deletions app/controllers/vendor_outage_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ def show
from_idv: session.delete(:vendor_outage_redirect_from_idv),
)
@specific_message = vendor_status.outage_message
@show_gpo_option = from_idv_phone? && gpo_letter_available?
vendor_status.track_event(analytics)
end

private

def from_idv_phone?
params[:from] == 'idv_phone'
end

def gpo_letter_available?
FeatureManagement.enable_gpo_verification? &&
current_user &&
!Idv::GpoMail.new(current_user).mail_spammed?
end
end
4 changes: 2 additions & 2 deletions app/forms/new_phone_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ def submit(params)
end

def delivery_preference_sms?
true
!VendorStatus.new.vendor_outage?(:sms)
end

def delivery_preference_voice?
false
VendorStatus.new.vendor_outage?(:sms)
end

def already_has_phone?
Expand Down
3 changes: 2 additions & 1 deletion app/javascript/packs/form-steps-wait.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ export class FormStepsWait {
this.scheduleNextPollFetch();
} else {
const message = getPageErrorMessage(dom);
if (message) {
const isSamePage = new URL(response.url).pathname === window.location.pathname;
if (message && isSamePage) {
this.renderError(message);
this.stopSpinner();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ def security_level
t('two_factor_authentication.two_factor_choice_options.less_secure_label')
end

def disabled?
VendorStatus.new.all_phone_vendor_outage?
end

private

def masked_number(number)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ def html_class
''
end

def disabled?
false
end

private

def option_mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ class SmsSelectionPresenter < PhoneSelectionPresenter
def method
:sms
end

def disabled?
VendorStatus.new.vendor_outage?(:sms)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ class VoiceSelectionPresenter < PhoneSelectionPresenter
def method
:voice
end

def disabled?
VendorStatus.new.vendor_outage?(:voice)
end
end
end
4 changes: 4 additions & 0 deletions app/presenters/two_factor_login_options_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ def cancel_link
end
end

def first_enabled_option_index
options.find_index { |option| !option.disabled? } || 0
end

private

def account_reset_link
Expand Down
34 changes: 26 additions & 8 deletions app/services/vendor_status.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
class VendorStatus
include ActionView::Helpers::TranslationHelper

def initialize(from: nil, from_idv: nil, sp: nil)
@from = from
@from_idv = from_idv
@sp = sp
end

IAL2_VENDORS = %i[acuant lexisnexis_instant_verify lexisnexis_trueid].freeze
ALL_VENDORS = (IAL2_VENDORS + %i[sms voice]).freeze
PHONE_VENDORS = %i[sms voice].freeze
ALL_VENDORS = (IAL2_VENDORS + PHONE_VENDORS).freeze

def vendor_outage?(vendor)
status = case vendor
Expand All @@ -30,10 +33,22 @@ def any_vendor_outage?(vendors = ALL_VENDORS)
vendors.any? { |vendor| vendor_outage?(vendor) }
end

def all_vendor_outage?(vendors = ALL_VENDORS)
vendors.all? { |vendor| vendor_outage?(vendor) }
end

def any_ial2_vendor_outage?
any_vendor_outage?(IAL2_VENDORS)
end

def any_phone_vendor_outage?
any_vendor_outage?(PHONE_VENDORS)
end

def all_phone_vendor_outage?
all_vendor_outage?(PHONE_VENDORS)
end

def from_idv?
from_idv
end
Expand All @@ -46,16 +61,19 @@ def outage_message
if any_ial2_vendor_outage?
if from_idv?
if sp
return I18n.t(
'vendor_outage.idv_blocked.with_sp',
service_provider: sp.friendly_name,
)
t('vendor_outage.blocked.idv.with_sp', service_provider: sp.friendly_name)
else
return I18n.t('vendor_outage.idv_blocked.without_sp')
t('vendor_outage.blocked.idv.without_sp')
end
else
t('vendor_outage.blocked.idv.generic')
end
elsif any_phone_vendor_outage?
if from_idv?
t('vendor_outage.blocked.phone.idv')
else
t('vendor_outage.blocked.phone.default')
end

return I18n.t('vendor_outage.idv_blocked.generic')
end
end

Expand Down
2 changes: 2 additions & 0 deletions app/views/idv/doc_auth/welcome.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<% title t('titles.doc_auth.verify') %>

<%= render(VendorOutageAlertComponent.new(vendors: [:sms, :voice], only_if_all: true, context: :idv)) %>

<% step = 0 %>

<%= render 'shared/maintenance_window_alert' do %>
Expand Down
4 changes: 4 additions & 0 deletions app/views/idv/otp_delivery_method/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

<% title t('titles.doc_auth.otp_delivery') %>

<%= render(VendorOutageAlertComponent.new(vendors: [:sms, :voice], context: :idv)) %>

<h1 class="margin-y-0">
<%= t('idv.titles.otp_delivery_method') %>
</h1>
Expand All @@ -28,6 +30,7 @@
'otp_delivery_preference',
:sms,
false,
disabled: VendorStatus.new.vendor_outage?(:sms),
class: 'usa-radio__input usa-radio__input--tile',
) %>
<label for="otp_delivery_preference_sms" class="usa-radio__label">
Expand All @@ -41,6 +44,7 @@
'otp_delivery_preference',
:voice,
false,
disabled: VendorStatus.new.vendor_outage?(:voice),
class: 'usa-radio__input usa-radio__input--tile',
) %>
<label for="otp_delivery_preference_voice" class="usa-radio__label">
Expand Down
5 changes: 4 additions & 1 deletion app/views/two_factor_authentication/options/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<% title @presenter.title %>

<%= render(VendorOutageAlertComponent.new(vendors: [:sms, :voice])) %>

<h1 class="margin-y-0">
<%= @presenter.heading %>
</h1>
Expand All @@ -24,7 +26,8 @@
<%= radio_button_tag(
'two_factor_options_form[selection]',
option.type,
index.zero?,
index == @presenter.first_enabled_option_index,
disabled: option.disabled?,
class: "usa-radio__input usa-radio__input--tile",
) %>
<%= label_tag(
Expand Down
3 changes: 3 additions & 0 deletions app/views/users/phone_setup/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<% title t('titles.phone_setup') %>

<%= render(VendorOutageAlertComponent.new(vendors: [:sms, :voice])) %>

<%= image_tag asset_url('2FA-voice.svg'), alt: '', width: 200, class: 'margin-bottom-2' %>

<h1><%= t('titles.phone_setup') %></h1>
Expand Down
2 changes: 2 additions & 0 deletions app/views/users/phones/add.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<%= title t('titles.add_info.phone') %>

<%= render(VendorOutageAlertComponent.new(vendors: [:sms, :voice])) %>

<h1><%= t('headings.add_info.phone') %></h1>

<p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
form_name_label,
:sms,
form_obj.delivery_preference_sms?,
disabled: VendorStatus.new.vendor_outage?(:sms),
class: 'js-otp-delivery-preference usa-radio__input usa-radio__input--bordered',
) %>
<label class="usa-radio__label width-full" for="<%= form_name_tag_sms %>">
Expand All @@ -30,6 +31,7 @@
form_name_label,
:voice,
form_obj.delivery_preference_voice?,
disabled: VendorStatus.new.vendor_outage?(:voice),
class: 'js-otp-delivery-preference usa-radio__input usa-radio__input--bordered',
) %>
<label class="usa-radio__label width-full" for="<%= form_name_tag_voice %>">
Expand Down
Loading