diff --git a/.reek b/.reek index 2aff7e03d26..a6b0daf18b8 100644 --- a/.reek +++ b/.reek @@ -80,10 +80,7 @@ UtilityFunction: - SessionTimeoutWarningHelper#frequency - SessionTimeoutWarningHelper#start - SessionTimeoutWarningHelper#warning - - SessionDecorator#registration_heading - - SessionDecorator#registration_bullet_1 - - SessionDecorator#new_session_heading - - SessionDecorator#timeout_flash_text + - SessionDecorator - WorkerHealthChecker::Middleware#call - UserEncryptedAttributeOverrides#create_fingerprint 'app/controllers': diff --git a/app/controllers/verify/finance_controller.rb b/app/controllers/verify/finance_controller.rb index d3613344cc3..1e0a5795d74 100644 --- a/app/controllers/verify/finance_controller.rb +++ b/app/controllers/verify/finance_controller.rb @@ -19,7 +19,7 @@ def create increment_step_attempts if result.success? - redirect_to verify_address_url + handle_success else render_failure render_form @@ -28,6 +28,11 @@ def create private + def handle_success + flash[:success] = t('idv.messages.personal_details_verified') + redirect_to verify_address_url + end + def step_name :financials end diff --git a/app/controllers/verify/sessions_controller.rb b/app/controllers/verify/sessions_controller.rb index 786d64ca4a1..bd5b199c245 100644 --- a/app/controllers/verify/sessions_controller.rb +++ b/app/controllers/verify/sessions_controller.rb @@ -6,7 +6,7 @@ class SessionsController < ApplicationController before_action :confirm_two_factor_authenticated, except: [:destroy] before_action :confirm_idv_attempts_allowed before_action :confirm_idv_needed - before_action :confirm_step_needed + before_action :confirm_step_needed, except: [:destroy] helper_method :idv_profile_form helper_method :step @@ -30,7 +30,8 @@ def create end def destroy - user_session[:idv].clear + idv_session = user_session[:idv] + idv_session && idv_session.clear handle_idv_redirect end diff --git a/app/decorators/service_provider_session_decorator.rb b/app/decorators/service_provider_session_decorator.rb index 34a17881c2b..1cef22fe8b1 100644 --- a/app/decorators/service_provider_session_decorator.rb +++ b/app/decorators/service_provider_session_decorator.rb @@ -14,14 +14,6 @@ def nav_partial 'shared/nav_branded' end - def new_session_heading - I18n.t('headings.sign_in_with_sp', sp: sp_name) - end - - def sp_name - sp.friendly_name || sp.agency - end - def registration_heading sp = ActionController::Base.helpers.content_tag(:strong, sp_name) ActionController::Base.helpers.safe_join( @@ -29,6 +21,14 @@ def registration_heading ) end + def new_session_heading + I18n.t('headings.sign_in_with_sp', sp: sp_name) + end + + def verification_method_choice + I18n.t('idv.messages.select_verification_with_sp', sp_name: sp_name) + end + def idv_hardfail4_partial 'verify/hardfail4' end @@ -48,6 +48,10 @@ def timeout_flash_text ) end + def sp_name + sp.friendly_name || sp.agency + end + def sp_return_url sp.return_to_sp_url end diff --git a/app/decorators/session_decorator.rb b/app/decorators/session_decorator.rb index 8d7eb710fe9..c58ae8b80fa 100644 --- a/app/decorators/session_decorator.rb +++ b/app/decorators/session_decorator.rb @@ -15,6 +15,10 @@ def new_session_heading I18n.t('headings.sign_in_without_sp') end + def verification_method_choice + I18n.t('idv.messages.select_verification_without_sp') + end + def idv_hardfail4_partial 'shared/null' end diff --git a/app/views/verify/address/index.html.slim b/app/views/verify/address/index.html.slim index cc07f2daa89..75c1d9cefd1 100644 --- a/app/views/verify/address/index.html.slim +++ b/app/views/verify/address/index.html.slim @@ -1,5 +1,14 @@ -p Pick an address verification mechanism +h1.h2 + = t('idv.titles.select_verification') +p + = decorated_session.verification_method_choice -p =link_to 'Phone', verify_phone_path +.clearfix + .sm-col.sm-col-12.md-col-6 + = link_to t('idv.buttons.activate_by_phone'), verify_phone_path, + class: 'btn btn-primary mb2 center inline-block' + .sm-col.sm-col-12.md-col-6 + = link_to t('idv.buttons.activate_by_mail'), verify_usps_path, + class: 'btn btn-outline rounded-lg mb2 center' -p =link_to 'USPS', verify_usps_path += render 'shared/cancel', link: verify_cancel_path diff --git a/app/views/verify/phone/new.html.slim b/app/views/verify/phone/new.html.slim index 08ba1ab4e65..234ea50c642 100644 --- a/app/views/verify/phone/new.html.slim +++ b/app/views/verify/phone/new.html.slim @@ -1,23 +1,33 @@ - title @view_model.title = render @view_model.mock_vendor_partial -h1.h3.my0 = t('idv.titles.session.phone') -p.mt-tiny.mb0 = t('idv.messages.phone.intro') -ul.py1.m0 - li - strong= t('idv.messages.phone.is_not') - = t('idv.messages.phone.virtual') - li - strong= t('idv.messages.phone.is_not') - = t('idv.messages.phone.prepaid') - li - strong= t('idv.messages.phone.is') - = t('idv.messages.phone.in_your_name') -p = t('idv.messages.phone.same_as_2fa') +h1.h2.my0 = t('idv.titles.session.phone') +p.mt-tiny.mb2 = t('idv.messages.phone.intro') + +.alert.alert-warning + strong + = t('idv.messages.phone.alert') + ul.py1.m0.px0 + li + = t('idv.messages.phone.in_your_name') + li + = t('idv.messages.phone.prepaid') + +em + = t('idv.messages.phone.same_as_2fa') = simple_form_for(idv_phone_form, url: verify_phone_path, - html: { autocomplete: 'off', method: :put, role: 'form' }) do |f| - = f.input :phone, required: true, input_html: { class: 'phone' } - = f.button :submit, t('forms.buttons.continue'), class: 'btn btn-primary btn-wide' -= render 'shared/cancel', link: verify_address_path + html: { autocomplete: 'off', method: :put, role: 'form', class: 'mt2' }) do |f| + = f.label :phone, label: t('idv.form.phone'), class: 'bold' + span.ml1 + em + = t('idv.form.phone_label_aside') + = f.input :phone, required: true, input_html: { class: 'phone' }, label: false, + wrapper_html: { class: 'inline-block mr2' } + = f.button :submit, t('forms.buttons.continue') + +p + = t('idv.form.no_alternate_phone_html', + link: link_to(t('idv.form.activate_by_mail'), verify_usps_path)) + = render @view_model.modal_partial, view_model: @view_model diff --git a/app/views/verify/usps/index.html.slim b/app/views/verify/usps/index.html.slim index eb8c2d04f7f..961f54deef6 100644 --- a/app/views/verify/usps/index.html.slim +++ b/app/views/verify/usps/index.html.slim @@ -1,21 +1,16 @@ .my2.p3.py2.sm-px3.border.border-teal.rounded.rounded-xl.relative = image_tag(asset_url('check-email.svg'), size: '48x48', alt: 'check email',\ class: 'absolute top-n24 left-0 right-0 mx-auto') - h1.sans-serif.h2 + h1.h2 = t('idv.titles.verify_mail') p = t('idv.messages.usps.byline') - p.h4.bold - | #{@applicant.address1}
- - if @applicant.address2.present? - | #{@applicant.address2}
- | #{@applicant.city}, #{@applicant.state} #{@applicant.zipcode} p.my0 - = t('idv.messages.usps.success') + strong + = t('idv.messages.usps.success') -= button_to t('forms.buttons.continue'), verify_usps_path, method: 'put', - class: 'btn btn-primary btn-wide' += button_to t('idv.buttons.send_letter'), verify_usps_path, method: 'put', + class: 'btn btn-primary btn-wide', form_class: 'inline-block mr2' -.mt2.pt1.border-top - = link_to t('idv.buttons.verify_by_phone'), verify_phone_path += link_to t('idv.messages.usps.bad_address'), verify_phone_path diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index 553f8c47a26..0252c1dce87 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -2,10 +2,12 @@ en: idv: buttons: + activate_by_phone: Activate by phone + activate_by_mail: Activate by mail continue: Continue identity verification cancel: Cancel and return to your profile help: Continue to Help Center - verify_by_phone: ‹ Verify by phone + send_letter: Send letter cancel: modal_header: Are you sure you want to cancel? warning_header: If you cancel now @@ -19,7 +21,7 @@ en: bad_dob: Your date of birth must be a valid date. duplicate_ssn: An account already exists with the information you provided. finance_number_length: Number must be between %{minimum} and %{maximum} digits. - hardfail: We were unable to verify the information you provided. + hardfail: We were unable to verify your identity at this time. incorrect_password: The password you entered is not correct. invalid_ccn: Credit card number should be only last 8 digits. missing_finance: You must provide a financial account number. @@ -28,6 +30,7 @@ en: ssn: 'Your Social Security Number must be entered in as ###-##-####' zipcode: 'Your zipcode must be entered in as #####-####' form: + activate_by_mail: Activate my account by mail. address1: Street address 1 address2: Street address 2 (optional) auto_loan: Auto loan account number @@ -39,9 +42,11 @@ en: home_equity_line: Home equity line of credit account number last_name: Last name mortgage: Mortgage loan account number + no_alternate_phone_html: I don't have another phone number. %{link} password: Password personal_details: Personal details - phone: Phone + phone: Phone Number + phone_label_aside: Mobile or landline previous_address_add: Add previous address previous_address_html: Moved in the last 3 months? select_financial_account: Select a financial account… @@ -115,24 +120,19 @@ en: no_account: Want to use a credit card instead? no_account_info: Help us verify your identity by providing the last 8 digits of your credit card. - hardfail: > - Your account is active but we were unable to verify the information you provided. Please - sign back in after %{hours} hours to try again. + hardfail: We can’t verify your identity right now. hardfail4: You can also go to %{sp} for more help in accessing services. help_center: Visit our Help Center to learn more about verifying your account. phone: - in_your_name: in your name or the name of someone in your household - intro: > - To help us verify your identity, please give us a phone number that - belongs to you and that meets the criteria below: - is: 'is ' - is_not: 'is not ' + alert: This phone line must be + in_your_name: in your name or a family member's name + intro: We can only send a confirmation code to a telephone number linked to your + legal identity. phone_of_record: phone of record - prepaid: a pay-as-you-go phone + prepaid: on a contract, not prepaid same_as_2fa: > This phone number can be the same one you used to set up your one-time password as long as it meets the criteria above. - virtual: a virtual phone, like Google Voice or Skype recovery_code: > 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. @@ -140,13 +140,21 @@ en: financial_info: Where is my financial account information? info_verified_html: We found records matching your %{phone_message} intro: Your verified information + select_verification_without_sp: + In order to protect your account from identity fraud, your profile + will not be activated until you enter a confirmation code. + select_verification_with_sp: To protect you from identity fraud, you can't use your + account at %{sp_name} until you activate it by entering a confirmation code. sessions: pii: personal information success: We found records matching your %{pii_message} no_pii: Do not use real personal information (demo purposes only) usps: - byline: We are mailing a letter with a comfirmation code to + bad_address: I can't get mail at this address + byline: We will mail a letter with a confirmation code to your verified + address on file. success: It should arrive in 5 to 10 business days. + personal_details_verified: Personal details verified! modal: attempts: one: You have 1 attempt remaining. @@ -186,12 +194,13 @@ en: expectations: Next, help us identify you fail: We were unable to verify your identity financials: Provide a financial account number - hardfail: We were unable to verify your account + hardfail: We were unable to verify your identity intro: Help us identify you phone: Phone number of record review: Review and submit + select_verification: Activate your account sessions: First, tell us about yourself session: - phone: What is your phone number? - review: Encrypt your verified data by entering your password + phone: Get a code by telephone + review: Save your verified data by entering your password verify_mail: Your letter is on its way diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index 1372e1047ff..e490be6a562 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -2,10 +2,12 @@ es: idv: buttons: + activate_by_phone: NOT TRANSLATED YET + activate_by_mail: NOT TRANSLATED YET continue: NOT TRANSLATED YET cancel: NOT TRANSLATED YET help: NOT TRANSLATED YET - verify_by_phone: NOT TRANSLATED YET + send_letter: NOT TRANSLATED YET cancel: modal_header: NOT TRANSLATED YET warning_header: NOT TRANSLATED YET @@ -23,6 +25,7 @@ es: ssn: NOT TRANSLATED YET zipcode: NOT TRANSLATED YET form: + activate_by_mail: NOT TRANSLATED YET address1: NOT TRANSLATED YET address2: NOT TRANSLATED YET auto_loan: NOT TRANSLATED YET @@ -34,9 +37,11 @@ es: home_equity_line: NOT TRANSLATED YET last_name: NOT TRANSLATED YET mortgage: NOT TRANSLATED YET + no_alternate_phone_html: NOT TRANSLATED YET password: NOT TRANSLATED YET personal_details: NOT TRANSLATED YET phone: NOT TRANSLATED YET + phone_label_aside: NOT TRANSLATED YET previous_address_add: NOT TRANSLATED YET previous_address_html: NOT TRANSLATED YET select_financial_account: NOT TRANSLATED YET @@ -91,26 +96,28 @@ es: hardfail4: NOT TRANSLATED YET help_center: NOT TRANSLATED YET phone: + alert: NOT TRANSLATED YET in_your_name: NOT TRANSLATED YET intro: NOT TRANSLATED YET - is: NOT TRANSLATED YET - is_not: NOT TRANSLATED YET phone_of_record: NOT TRANSLATED YET prepaid: NOT TRANSLATED YET same_as_2fa: NOT TRANSLATED YET - virtual: NOT TRANSLATED YET recovery_code: NOT TRANSLATED YET review: financial_info: NOT TRANSLATED YET info_verified_html: NOT TRANSLATED YET intro: NOT TRANSLATED YET + select_verification_without_sp: NOT TRANSLATED YET + select_verification_with_sp: NOT TRANSLATED YET sessions: pii: NOT TRANSLATED YET success: NOT TRANSLATED YET no_pii: NOT TRANSLATED YET usps: + bad_address: NOT TRANSLATED YET byline: NOT TRANSLATED YET success: NOT TRANSLATED YET + personal_details_verified: NOT TRANSLATED YET modal: attempts: one: NOT TRANSLATED YET @@ -147,6 +154,7 @@ es: intro: NOT TRANSLATED YET phone: NOT TRANSLATED YET review: NOT TRANSLATED YET + select_verification: NOT TRANSLATED YET sessions: NOT TRANSLATED YET session: phone: NOT TRANSLATED YET diff --git a/spec/controllers/verify/finance_controller_spec.rb b/spec/controllers/verify/finance_controller_spec.rb index c80bbcf1a9f..aaaa342d7c7 100644 --- a/spec/controllers/verify/finance_controller_spec.rb +++ b/spec/controllers/verify/finance_controller_spec.rb @@ -83,23 +83,11 @@ end context 'when form is valid' do - it 'creates analytics event' do - stub_analytics - allow(@analytics).to receive(:track_event) - - put :create, idv_finance_form: { finance_type: :ccn, ccn: '12345678' } - - result = { success: true, errors: {}, vendor: { reasons: ['Good number'] } } - - expect(@analytics).to have_received(:track_event).with( - Analytics::IDV_FINANCE_CONFIRMATION, result - ) - end - context 'when CCN is confirmed' do it 'redirects to phone page' do put :create, idv_finance_form: { finance_type: :ccn, ccn: '12345678' } + expect(flash[:success]).to eq(t('idv.messages.personal_details_verified')) expect(response).to redirect_to verify_address_url expected_params = { ccn: '12345678' } diff --git a/spec/controllers/verify/sessions_controller_spec.rb b/spec/controllers/verify/sessions_controller_spec.rb index e7575f90bd6..5fa09f33d05 100644 --- a/spec/controllers/verify/sessions_controller_spec.rb +++ b/spec/controllers/verify/sessions_controller_spec.rb @@ -34,7 +34,7 @@ [:confirm_two_factor_authenticated, except: :destroy], :confirm_idv_attempts_allowed, :confirm_idv_needed, - :confirm_step_needed + [:confirm_step_needed, except: :destroy] ) end end diff --git a/spec/decorators/service_provider_session_decorator_spec.rb b/spec/decorators/service_provider_session_decorator_spec.rb index f6dc5dd13bb..2393edc879c 100644 --- a/spec/decorators/service_provider_session_decorator_spec.rb +++ b/spec/decorators/service_provider_session_decorator_spec.rb @@ -42,6 +42,14 @@ end end + describe '#verification_method_choice' do + it 'returns the correct string' do + expect(subject.verification_method_choice).to eq( + I18n.t('idv.messages.select_verification_with_sp', sp_name: sp_name) + ) + end + end + describe '#idv_hardfail4_partial' do it 'returns the correct partial' do expect(subject.idv_hardfail4_partial).to eq 'verify/hardfail4' diff --git a/spec/decorators/session_decorator_spec.rb b/spec/decorators/session_decorator_spec.rb index 39503bf6574..0c2520354f5 100644 --- a/spec/decorators/session_decorator_spec.rb +++ b/spec/decorators/session_decorator_spec.rb @@ -35,6 +35,14 @@ end end + describe '#verification_method_choice' do + it 'returns the correct string' do + expect(subject.verification_method_choice).to eq( + I18n.t('idv.messages.select_verification_without_sp') + ) + end + end + describe '#idv_hardfail4_partial' do it 'returns the correct partial' do expect(subject.idv_hardfail4_partial).to eq 'shared/null' diff --git a/spec/features/idv/flow_spec.rb b/spec/features/idv/flow_spec.rb index 984c4800353..ffd7b4fa888 100644 --- a/spec/features/idv/flow_spec.rb +++ b/spec/features/idv/flow_spec.rb @@ -348,7 +348,6 @@ scenario 'pick USPS address verification' do sign_in_and_2fa_user - visit verify_session_path fill_out_idv_form_ok @@ -356,10 +355,47 @@ fill_out_financial_form_ok click_idv_continue click_idv_address_choose_usps - click_idv_continue + click_on t('idv.buttons.send_letter') expect(current_path).to eq verify_review_path end + + context 'cancel from USPS/Phone verification screen' do + context 'without js' do + it 'returns user to profile path' do + sign_in_and_2fa_user + loa3_sp_session + visit verify_session_path + + fill_out_idv_form_ok + click_idv_continue + fill_out_financial_form_ok + click_idv_continue + + click_idv_cancel + + expect(current_path).to eq(profile_path) + end + end + + context 'with js', js: true do + it 'redirects to profile from a modal' do + sign_in_and_2fa_user + loa3_sp_session + visit verify_session_path + + fill_out_idv_form_ok + click_idv_continue + fill_out_financial_form_ok + click_idv_continue + + click_on t('links.cancel_idv') + click_idv_cancel_modal + + expect(current_path).to eq(profile_path) + end + end + end end def complete_idv_profile_fail diff --git a/spec/features/saml/loa3_sso_spec.rb b/spec/features/saml/loa3_sso_spec.rb index a503cf67d9d..971ded8870e 100644 --- a/spec/features/saml/loa3_sso_spec.rb +++ b/spec/features/saml/loa3_sso_spec.rb @@ -44,37 +44,61 @@ end end - context 'canceling verification', js: true do - it 'returns user to recovery code page if they sign up via loa3' do - user = create(:user, phone: '1 (111) 111-1111', recovery_code: nil) - sign_in_with_warden(user) - loa3_sp_session + context 'canceling verification' do + context 'with js', js: true do + it 'returns user to recovery code page if they sign up via loa3' do + user = create(:user, phone: '1 (111) 111-1111', recovery_code: nil) + sign_in_with_warden(user) + loa3_sp_session + + visit verify_path + click_on t('links.cancel') + click_on t('idv.buttons.cancel') + + expect(current_path).to eq(manage_recovery_code_path) + end + + it 'returns user to profile page if they have previously signed up' do + sign_in_and_2fa_user + loa3_sp_session + + visit verify_path + click_on t('links.cancel') + click_on t('idv.buttons.cancel') + + expect(current_path).to match(profile_path) + end + end - visit verify_path + context 'without js' do + it 'returns user to recovery code page if they sign up via loa3' do + user = create(:user, phone: '1 (111) 111-1111', recovery_code: nil) + sign_in_with_warden(user) + loa3_sp_session - click_on t('links.cancel') - click_on t('idv.buttons.cancel') + visit verify_path + click_idv_cancel - expect(current_path).to eq(manage_recovery_code_path) - end + expect(current_path).to eq(manage_recovery_code_path) + end - it 'returns user to profile page if they have previously signed up' do - sign_in_and_2fa_user - loa3_sp_session + it 'returns user to profile page if they have previously signed up' do + sign_in_and_2fa_user + loa3_sp_session - visit verify_path + visit verify_path + click_idv_cancel - click_on t('links.cancel') - click_on t('idv.buttons.cancel') - expect(current_url).to match(/profile/) + expect(current_url).to eq(profile_url) + end end end context 'visiting sign_up_completed path before proofing' do it 'redirects to verify_path' do sign_in_and_2fa_user - visit loa3_authnrequest + visit loa3_authnrequest visit sign_up_completed_path expect(current_path).to eq verify_path diff --git a/spec/support/features/idv_helper.rb b/spec/support/features/idv_helper.rb index 48c9ddbccf1..56651c5c798 100644 --- a/spec/support/features/idv_helper.rb +++ b/spec/support/features/idv_helper.rb @@ -64,11 +64,21 @@ def click_idv_continue end def click_idv_address_choose_phone - click_link 'Phone' + click_link t('idv.buttons.activate_by_phone') end def click_idv_address_choose_usps - click_link 'USPS' + click_link t('idv.buttons.activate_by_mail') + end + + def click_idv_cancel_modal + within('.modal') do + click_on t('idv.buttons.cancel') + end + end + + def click_idv_cancel + click_on t('idv.buttons.cancel') end def complete_idv_profile_ok(user)