diff --git a/app/controllers/concerns/inherited_proofing_concern.rb b/app/controllers/concerns/inherited_proofing_concern.rb index f7ec92960d1..3b26d60826b 100644 --- a/app/controllers/concerns/inherited_proofing_concern.rb +++ b/app/controllers/concerns/inherited_proofing_concern.rb @@ -4,9 +4,8 @@ # Login.gov account. module InheritedProofingConcern extend ActiveSupport::Concern - include Idv::InheritedProofing::ServiceProviderForms - include Idv::InheritedProofing::ServiceProviderServices + # Returns true if Inherited Proofing is currently underway. def inherited_proofing? inherited_proofing_service_provider.present? end diff --git a/app/controllers/idv/inherited_proofing_cancellations_controller.rb b/app/controllers/idv/inherited_proofing_cancellations_controller.rb index c277fd9c9d0..c143c72bcee 100644 --- a/app/controllers/idv/inherited_proofing_cancellations_controller.rb +++ b/app/controllers/idv/inherited_proofing_cancellations_controller.rb @@ -8,7 +8,7 @@ class InheritedProofingCancellationsController < ApplicationController before_action :confirm_idv_needed def new - # NOTE: Uncomment this when analytics are implemented. + # LG-7128: Implement Inherited Proofing analytics here. # properties = ParseControllerFromReferer.new(request.referer).call # analytics.idv_inherited_proofing_cancellation_visited(step: params[:step], **properties) self.session_go_back_path = go_back_path || idv_inherited_proofing_path @@ -19,13 +19,13 @@ def new end def update - # NOTE: Uncomment this when analytics are implemented. + # LG-7128: Implement Inherited Proofing analytics here. # analytics.idv_inherited_proofing_cancellation_go_back(step: params[:step]) redirect_to session_go_back_path || idv_inherited_proofing_path end def destroy - # NOTE: Uncomment this when analytics are implemented. + # LG-7128: Implement Inherited Proofing analytics here. # analytics.idv_inherited_proofing_cancellation_confirmed(step: params[:step]) cancel_session render json: { redirect_url: cancelled_redirect_path } diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index 55da89d4182..dc969067da1 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -5,21 +5,23 @@ class SessionsController < ApplicationController before_action :confirm_two_factor_authenticated def destroy - cancel_verification_attempt_if_pending_profile - cancel_in_person_enrollment_if_exists - analytics.idv_start_over( - step: location_params[:step], - location: location_params[:location], - ) - user_session['idv/doc_auth'] = {} - user_session['idv/in_person'] = {} - idv_session.clear - Pii::Cacher.new(current_user, user_session).delete + cancel_processing + clear_session + log_analytics redirect_to idv_url end private + def location_params + params.permit(:step, :location).to_h.symbolize_keys + end + + def cancel_processing + cancel_verification_attempt_if_pending_profile + cancel_in_person_enrollment_if_exists + end + def cancel_verification_attempt_if_pending_profile return if current_user.profiles.gpo_verification_pending.blank? Idv::CancelVerificationAttempt.new(user: current_user).call @@ -32,8 +34,22 @@ def cancel_in_person_enrollment_if_exists cancel_stale_establishing_enrollments_for_user(current_user) end - def location_params - params.permit(:step, :location).to_h.symbolize_keys + def clear_session + user_session['idv/doc_auth'] = {} + user_session['idv/in_person'] = {} + user_session['idv/inherited_proofing'] = {} + idv_session.clear + Pii::Cacher.new(current_user, user_session).delete + end + + def log_analytics + # LG-7128: Implement Inherited Proofing analytics here. + # include InheritedProofingConcern and if inherited_proofing?, + # pass flow/param/analytics_ids param to the existing idv_start_over event. + analytics.idv_start_over( + step: location_params[:step], + location: location_params[:location], + ) end end end diff --git a/app/jobs/inherited_proofing_job.rb b/app/jobs/inherited_proofing_job.rb index 9f0ccb178ed..c4f8d5f79e9 100644 --- a/app/jobs/inherited_proofing_job.rb +++ b/app/jobs/inherited_proofing_job.rb @@ -1,6 +1,5 @@ class InheritedProofingJob < ApplicationJob include Idv::InheritedProofing::ServiceProviderServices - include Idv::InheritedProofing::ServiceProviderForms include JobHelpers::StaleJobHelper queue_as :default diff --git a/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb b/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb index f66490c971e..45df7920b8c 100644 --- a/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb +++ b/app/services/idv/steps/inherited_proofing/verify_wait_step_show.rb @@ -61,7 +61,7 @@ def async_state_done(_current_async_state) mark_step_incomplete(:agreement) end - return form_response + form_response end def dcs_uuid diff --git a/app/views/idv/inherited_proofing/verify_wait.html.erb b/app/views/idv/inherited_proofing/verify_wait.html.erb index 90cb1a88710..2936142e739 100644 --- a/app/views/idv/inherited_proofing/verify_wait.html.erb +++ b/app/views/idv/inherited_proofing/verify_wait.html.erb @@ -14,3 +14,4 @@

<%= t('inherited_proofing.info.retrieval_time') %>

<%= t('inherited_proofing.info.retrieval_thanks') %>

+<%= render 'idv/inherited_proofing/cancel', step: 'verify_info' %> diff --git a/app/views/idv/inherited_proofing_cancellations/new.html.erb b/app/views/idv/inherited_proofing_cancellations/new.html.erb index d8803427e38..159f8363027 100644 --- a/app/views/idv/inherited_proofing_cancellations/new.html.erb +++ b/app/views/idv/inherited_proofing_cancellations/new.html.erb @@ -8,10 +8,9 @@

<%= t('inherited_proofing.cancel.description.start_over') %>

- <%# NOTE: Render "Start Over" button here, but first have to create an IP-specific SessionController. %> - <%#= render ButtonComponent.new( + <%= render ButtonComponent.new( action: ->(**tag_options, &block) do - button_to(idv_session_path(step: @flow_step), **tag_options, &block) + button_to(idv_inherited_proofing_session_path(step: @flow_step), **tag_options, &block) end, method: :delete, big: true, diff --git a/config/routes.rb b/config/routes.rb index 2e527ceb388..e5544dc37bd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -362,6 +362,7 @@ scope '/verify/inherited_proofing', module: 'idv', as: 'idv_inherited_proofing' do # NOTE: cancellation routes need to be before any other IP # routes in this scope. + delete '/session' => 'sessions#destroy' get '/cancel' => 'inherited_proofing_cancellations#new', as: :cancel put '/cancel' => 'inherited_proofing_cancellations#update' delete '/cancel' => 'inherited_proofing_cancellations#destroy' diff --git a/spec/controllers/idv/sessions_controller_spec.rb b/spec/controllers/idv/sessions_controller_spec.rb index 7c0ce97cd73..224c33c332f 100644 --- a/spec/controllers/idv/sessions_controller_spec.rb +++ b/spec/controllers/idv/sessions_controller_spec.rb @@ -9,29 +9,43 @@ end describe '#destroy' do - let(:idv_session) { double } - let(:flow_session) { {} } - let(:pii) { { first_name: 'Jane' } } - before do allow(idv_session).to receive(:clear) allow(subject).to receive(:idv_session).and_return(idv_session) controller.user_session['idv/doc_auth'] = flow_session controller.user_session['idv/in_person'] = flow_session + controller.user_session['idv/inherited_proofing'] = flow_session controller.user_session[:decrypted_pii] = pii end - it 'deletes idv session' do - expect(idv_session).to receive(:clear) + let(:idv_session) { double } + let(:flow_session) { { x: {} } } + let(:pii) { { first_name: 'Jane' } } - delete :destroy + context 'when destroying the session' do + before do + expect(idv_session).to receive(:clear) + delete :destroy + end + + it 'clears the idv/doc_auth session' do + expect(controller.user_session['idv/doc_auth']).to be_blank + end + + it 'clears the idv/in_person session' do + expect(controller.user_session['idv/in_person']).to be_blank + end + + it 'clears the idv/inherited_proofing session' do + expect(controller.user_session['idv/inherited_proofing']).to be_blank + end - expect(controller.user_session['idv/doc_auth']).to be_blank - expect(controller.user_session['idv/in_person']).to be_blank - expect(controller.user_session[:decrypted_pii]).to be_blank + it 'clears the decrypted_pii session' do + expect(controller.user_session[:decrypted_pii]).to be_blank + end end - it 'logs start over with step and location params' do + it 'logs IDV start over analytics with step and location params' do delete :destroy, params: { step: 'first', location: 'get_help' } expect(@analytics).to have_logged_event( @@ -41,7 +55,7 @@ ) end - it 'redirects to start of identity verificaton' do + it 'redirect occurs to the start of identity verification' do delete :destroy expect(response).to redirect_to(idv_url) diff --git a/spec/features/idv/inherited_proofing/inherited_proofing_cancel_spec.rb b/spec/features/idv/inherited_proofing/inherited_proofing_cancel_spec.rb new file mode 100644 index 00000000000..d3be7768af1 --- /dev/null +++ b/spec/features/idv/inherited_proofing/inherited_proofing_cancel_spec.rb @@ -0,0 +1,198 @@ +require 'rails_helper' + +# Simulates a user (in this case, a VA inherited proofing-authorized user) +# coming over to login.gov from a service provider, and hitting the +# OpenidConnect::AuthorizationController#index action. +def send_user_from_service_provider_to_login_gov_openid_connect(user) + expect(user).to_not be_nil + # NOTE: VA user. + visit_idp_from_oidc_va_with_ial2 +end + +def complete_idv_steps_up_to_inherited_proofing_get_started_step(user, expect_accessible: false) + unless current_path == idv_inherited_proofing_step_path(step: :get_started) + complete_idv_steps_before_phone_step(user) + click_link t('links.cancel') + click_button t('idv.cancel.actions.start_over') + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) + end + expect(page).to be_axe_clean.according_to :section508, :"best-practice" if expect_accessible +end + +def complete_idv_steps_up_to_inherited_proofing_how_verifying_step(user, expect_accessible: false) + complete_idv_steps_up_to_inherited_proofing_get_started_step user, + expect_accessible: expect_accessible + unless current_path == idv_inherited_proofing_step_path(step: :agreement) + click_on t('inherited_proofing.buttons.continue') + end +end + +def complete_idv_steps_up_to_inherited_proofing_we_are_retrieving_step(user, + expect_accessible: false) + complete_idv_steps_up_to_inherited_proofing_how_verifying_step( + user, + expect_accessible: expect_accessible, + ) + unless current_path == idv_inherited_proofing_step_path(step: :verify_wait) + check t('inherited_proofing.instructions.consent', app_name: APP_NAME), allow_label_click: true + click_on t('inherited_proofing.buttons.continue') + end +end + +def complete_idv_steps_up_to_inherited_proofing_verify_your_info_step(user, + expect_accessible: false) + complete_idv_steps_up_to_inherited_proofing_we_are_retrieving_step( + user, + expect_accessible: expect_accessible, + ) +end + +feature 'inherited proofing cancel process', :js do + include InheritedProofingHelper + include_context 'va_user_context' + + before do + allow(IdentityConfig.store).to receive(:va_inherited_proofing_mock_enabled).and_return true + send_user_from_service_provider_to_login_gov_openid_connect user + end + + let!(:user) { user_with_2fa } + + context 'from the "Get started verifying your identity" view, and clicking the "Cancel" link' do + before do + complete_idv_steps_up_to_inherited_proofing_get_started_step user + end + + it 'should have current path equal to the Getting Started page' do + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) + end + + context 'when clicking the "Start Over" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :get_started)) + end + + it 'redirects the user back to the start of the Inherited Proofing process' do + click_button t('inherited_proofing.cancel.actions.start_over') + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) + end + end + + context 'when clicking the "No, keep going" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :get_started)) + end + + it 'redirects the user back to where the user left off in the Inherited Proofing process' do + click_button t('inherited_proofing.cancel.actions.keep_going') + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) + end + end + + context 'when clicking the "Exit Login.gov" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :get_started)) + end + + it 'redirects the user back to the service provider website' do + click_button t('idv.cancel.actions.exit', app_name: APP_NAME) + expect(page).to have_current_path(/\/auth\/result\?/) + end + end + end + + context 'from the "How verifying your identify works" view, and clicking the "Cancel" link' do + before do + complete_idv_steps_up_to_inherited_proofing_how_verifying_step user + end + + it 'should have current path equal to the How Verifying (agreement step) page' do + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :agreement)) + end + + context 'when clicking the "Start Over" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :agreement)) + end + + it 'redirects the user back to the start of the Inherited Proofing process' do + click_button t('inherited_proofing.cancel.actions.start_over') + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) + end + end + + context 'when clicking the "No, keep going" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :agreement)) + end + + it 'redirects the user back to where the user left off in the Inherited Proofing process' do + click_button t('inherited_proofing.cancel.actions.keep_going') + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :agreement)) + end + end + + context 'when clicking the "Exit Login.gov" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :agreement)) + end + + it 'redirects the user back to the service provider website' do + click_button t('idv.cancel.actions.exit', app_name: APP_NAME) + expect(page).to have_current_path(/\/auth\/result\?/) + end + end + end + + context 'from the "Verify your information..." view, and clicking the "Cancel" link' do + before do + complete_idv_steps_up_to_inherited_proofing_verify_your_info_step user + end + + it 'should have current path equal to the Verify your information (verify_info step) page' do + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :verify_info)) + end + + context 'when clicking the "Start Over" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :verify_info)) + end + + it 'redirects the user back to the start of the Inherited Proofing process' do + click_button t('inherited_proofing.cancel.actions.start_over') + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :get_started)) + end + end + + context 'when clicking the "No, keep going" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :verify_info)) + end + + it 'redirects the user back to where the user left off in the Inherited Proofing process' do + click_button t('inherited_proofing.cancel.actions.keep_going') + expect(page).to have_current_path(idv_inherited_proofing_step_path(step: :verify_info)) + end + end + + context 'when clicking the "Exit Login.gov" button from the "Cancel" view' do + before do + click_link t('links.cancel') + expect(page).to have_current_path(idv_inherited_proofing_cancel_path(step: :verify_info)) + end + + it 'redirects the user back to the service provider website' do + click_button t('idv.cancel.actions.exit', app_name: APP_NAME) + expect(page).to have_current_path(/\/auth\/result\?/) + end + end + end +end diff --git a/spec/support/features/idv_helper.rb b/spec/support/features/idv_helper.rb index 7c4713cc2c5..c244ac17b6c 100644 --- a/spec/support/features/idv_helper.rb +++ b/spec/support/features/idv_helper.rb @@ -120,6 +120,29 @@ def visit_idp_from_oidc_sp_with_ial2( ) end + def visit_idp_from_oidc_va_with_ial2( + client_id: sp_oidc_issuer, + state: SecureRandom.hex, + nonce: SecureRandom.hex, + verified_within: nil + ) + @state = state + @client_id = sp_oidc_issuer + @nonce = nonce + visit openid_connect_authorize_path( + client_id: client_id, + response_type: 'code', + acr_values: Saml::Idp::Constants::IAL2_AUTHN_CONTEXT_CLASSREF, + scope: 'openid email profile:name phone social_security_number', + redirect_uri: sp_oidc_redirect_uri, + state: state, + prompt: 'select_account', + nonce: nonce, + verified_within: verified_within, + inherited_proofing_auth: Idv::InheritedProofing::Va::Mocks::Service::VALID_AUTH_CODE, + ) + end + def visit_idp_from_oidc_sp_with_loa3 visit openid_connect_authorize_path( client_id: sp_oidc_issuer, diff --git a/spec/views/idv/inherited_proofing/retrieval.html.erb_spec.rb b/spec/views/idv/inherited_proofing/retrieval.html.erb_spec.rb index 031ae922f0b..7db2ed40eb1 100644 --- a/spec/views/idv/inherited_proofing/retrieval.html.erb_spec.rb +++ b/spec/views/idv/inherited_proofing/retrieval.html.erb_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' describe 'idv/inherited_proofing/verify_wait.html.erb' do + include Devise::Test::ControllerHelpers + it 'renders' do render template: 'idv/inherited_proofing/verify_wait'