Skip to content

Commit

Permalink
LG-15177 Add a CTA to return to an SP after entering a verify-by-mail…
Browse files Browse the repository at this point in the history
… code (#11602)

In #11591 we added a `post_idv_follow_up_url` that allows users to return to a service provider after finishing verification out-of-band.

This commit puts this new URL to work in the verify-by-mail code. After this commit users who enter a verify-by-mail code without an SP in their session will see a new SP follow-up screen. This screen includes a CTA that prompts the user to connect their account to the service provider they started proofing with. This link leads to the new post-IdV follow-up URL.

changelog: User-Facing Improvements, Verify-by-mail, A CTA was added to prompt users to return to the service provider after verify-by-mail
  • Loading branch information
jmhooper authored Dec 9, 2024
1 parent 27d822b commit cd90fae
Show file tree
Hide file tree
Showing 14 changed files with 436 additions and 6 deletions.
49 changes: 49 additions & 0 deletions app/controllers/idv/by_mail/sp_follow_up_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

module Idv
module ByMail
class SpFollowUpController < ApplicationController
include Idv::AvailabilityConcern

before_action :confirm_two_factor_authenticated
before_action :confirm_needs_sp_follow_up

def new
analytics.track_event(:idv_by_mail_sp_follow_up_visited, **analytics_params)
@presenter = Idv::ByMail::SpFollowUpPresenter.new(current_user:)
end

def show
analytics.track_event(:idv_by_mail_sp_follow_up_submitted, **analytics_params)

sp_return_url_resolver = SpReturnUrlResolver.new(
service_provider: current_user.active_profile.initiating_service_provider,
)
redirect_url = sp_return_url_resolver.post_idv_follow_up_url ||
sp_return_url_resolver.return_to_sp_url
redirect_to(redirect_url, allow_other_host: true)
end

def cancel
analytics.track_event(:idv_by_mail_sp_follow_up_cancelled, **analytics_params)
redirect_to account_url
end

private

def analytics_params
initiating_service_provider = current_user.active_profile.initiating_service_provider
{
initiating_service_provider: initiating_service_provider.issuer,
}
end

def confirm_needs_sp_follow_up
return if current_user.identity_verified? &&
current_user.active_profile.initiating_service_provider.present? &&
!current_sp.present?
redirect_to account_url
end
end
end
end
2 changes: 2 additions & 0 deletions app/controllers/idv/personal_key_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ def next_step
idv_please_call_url
elsif session[:sp]
sign_up_completed_url
elsif idv_session.address_verification_mechanism == 'gpo'
idv_sp_follow_up_path
else
after_sign_in_path_for(current_user)
end
Expand Down
40 changes: 40 additions & 0 deletions app/presenters/idv/by_mail/sp_follow_up_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module Idv
module ByMail
class SpFollowUpPresenter
include ActionView::Helpers::TranslationHelper

attr_reader :current_user

def initialize(current_user:)
@current_user = current_user
end

def heading
t(
'idv.by_mail.sp_follow_up.heading',
service_provider: initiating_service_provider_name,
)
end

def body
t(
'idv.by_mail.sp_follow_up.body',
service_provider: initiating_service_provider_name,
app_name: APP_NAME,
)
end

private

def initiating_service_provider_name
initiating_service_provider.friendly_name
end

def initiating_service_provider
@initiating_service_provider ||= current_user.active_profile.initiating_service_provider
end
end
end
end
47 changes: 47 additions & 0 deletions app/services/analytics_events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -820,15 +820,32 @@ def gpo_confirmation_upload(
# User visited sign-in URL from the "You've been successfully verified email" CTA button
# @param issuer [String] the ServiceProvider.issuer
# @param campaign_id [String] the email campaign ID
# @param [Hash,nil] proofing_components User's current proofing components
# @option proofing_components [String,nil] 'document_check' Vendor that verified the user's ID
# @option proofing_components [String,nil] 'document_type' Type of ID used to verify
# @option proofing_components [String,nil] 'source_check' Source used to verify user's PII
# @option proofing_components [String,nil] 'resolution_check' Vendor for identity resolution check
# @option proofing_components [String,nil] 'address_check' Method used to verify user's address
# @option proofing_components [Boolean,nil] 'threatmetrix' Whether ThreatMetrix check was done
# @option proofing_components [String,nil] 'threatmetrix_review_status' TMX decision on the user
# @param [String,nil] active_profile_idv_level ID verification level of user's active profile.
# @param [String,nil] pending_profile_idv_level ID verification level of user's pending profile.
def idv_account_verified_cta_visited(
issuer:,
campaign_id:,
proofing_components: nil,
active_profile_idv_level: nil,
pending_profile_idv_level: nil,
**extra
)
track_event(
:idv_account_verified_cta_visited,
issuer:,
campaign_id:,
proofing_components:,
active_profile_idv_level:,
pending_profile_idv_level:,

**extra,
)
end
Expand Down Expand Up @@ -1032,6 +1049,36 @@ def idv_barcode_warning_retake_photos_clicked(liveness_checking_required:, **ext
)
end

# @param [String] initiating_service_provider The service provider the user needs to connect to
# The user chose not to connect their account from the SP follow-up page
def idv_by_mail_sp_follow_up_cancelled(initiating_service_provider:, **extra)
track_event(
:idv_by_mail_sp_follow_up_cancelled,
initiating_service_provider:,
**extra,
)
end

# @param [String] initiating_service_provider The service provider the user needs to connect to
# The user chose to connect their account from the SP follow-up page
def idv_by_mail_sp_follow_up_submitted(initiating_service_provider:, **extra)
track_event(
:idv_by_mail_sp_follow_up_submitted,
initiating_service_provider:,
**extra,
)
end

# @param [String] initiating_service_provider The service provider the user needs to connect to
# The user visited the SP follow-up page
def idv_by_mail_sp_follow_up_visited(initiating_service_provider:, **extra)
track_event(
:idv_by_mail_sp_follow_up_visited,
initiating_service_provider:,
**extra,
)
end

# @param [Hash] error
def idv_camera_info_error(error:, **_extra)
track_event(:idv_camera_info_error, error: error)
Expand Down
24 changes: 24 additions & 0 deletions app/views/idv/by_mail/sp_follow_up/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<% self.title = @presenter.heading %>

<div class="text-center">
<%= image_tag(asset_url('user-access.svg'), width: '280', height: '91', alt: '', aria: { hidden: true }) %>
<h1 class="margin-bottom-4"><%= @presenter.heading %></h1>
</div>

<p><%= @presenter.body %></p>

<div class='margin-top-5 margin-bottom-2'>
<%= render ButtonComponent.new(
url: idv_sp_follow_up_connect_path,
big: true,
wide: true,
).with_content(t('idv.by_mail.sp_follow_up.connect_account')) %>
</div>
<div>
<%= render ButtonComponent.new(
url: idv_sp_follow_up_cancel_path,
big: true,
wide: true,
outline: true,
).with_content(t('idv.by_mail.sp_follow_up.go_to_account')) %>
</div>
4 changes: 4 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,10 @@ idv.buttons.change_ssn_label: Update Social Security number
idv.buttons.change_state_id_label: Update state ID
idv.buttons.continue_plain: Continue
idv.buttons.mail.send: Request a letter
idv.by_mail.sp_follow_up.body: Sign back in to %{service_provider} to connect your verified %{app_name} account and access services.
idv.by_mail.sp_follow_up.connect_account: Connect your account
idv.by_mail.sp_follow_up.go_to_account: Go to account
idv.by_mail.sp_follow_up.heading: Connect to %{service_provider}
idv.cancel.actions.account_page: Go to account page
idv.cancel.actions.exit: Exit %{app_name}
idv.cancel.actions.keep_going: No, keep going
Expand Down
4 changes: 4 additions & 0 deletions config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,10 @@ idv.buttons.change_ssn_label: Actualizar número de Seguro Social
idv.buttons.change_state_id_label: Actualizar identificación estatal
idv.buttons.continue_plain: Continuar
idv.buttons.mail.send: Solicitar una carta
idv.by_mail.sp_follow_up.body: Vuelva a iniciar sesión en %{service_provider} para conectar su cuenta verificada de %{app_name} y acceder a los servicios.
idv.by_mail.sp_follow_up.connect_account: Conecte su cuenta
idv.by_mail.sp_follow_up.go_to_account: Ir a la cuenta
idv.by_mail.sp_follow_up.heading: Conéctese a %{service_provider}
idv.cancel.actions.account_page: Ir a la página de la cuenta
idv.cancel.actions.exit: Salir de %{app_name}
idv.cancel.actions.keep_going: No, continuar
Expand Down
4 changes: 4 additions & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,10 @@ idv.buttons.change_ssn_label: Mettre à jour votre numéro de sécurité sociale
idv.buttons.change_state_id_label: Mettre à jour votre pièce d’identité
idv.buttons.continue_plain: Suite
idv.buttons.mail.send: Demander une lettre
idv.by_mail.sp_follow_up.body: Connectez-vous à nouveau à %{service_provider} pour y associer votre compte %{app_name} vérifié et accéder aux services de cet organisme.
idv.by_mail.sp_follow_up.connect_account: Associer votre compte
idv.by_mail.sp_follow_up.go_to_account: Aller sur le compte
idv.by_mail.sp_follow_up.heading: Vous connecter à %{service_provider}
idv.cancel.actions.account_page: Aller à la page de votre compte
idv.cancel.actions.exit: Quitter %{app_name}
idv.cancel.actions.keep_going: Non, continuer
Expand Down
4 changes: 4 additions & 0 deletions config/locales/zh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,10 @@ idv.buttons.change_ssn_label: 更新社会保障号码
idv.buttons.change_state_id_label: 更新州颁发的身份证件
idv.buttons.continue_plain: 继续
idv.buttons.mail.send: 要求发一封信
idv.by_mail.sp_follow_up.body: 重新登录 %{service_provider}以连接你验证过的%{app_name}账户并获得服务。
idv.by_mail.sp_follow_up.connect_account: 连接你的账户
idv.by_mail.sp_follow_up.go_to_account: 前往账户
idv.by_mail.sp_follow_up.heading: 连接 %{service_provider}
idv.cancel.actions.account_page: 到账户页面
idv.cancel.actions.exit: 退出 %{app_name}
idv.cancel.actions.keep_going: 不是,继续
Expand Down
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,9 @@
end

get '/by_mail/letter_enqueued' => 'by_mail/letter_enqueued#show', as: :letter_enqueued
get '/by_mail/sp_follow_up' => 'by_mail/sp_follow_up#new', as: :sp_follow_up
get '/by_mail/sp_follow_up/connect' => 'by_mail/sp_follow_up#show', as: :sp_follow_up_connect
get '/by_mail/sp_follow_up/cancel' => 'by_mail/sp_follow_up#cancel', as: :sp_follow_up_cancel

# We re-mapped `/verify/by_mail` to `/verify/by_mail/enter_code`. However, we sent emails to
# users with a link to `/verify/by_mail?did_not_receive_letter=1`. We need to continue
Expand Down
83 changes: 83 additions & 0 deletions spec/controllers/idv/by_mail/sp_follow_up_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
require 'rails_helper'

RSpec.describe Idv::ByMail::SpFollowUpController do
let(:post_idv_follow_up_url) { 'https://example.com/follow_up' }
let(:initiating_service_provider) { create(:service_provider, post_idv_follow_up_url:) }
let(:user) { create(:user, :fully_registered) }
let!(:profile) { create(:profile, :active, user:, initiating_service_provider:) }

before do
stub_sign_in(user) if user.present?
stub_analytics
end

describe '#new' do
context 'the user has not finished verification' do
let(:profile) do
create(:profile, :verify_by_mail_pending, user:, initiating_service_provider:)
end

it 'redirects to the account page' do
get :new

expect(response).to redirect_to(account_url)
end
end

context 'the user has an SP in the session' do
before do
allow(controller).to receive(:current_sp).and_return(initiating_service_provider)
end

it 'redirects to the account page' do
get :new

expect(response).to redirect_to(account_url)
end
end

context 'the user does not have an initiating service provider' do
let(:profile) { create(:profile, :active, user:, initiating_service_provider: nil) }

it 'redirects to the account page' do
get :new

expect(response).to redirect_to(account_url)
end
end

it 'logs analytics and renders the template' do
get :new

expect(response).to render_template(:new)
expect(@analytics).to have_logged_event(
:idv_by_mail_sp_follow_up_visited,
initiating_service_provider: initiating_service_provider.issuer,
)
end
end

describe '#show' do
it 'logs analytics and redirects to the service provider' do
get :show

expect(response).to redirect_to(post_idv_follow_up_url)
expect(@analytics).to have_logged_event(
:idv_by_mail_sp_follow_up_submitted,
initiating_service_provider: initiating_service_provider.issuer,
)
end
end

describe '#cancel' do
it 'logs analytics and redirects to the account URL' do
get :cancel

expect(response).to redirect_to(account_url)
expect(@analytics).to have_logged_event(
:idv_by_mail_sp_follow_up_cancelled,
initiating_service_provider: initiating_service_provider.issuer,
)
end
end
end
41 changes: 35 additions & 6 deletions spec/controllers/idv/personal_key_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -483,14 +483,43 @@ def assert_personal_key_generated_for_profiles(*profile_pii_pairs)
context 'user selected gpo verification' do
let(:address_verification_mechanism) { 'gpo' }

it 'redirects to correct url' do
patch :update
expect(response).to redirect_to idv_letter_enqueued_url
context 'when the user requested a letter this session' do
it 'redirects to correct url' do
patch :update
expect(response).to redirect_to idv_letter_enqueued_url
end

it 'does not log any events' do
expect(@analytics).not_to have_logged_event
patch :update
end
end

it 'does not log any events' do
expect(@analytics).not_to have_logged_event
patch :update
context 'when the user entered a GPO code' do
before do
pending_profile = user.pending_profile
pending_profile.remove_gpo_deactivation_reason
pending_profile.activate
end

it 'redirects to correct url' do
patch :update
expect(response).to redirect_to idv_sp_follow_up_url
end

it 'logs analytics' do
patch :update

expect(@analytics).to have_logged_event(
'IdV: personal key submitted',
hash_including(
address_verification_method: 'gpo',
fraud_review_pending: false,
fraud_rejection: false,
in_person_verification_pending: false,
),
)
end
end
end

Expand Down
Loading

0 comments on commit cd90fae

Please sign in to comment.