diff --git a/app/controllers/idv/doc_auth_controller.rb b/app/controllers/idv/doc_auth_controller.rb index 2861a53eb7f..b7e96c996a2 100644 --- a/app/controllers/idv/doc_auth_controller.rb +++ b/app/controllers/idv/doc_auth_controller.rb @@ -15,10 +15,6 @@ class DocAuthController < ApplicationController before_action :redirect_if_flow_completed before_action :override_document_capture_step_csp before_action :update_if_skipping_upload - # rubocop:disable Rails/LexicallyScopedActionFilter - before_action :check_for_outage, only: :show - # rubocop:enable Rails/LexicallyScopedActionFilter - before_action :override_csp_for_threat_metrix FLOW_STATE_MACHINE_SETTINGS = { @@ -68,13 +64,5 @@ def do_meta_refresh(meta_refresh_count) def flow_session user_session['idv/doc_auth'] end - - def check_for_outage - if VendorStatus.new.any_ial2_vendor_outage? - session[:vendor_outage_redirect] = current_step - session[:vendor_outage_redirect_from_idv] = true - redirect_to vendor_outage_url - end - end end end diff --git a/app/controllers/idv/unavailable_controller.rb b/app/controllers/idv/unavailable_controller.rb new file mode 100644 index 00000000000..79ffe2bf1e4 --- /dev/null +++ b/app/controllers/idv/unavailable_controller.rb @@ -0,0 +1,34 @@ +module Idv + class UnavailableController < ApplicationController + ALLOWED_FROM_LOCATIONS = [SignUp::RegistrationsController::CREATE_ACCOUNT] + + before_action :redirect_if_idv_available_and_from_create_account + + def show + analytics.vendor_outage( + vendor_status: { + acuant: IdentityConfig.store.vendor_status_acuant, + lexisnexis_instant_verify: IdentityConfig.store.vendor_status_lexisnexis_instant_verify, + lexisnexis_trueid: IdentityConfig.store.vendor_status_lexisnexis_trueid, + sms: IdentityConfig.store.vendor_status_sms, + voice: IdentityConfig.store.vendor_status_voice, + }, + redirect_from: from, + ) + end + + private + + def from + params[:from] if ALLOWED_FROM_LOCATIONS.include?(params[:from]) + end + + def from_create_account? + from == SignUp::RegistrationsController::CREATE_ACCOUNT + end + + def redirect_if_idv_available_and_from_create_account + redirect_to sign_up_email_url if FeatureManagement.idv_available? && from_create_account? + end + end +end diff --git a/app/controllers/sign_up/registrations_controller.rb b/app/controllers/sign_up/registrations_controller.rb index 19204b5c997..8104421b7f4 100644 --- a/app/controllers/sign_up/registrations_controller.rb +++ b/app/controllers/sign_up/registrations_controller.rb @@ -72,10 +72,9 @@ def sp_request_id end def redirect_if_ial2_and_vendor_outage - return unless ial2_requested? && VendorStatus.new.any_ial2_vendor_outage? - - session[:vendor_outage_redirect] = CREATE_ACCOUNT - return redirect_to vendor_outage_url + if ial2_requested? && !FeatureManagement.idv_available? + redirect_to idv_unavailable_path(from: CREATE_ACCOUNT) + end end end end diff --git a/app/controllers/vendor_outage_controller.rb b/app/controllers/vendor_outage_controller.rb index ab47989c85e..e81874099e3 100644 --- a/app/controllers/vendor_outage_controller.rb +++ b/app/controllers/vendor_outage_controller.rb @@ -2,8 +2,6 @@ class VendorOutageController < ApplicationController def show vendor_status = VendorStatus.new( sp: current_sp, - from: session.delete(:vendor_outage_redirect), - from_idv: session.delete(:vendor_outage_redirect_from_idv), ) @specific_message = vendor_status.outage_message @show_gpo_option = from_idv_phone? && gpo_letter_available? diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index 445d71961fd..810df9e3f0e 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -2901,12 +2901,12 @@ def user_registration_2fa_setup_visit track_event('User Registration: 2FA Setup visited') end - # @param [String] redirect_from + # @param [String,nil] redirect_from # @param [Hash] vendor_status # Tracks when vendor has outage def vendor_outage( - redirect_from:, vendor_status:, + redirect_from: nil, **extra ) track_event( diff --git a/app/services/vendor_status.rb b/app/services/vendor_status.rb index 32af74b2370..7fb3bb906b4 100644 --- a/app/services/vendor_status.rb +++ b/app/services/vendor_status.rb @@ -1,9 +1,7 @@ class VendorStatus include ActionView::Helpers::TranslationHelper - def initialize(from: nil, from_idv: nil, sp: nil) - @from = from - @from_idv = from_idv + def initialize(sp: nil) @sp = sp end @@ -49,31 +47,15 @@ def all_phone_vendor_outage? all_vendor_outage?(PHONE_VENDORS) end - def from_idv? - from_idv - end - # Returns an appropriate error message based upon the type of outage or what the user was doing # when they encountered the outage. # # @return [String, nil] the localized message. def outage_message if any_ial2_vendor_outage? - if from_idv? - if sp - t('vendor_outage.blocked.idv.with_sp', service_provider: sp.friendly_name) - else - t('vendor_outage.blocked.idv.without_sp') - end - else - t('vendor_outage.blocked.idv.generic') - end + t('vendor_outage.blocked.idv.generic') elsif any_phone_vendor_outage? - if from_idv? - t('vendor_outage.blocked.phone.idv') - else - t('vendor_outage.blocked.phone.default') - end + t('vendor_outage.blocked.phone.default') end end @@ -88,11 +70,10 @@ def track_event(analytics) sms: IdentityConfig.store.vendor_status_sms, voice: IdentityConfig.store.vendor_status_voice, }, - redirect_from: from, ) end private - attr_reader :from, :from_idv, :sp + attr_reader :sp end diff --git a/app/views/idv/unavailable/show.html.erb b/app/views/idv/unavailable/show.html.erb new file mode 100644 index 00000000000..a1d2cf21210 --- /dev/null +++ b/app/views/idv/unavailable/show.html.erb @@ -0,0 +1,38 @@ +<% title t('idv.titles.unavailable') %> + +<%= render StatusPageComponent.new(status: :error) do |c| %> + + <% c.header { t('idv.titles.unavailable') } %> + +

+ <% if decorated_session.sp_name.present? %> + <%= t('idv.unavailable.idv_explanation.with_sp', sp: decorated_session.sp_name) %> + <% else %> + <%= t('idv.unavailable.idv_explanation.without_sp') %> + <% end %> +

+ +

+ <%= t( + 'idv.unavailable.next_steps_html', + app_name: APP_NAME, + status_page_link: new_window_link_to( + t('idv.unavailable.status_page_link'), + StatusPage.base_url, + ), + ) %> +

+ + <% c.action_button( + action: ->(**tag_options, &block) do + link_to( + return_to_sp_failure_to_proof_path(location: :unavailable), + **tag_options, + &block + ) + end, + big: true, + wide: true, + ).with_content(t('idv.unavailable.exit_button', app_name: APP_NAME)) %> + +<% end %> diff --git a/config/application.yml.default b/config/application.yml.default index c421f959f4a..2c35d5a3e82 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -120,6 +120,7 @@ hide_phone_mfa_signup: false identity_pki_disabled: false identity_pki_local_dev: false idv_attempt_window_in_hours: 6 +idv_available: true idv_contact_url: https://www.example.com idv_contact_phone_number: (844) 555-5555 idv_max_attempts: 5 diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index bf02a3e1993..6c562e1aa5f 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -199,6 +199,7 @@ en: session: phone: Enter your phone number review: Re-enter your %{app_name} password to protect your data + unavailable: 'We are working to resolve an error' troubleshooting: headings: missing_required_items: Are you missing one of these items? @@ -215,6 +216,17 @@ en: learn_more_verify_in_person: Learn more about verifying in person supported_documents: See a list of accepted state-issued IDs verify_by_mail: Verify your address by mail instead + unavailable: + exit_button: 'Exit %{app_name}' + idv_explanation: + with_sp: '%{sp} needs to make sure you are you — not someone pretending to be + you.' + without_sp: 'The agency that you are trying to access needs to make sure you are + you — not someone pretending to be you.' + next_steps_html: 'Unfortunately, we are having technical difficulties and cannot + verify your identity at this time. %{status_page_link} or exit + %{app_name} and try again later.' + status_page_link: 'Get updates on our status page' welcome: no_js_header: You must enable JavaScript to verify your identity. no_js_intro: '%{sp_name} needs you to verify your identity. You need to enable diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index 62e927149fa..2b83307873f 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -213,6 +213,7 @@ es: session: phone: Introduzca su número de teléfono review: Vuelve a ingresar tu contraseña de %{app_name} para encriptar tus datos + unavailable: Estamos trabajando para resolver un error troubleshooting: headings: missing_required_items: '¿Le falta alguno de estos puntos?' @@ -231,6 +232,18 @@ es: supported_documents: Vea la lista de documentos de identidad emitidos por el estado que son aceptados verify_by_mail: Verifique su dirección por correo + unavailable: + exit_button: 'Salir de %{app_name}' + idv_explanation: + with_sp: '%{sp} necesita asegurarse de que es usted realmente y no alguien que + se hace pasar por usted.' + without_sp: 'La agencia a la que está intentando acceder debe asegurarse de que + usted sea quien dice ser, y no alguien que se hace pasar por usted.' + next_steps_html: 'Lamentablemente, debido a problemas técnicos por nuestra + parte, tal vez no podamos verificar su identidad en estos momentos. + %{status_page_link} o salga de %{app_name} y vuelva a intentarlo más + tarde.' + status_page_link: 'Consulte las actualizaciones en nuestra página de estado' welcome: no_js_header: Debe habilitar JavaScript para verificar su identidad. no_js_intro: '%{sp_name} requiere que usted verifique su identidad. Debe diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml index a7406a5ff3c..63c75ea465e 100644 --- a/config/locales/idv/fr.yml +++ b/config/locales/idv/fr.yml @@ -227,6 +227,7 @@ fr: session: phone: Entrez votre numéro de téléphone review: Entrez à nouveau votre mot de passe %{app_name} pour crypter vos données + unavailable: Nous travaillons à la résolution d’une erreur troubleshooting: headings: missing_required_items: Est-ce qu’il vous manque un de ces éléments? @@ -245,6 +246,19 @@ fr: learn_more_verify_in_person: En savoir plus sur la vérification en personne supported_documents: Voir la liste des pièces d’identité acceptées et délivrées par l’État verify_by_mail: Vérifiez plutôt votre adresse par courrier + unavailable: + exit_button: 'Quitter %{app_name}' + idv_explanation: + with_sp: '%{sp} doit s’assurer que c’est bien vous — et non quelqu’un qui se + fait passer pour vous.' + without_sp: 'L’agence à laquelle vous essayez d’accéder doit s’assurer qu’il + s’agit bien de vous, et non de quelqu’un qui se fait passer pour + vous.' + next_steps_html: 'Malheureusement, nous rencontrons des difficultés techniques + et ne pouvons pas vérifier votre identité pour le moment. + %{status_page_link} ou quittez le site %{app_name} et réessayez plus + tard.' + status_page_link: 'Obtenez des mises à jour sur notre page de statut' welcome: no_js_header: Vous devez activer JavaScript pour vérifier votre identité. no_js_intro: '%{sp_name} a besoin de vous pour vérifier votre identité. Vous diff --git a/config/locales/vendor_outage/en.yml b/config/locales/vendor_outage/en.yml index 4fa7ff9debc..d0d7febfcb5 100644 --- a/config/locales/vendor_outage/en.yml +++ b/config/locales/vendor_outage/en.yml @@ -22,18 +22,8 @@ en: idv: generic: We are having technical difficulties on our end and cannot verify your identity at this time. Please try again later. - with_sp: '%{service_provider} needs to make sure you are you — not someone - pretending to be you. Unfortunately, we are having technical - difficulties and cannot verify your identity at this time. Please try - again later.' - without_sp: The agency that you are trying to access needs to make sure you are - you — not someone pretending to be you. Unfortunately, we are having - technical difficulties and cannot verify your identity at this time. - Please try again later. phone: default: We cannot verify phones at this time. Please try again later. - idv: We cannot verify phones at this time. Please try again later or verify your - address by mail instead. get_updates: Get updates get_updates_on_status_page: Get updates on our status page working: We are working to resolve an error diff --git a/config/locales/vendor_outage/es.yml b/config/locales/vendor_outage/es.yml index 094859a4cd5..bdd0f6530ab 100644 --- a/config/locales/vendor_outage/es.yml +++ b/config/locales/vendor_outage/es.yml @@ -28,22 +28,9 @@ es: generic: Debido a problemas técnicos por nuestra parte, no podemos verificar su identidad en estos momentos. Por favor, inténtelo nuevamente más tarde. - with_sp: '%{service_provider} necesita asegurarse de que es usted realmente y no - alguien que se hace pasar por usted. Lamentablemente, debido a - problemas técnicos por nuestra parte, tal vez no podamos verificar su - identidad en estos momentos. Por favor, inténtelo nuevamente más - tarde.' - without_sp: La agencia a la que está intentando acceder debe asegurarse de que - usted sea quien dice ser, y no alguien que se hace pasar por usted. - Lamentablemente, debido a problemas técnicos por nuestra parte, tal - vez no podamos verificar su identidad en estos momentos. Por favor, - inténtelo nuevamente más tarde. phone: default: No podemos verificar teléfonos en estos momentos. Por favor, inténtelo nuevamente más tarde. - idv: No podemos verificar teléfonos en estos momentos. Por favor, inténtelo - nuevamente más tarde o, en lugar de ello, verifique su dirección por - correo. get_updates: Obtenga actualizaciones get_updates_on_status_page: Reciba actualizaciones en nuestra página de estado working: Estamos trabajando para corregir un error diff --git a/config/locales/vendor_outage/fr.yml b/config/locales/vendor_outage/fr.yml index 83b80e5cd91..ade32517d24 100644 --- a/config/locales/vendor_outage/fr.yml +++ b/config/locales/vendor_outage/fr.yml @@ -26,20 +26,9 @@ fr: idv: generic: Nous rencontrons des difficultés techniques et ne pouvons pas vérifier votre identité pour le moment. Veuillez réessayer plus tard. - with_sp: '%{service_provider} doit s’assurer que c’est bien vous — et non - quelqu’un qui se fait passer pour vous. Malheureusement, nous - rencontrons des difficultés techniques et ne pouvons pas vérifier - votre identité pour le moment. Veuillez réessayer plus tard.' - without_sp: L’agence à laquelle vous essayez d’accéder doit s’assurer qu’il - s’agit bien de vous, et non de quelqu’un qui se fait passer pour vous. - Malheureusement, nous rencontrons des difficultés techniques et ne - pouvons pas vérifier votre identité pour le moment. Veuillez réessayer - plus tard. phone: default: Nous ne pouvons pas vérifier les téléphones pour le moment. Veuillez réessayer plus tard. - idv: Nous ne pouvons pas vérifier les téléphones pour le moment. Veuillez - réessayer plus tard ou vérifier votre adresse par la poste. get_updates: Obtenir des mises à jour get_updates_on_status_page: Obtenez des mises à jour sur notre page de statut working: Nous travaillons à la résolution d’une erreur diff --git a/config/routes.rb b/config/routes.rb index b4d4e9db409..a1fc84cfbe2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -62,7 +62,8 @@ put '/users/password' => 'users/reset_passwords#update', as: nil post '/users/password' => 'users/reset_passwords#create', as: nil - get '/account/forget_all_browsers' => 'users/forget_all_browsers#show', as: :forget_all_browsers + get '/account/forget_all_browsers' => 'users/forget_all_browsers#show', + as: :forget_all_browsers delete '/account/forget_all_browsers' => 'users/forget_all_browsers#destroy' get '/account/service_providers/:sp_id/revoke' => 'users/service_provider_revoke#show', @@ -185,7 +186,8 @@ get '/account/reactivate/start' => 'reactivate_account#index', as: :reactivate_account put '/account/reactivate/start' => 'reactivate_account#update' get '/account/reactivate/verify_password' => 'users/verify_password#new', as: :verify_password - put '/account/reactivate/verify_password' => 'users/verify_password#update', as: :update_verify_password + put '/account/reactivate/verify_password' => 'users/verify_password#update', + as: :update_verify_password get '/account/reactivate/verify_personal_key' => 'users/verify_personal_key#new', as: :verify_personal_key post '/account/reactivate/verify_personal_key' => 'users/verify_personal_key#create', @@ -205,7 +207,8 @@ get '/piv_cac' => 'users/piv_cac_authentication_setup#new', as: :setup_piv_cac get '/piv_cac_error' => 'users/piv_cac_authentication_setup#error', as: :setup_piv_cac_error delete '/piv_cac' => 'users/piv_cac_authentication_setup#delete', as: :disable_piv_cac - post '/present_piv_cac' => 'users/piv_cac_authentication_setup#submit_new_piv_cac', as: :submit_new_piv_cac + post '/present_piv_cac' => 'users/piv_cac_authentication_setup#submit_new_piv_cac', + as: :submit_new_piv_cac get '/webauthn_setup' => 'users/webauthn_setup#new', as: :webauthn_setup patch '/webauthn_setup' => 'users/webauthn_setup#confirm' @@ -283,12 +286,14 @@ post '/sign_up/completed' => 'sign_up/completions#update' get '/user_authorization_confirmation' => 'users/authorization_confirmation#new' post '/user_authorization_confirmation' => 'users/authorization_confirmation#create' - match '/user_authorization_confirmation/reset' => 'users/authorization_confirmation#destroy', as: :reset_user_authorization, via: %i[put delete] + match '/user_authorization_confirmation/reset' => 'users/authorization_confirmation#destroy', + as: :reset_user_authorization, via: %i[put delete] get '/sign_up/cancel/' => 'sign_up/cancellations#new', as: :sign_up_cancel delete '/sign_up/cancel' => 'sign_up/cancellations#destroy', as: :sign_up_destroy get '/redirect/return_to_sp/cancel' => 'redirect/return_to_sp#cancel', as: :return_to_sp_cancel - get '/redirect/return_to_sp/failure_to_proof' => 'redirect/return_to_sp#failure_to_proof', as: :return_to_sp_failure_to_proof + get '/redirect/return_to_sp/failure_to_proof' => 'redirect/return_to_sp#failure_to_proof', + as: :return_to_sp_failure_to_proof get '/redirect/help_center' => 'redirect/help_center#show', as: :help_center_redirect get '/redirect/contact/' => 'redirect/contact#show', as: :contact_redirect @@ -296,11 +301,17 @@ get '/restricted' => 'banned_user#show', as: :banned_user + get '/errors/idv_unavailable' => 'idv/unavailable#show', as: :idv_unavailable + scope '/verify', as: 'idv' do get '/' => 'idv#index' get '/activated' => 'idv#activated' end scope '/verify', module: 'idv', as: 'idv' do + if !FeatureManagement.idv_available? + # IdV has been disabled. + match '/*path' => 'unavailable#show', via: %i[get post] + end get '/come_back_later' => 'come_back_later#show' get '/personal_key' => 'personal_key#show' post '/personal_key' => 'personal_key#update' diff --git a/lib/feature_management.rb b/lib/feature_management.rb index 7763cc92c32..353ec46316b 100644 --- a/lib/feature_management.rb +++ b/lib/feature_management.rb @@ -15,6 +15,11 @@ def self.identity_pki_disabled? !IdentityConfig.store.piv_cac_verify_token_url end + def self.idv_available? + return false if !IdentityConfig.store.idv_available + !VendorStatus.new.any_ial2_vendor_outage? + end + def self.development_and_identity_pki_disabled? # This controls if we try to hop over to identity-pki or just throw up # a screen asking for a Subject or one of a list of error conditions. diff --git a/lib/identity_config.rb b/lib/identity_config.rb index 3b100b9cb70..74325515d9c 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -199,6 +199,7 @@ def self.build_store(config_map) config.add(:identity_pki_disabled, type: :boolean) config.add(:identity_pki_local_dev, type: :boolean) config.add(:idv_attempt_window_in_hours, type: :integer) + config.add(:idv_available, type: :boolean) config.add(:idv_contact_url, type: :string) config.add(:idv_contact_phone_number, type: :string) config.add(:idv_max_attempts, type: :integer) diff --git a/spec/controllers/idv/unavailable_controller_spec.rb b/spec/controllers/idv/unavailable_controller_spec.rb new file mode 100644 index 00000000000..2fd3442f60b --- /dev/null +++ b/spec/controllers/idv/unavailable_controller_spec.rb @@ -0,0 +1,82 @@ +require 'rails_helper' + +describe Idv::UnavailableController, type: :controller do + let(:idv_available) { false } + + before do + allow(IdentityConfig.store).to receive(:idv_available).and_return(idv_available) + end + + describe '#show' do + let(:params) { nil } + + before do + stub_analytics + get :show, params: params + end + + it 'returns 200 OK' do + # https://http.cat/200 + expect(response.status).to eql(200) + end + + it 'logs an analytics event' do + expect(@analytics).to have_logged_event( + 'Vendor Outage', + redirect_from: nil, + vendor_status: { + acuant: :operational, + lexisnexis_instant_verify: :operational, + lexisnexis_trueid: :operational, + sms: :operational, + voice: :operational, + }, + ) + end + + it 'renders the view' do + expect(response).to render_template('idv/unavailable/show') + end + + context 'coming from the create account page' do + let(:params) do + { from: SignUp::RegistrationsController::CREATE_ACCOUNT } + end + it 'logs an analytics event' do + expect(@analytics).to have_logged_event( + 'Vendor Outage', + redirect_from: SignUp::RegistrationsController::CREATE_ACCOUNT, + vendor_status: { + acuant: :operational, + lexisnexis_instant_verify: :operational, + lexisnexis_trueid: :operational, + sms: :operational, + voice: :operational, + }, + ) + end + it 'renders the view' do + expect(response).to render_template('idv/unavailable/show') + end + end + + context 'IdV is enabled' do + let(:idv_available) { true } + + it 'renders the view' do + expect(response).to render_template('idv/unavailable/show') + end + + it 'returns a 200' do + expect(response.status).to eql(200) + end + + context 'coming from the create account page' do + let(:params) { { from: SignUp::RegistrationsController::CREATE_ACCOUNT } } + it 'redirects back to create account' do + expect(response).to redirect_to(sign_up_email_path) + end + end + end + end +end diff --git a/spec/controllers/sign_up/registrations_controller_spec.rb b/spec/controllers/sign_up/registrations_controller_spec.rb index 4d9964e8bdc..6f3511ad465 100644 --- a/spec/controllers/sign_up/registrations_controller_spec.rb +++ b/spec/controllers/sign_up/registrations_controller_spec.rb @@ -25,6 +25,19 @@ expect { get :new }. to raise_error(Mime::Type::InvalidMimeType) end + + context 'IdV unavailable' do + before do + allow(IdentityConfig.store).to receive(:idv_available).and_return(false) + end + it 'redirects to idv vendor outage page when ial2 requested' do + allow(controller).to receive(:ial2_requested?).and_return(true) + get :new + expect(response).to redirect_to( + idv_unavailable_path(from: SignUp::RegistrationsController::CREATE_ACCOUNT), + ) + end + end end describe '#create' do diff --git a/spec/features/idv/vendor_outage_spec.rb b/spec/features/idv/vendor_outage_spec.rb index 853fc247011..b8c71edb734 100644 --- a/spec/features/idv/vendor_outage_spec.rb +++ b/spec/features/idv/vendor_outage_spec.rb @@ -8,11 +8,19 @@ let(:new_password) { 'some really awesome new password' } let(:pii) { { ssn: '666-66-1234', dob: '1920-01-01', first_name: 'alice' } } + after(:all) do + # Reload routes now that config changes made in various contexts have been torn down + Rails.application.reload_routes! + end + %w[acuant lexisnexis_instant_verify lexisnexis_trueid].each do |service| context "full outage on #{service}" do before do allow(IdentityConfig.store).to receive("vendor_status_#{service}".to_sym). and_return(:full_outage) + + # Force route reload to pick up route changes implied by above config change + Rails.application.reload_routes! end it 'prevents an existing ial1 user from verifying their identity' do @@ -20,14 +28,14 @@ sign_in_user(user_with_2fa) fill_in_code_with_last_phone_otp click_submit_default - expect(current_path).to eq vendor_outage_path + expect(page).to have_http_status(200) expect(page).to have_content( - t('vendor_outage.blocked.idv.with_sp', service_provider: 'Test SP'), + t('idv.unavailable.idv_explanation.with_sp', sp: 'Test SP'), ) end it 'prevents a user who reset their password from reactivating profile with no personal key', - email: true, js: true do + email: true, js: true, allow_browser_log: true do personal_key_from_pii(user, pii) trigger_reset_password_and_click_email_link(user.email) reset_password(user, new_password) @@ -41,15 +49,14 @@ click_on t('links.account.reactivate.without_key') click_on t('forms.buttons.continue') - expect(current_path).to eq vendor_outage_path - expect(page).to have_content(t('vendor_outage.blocked.idv.without_sp')) + expect(page).to have_content(t('idv.unavailable.idv_explanation.without_sp')) end it 'prevents a user from creating an account' do visit_idp_from_sp_with_ial2(:oidc) click_link t('links.create_account') - expect(current_path).to eq vendor_outage_path - expect(page).to have_content(t('vendor_outage.blocked.idv.generic')) + + expect(page).to have_content(t('idv.unavailable.idv_explanation.with_sp', sp: 'Test SP')) end end end diff --git a/spec/lib/feature_management_spec.rb b/spec/lib/feature_management_spec.rb index 2af24ac3a32..fa6ac652c99 100644 --- a/spec/lib/feature_management_spec.rb +++ b/spec/lib/feature_management_spec.rb @@ -461,4 +461,46 @@ end end end + + describe '#idv_available?' do + let(:idv_available) { true } + let(:vendor_status_acuant) { :operational } + let(:vendor_status_lexisnexis_instant_verify) { :operational } + let(:vendor_status_lexisnexis_trueid) { :operational } + + before do + allow(IdentityConfig.store).to receive(:idv_available).and_return(idv_available) + allow(IdentityConfig.store).to receive(:vendor_status_acuant).and_return(vendor_status_acuant) + allow(IdentityConfig.store).to receive(:vendor_status_lexisnexis_instant_verify). + and_return(vendor_status_lexisnexis_instant_verify) + allow(IdentityConfig.store).to receive(:vendor_status_lexisnexis_trueid). + and_return(vendor_status_lexisnexis_trueid) + end + + it 'returns true by default' do + expect(FeatureManagement.idv_available?).to eql(true) + end + + context 'idv has been disabled using config flag' do + let(:idv_available) { false } + it 'returns false' do + expect(FeatureManagement.idv_available?).to eql(false) + end + end + + %w[acuant lexisnexis_instant_verify lexisnexis_trueid].each do |service| + context "#{service} is in :full_outage" do + let("vendor_status_#{service}".to_sym) { :full_outage } + it 'returns false' do + expect(FeatureManagement.idv_available?).to eql(false) + end + end + context "#{service} is in :partial_outage" do + let("vendor_status_#{service}".to_sym) { :partial_outage } + it 'returns false' do + expect(FeatureManagement.idv_available?).to eql(false) + end + end + end + end end diff --git a/spec/services/vendor_status_spec.rb b/spec/services/vendor_status_spec.rb index bd59e003aff..681b0847726 100644 --- a/spec/services/vendor_status_spec.rb +++ b/spec/services/vendor_status_spec.rb @@ -1,11 +1,9 @@ require 'rails_helper' describe VendorStatus do - let(:from) { nil } - let(:from_idv) { nil } let(:sp) { nil } subject(:vendor_status) do - VendorStatus.new(from: from, from_idv: from_idv, sp: sp) + VendorStatus.new(sp: sp) end it 'raises an error if passed an unknown vendor' do @@ -51,40 +49,6 @@ it 'correctly reports an ial2 vendor outage' do expect(subject.any_ial2_vendor_outage?).to be end - - context 'user coming from create_account' do - let(:from) { SignUp::RegistrationsController::CREATE_ACCOUNT } - - it 'returns the correct message' do - expect(subject.outage_message).to eq I18n.t('vendor_outage.blocked.idv.generic') - end - end - - context 'user coming from idv flow' do - let(:from) { :welcome } - let(:from_idv) { true } - - context 'no service_provider in session' do - it 'returns the correct message' do - expect(subject.outage_message).to eq( - I18n.t('vendor_outage.blocked.idv.without_sp'), - ) - end - end - - context 'with service_provider in session' do - let(:sp) { create(:service_provider) } - - it 'returns the correct message tailored to the service provider' do - expect(subject.outage_message).to eq( - I18n.t( - 'vendor_outage.blocked.idv.with_sp', - service_provider: sp.friendly_name, - ), - ) - end - end - end end context 'when a non-ial2 vendor has an outage' do @@ -171,14 +135,6 @@ it 'returns default phone outage message' do expect(outage_message).to eq(t('vendor_outage.blocked.phone.default')) end - - context 'from idv' do - let(:from_idv) { true } - - it 'returns idv phone outage message' do - expect(outage_message).to eq(t('vendor_outage.blocked.phone.idv')) - end - end end end @@ -187,7 +143,7 @@ analytics = FakeAnalytics.new expect(analytics).to receive(:track_event).with( 'Vendor Outage', - redirect_from: from, + redirect_from: nil, vendor_status: VendorStatus::ALL_VENDORS.index_with do |_vendor| satisfy { |status| IdentityConfig::VENDOR_STATUS_OPTIONS.include?(status) } end, diff --git a/spec/views/idv/unavailable/show.html.erb_spec.rb b/spec/views/idv/unavailable/show.html.erb_spec.rb new file mode 100644 index 00000000000..502a5e2f796 --- /dev/null +++ b/spec/views/idv/unavailable/show.html.erb_spec.rb @@ -0,0 +1,52 @@ +require 'rails_helper' + +describe 'idv/unavailable/show.html.erb' do + let(:sp_name) { nil } + subject(:rendered) { render } + + before do + allow(view).to receive(:decorated_session).and_return( + instance_double(ServiceProviderSessionDecorator, sp_name: sp_name), + ) + end + + it 'sets a title' do + expect(view).to receive(:title).with(t('idv.titles.unavailable')) + render + end + it 'has an h1' do + expect(rendered).to have_selector('h1', text: t('idv.titles.unavailable')) + end + it 'links to the status page in a new window' do + expect(rendered).to have_selector( + 'a[target=_blank]', + text: t('idv.unavailable.status_page_link'), + ) + end + + describe('exit button') do + it 'is rendered' do + expect(rendered).to have_selector( + 'a', + text: t('idv.unavailable.exit_button', app_name: APP_NAME), + ) + end + it 'links to the right place' do + expect(rendered).to have_link( + t('idv.unavailable.exit_button', app_name: APP_NAME), + href: return_to_sp_failure_to_proof_path(location: 'unavailable'), + ) + end + end + + it 'does not render any l13n markers' do + expect(rendered).not_to include('%{') + end + + context 'with sp' do + let(:sp_name) { 'Department of Ice Cream' } + it 'renders the explanation with the sp name' do + expect(rendered).to include(sp_name) + end + end +end