Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a4cd9d2
Initial commit of new combined hybrid handoff step
Feb 9, 2023
c52ee19
Deleting useless hybrid handoff mobile tests
Feb 9, 2023
56a7007
Pulling in send_link step functionality to upload_step
Feb 9, 2023
c1d71ab
Adding feature flag for new combined hybrid handoff step
Feb 9, 2023
84525ac
Existing tests, feature flagged, are now passing
Feb 10, 2023
17e18d8
Undo bad analytics change
Feb 13, 2023
f1a92ac
Adding test to ensure phone number is prefilled
Feb 13, 2023
973e2a3
Test that combined hybrid proceeds to link sent with valid info
Feb 13, 2023
18fbc0f
Adding feature flagged version of form_submit to new upload step
Feb 14, 2023
027bccb
Adding throttle feature test for combined upload step spec
Feb 14, 2023
eb41f8c
Completing addition of send_link feature specs to comb. upload
Feb 15, 2023
912681e
Adding a plain step test for upload that copies send_link
Feb 15, 2023
b6b7992
Updating locales and styling for new combined hybrid upload step
Feb 16, 2023
a08b253
Adding click helpers for new upload hybrid view and updating tests
Feb 17, 2023
512907f
Normalizing yaml changes
Feb 17, 2023
fbfa4d3
Lints
Feb 17, 2023
f1bbb48
Optimizing assets (new images)
Feb 17, 2023
b67f3e5
Removing TODO
Feb 17, 2023
43ff1d5
Adding missing translations
Feb 17, 2023
c79df80
Update app/views/idv/doc_auth/_combined_upload.html.erb
eric-gade Feb 17, 2023
9d2782e
Update app/views/idv/doc_auth/_combined_upload.html.erb
eric-gade Feb 17, 2023
22ee1f2
Updating image size and erb indentation
Feb 17, 2023
fc84259
Updating grid for tablet and adding simple margin to icon images
Feb 17, 2023
441cb93
Switching buttons back to wide, for idv consistency
Feb 17, 2023
0f83be7
Lints!
Feb 17, 2023
03533d8
Adding additional checking for 50/50 conditions
Feb 17, 2023
f1c48c7
Update app/views/idv/doc_auth/_combined_upload.html.erb
eric-gade Feb 21, 2023
b09792f
Updating grid styling for icon display and gaps
Feb 21, 2023
01783a6
lint
Feb 21, 2023
30a02c2
Updating phone input to be required in combined case
Feb 21, 2023
9bee92c
Update app/views/idv/doc_auth/_combined_upload.html.erb
eric-gade Feb 22, 2023
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
1 change: 1 addition & 0 deletions app/assets/images/idv/laptop-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/assets/images/idv/phone-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/services/idv/actions/cancel_link_sent_action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ def self.analytics_submitted_event

def call
mark_step_incomplete(:send_link)
if IdentityConfig.store.doc_auth_combined_hybrid_handoff_enabled
mark_step_incomplete(:upload)
end
end
end
end
Expand Down
135 changes: 135 additions & 0 deletions app/services/idv/steps/upload_step.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Idv
module Steps
class UploadStep < DocAuthBaseStep
include ActionView::Helpers::DateHelper
STEP_INDICATOR_STEP = :verify_id

def self.analytics_visited_event
Expand All @@ -20,11 +21,29 @@ def call
# app/views/idv/doc_auth/upload.html.erb
if params[:type] == 'desktop'
handle_desktop_selection
elsif params[:combined]
# The user was shown the new combined view and
# submitted a phone number to this step with feature flag on
# OR
# The user was originally shown the new combined view,
# but has submitted to a step with the feature flag off
# (50/50 from new to old)
handle_phone_submission
else
handle_mobile_selection
end
end

def extra_view_variables
if IdentityConfig.store.doc_auth_combined_hybrid_handoff_enabled
{
idv_phone_form: build_form,
}
else
{}
end
end

private

def handle_desktop_selection
Expand All @@ -35,6 +54,27 @@ def handle_desktop_selection
end
end

def build_form
Idv::PhoneForm.new(
previous_params: {},
user: current_user,
delivery_methods: [:sms],
)
end

def form_submit
return super if !IdentityConfig.store.doc_auth_combined_hybrid_handoff_enabled
return super if params[:type] == 'desktop'

# Remove after 50/50 deploy w/ flag
return super if params[:type] != 'combined'

params = permit(:phone)
params[:otp_delivery_preference] = 'sms'
build_form.submit(params)
end

# To be removed after 50/50
def handle_mobile_selection
if mobile_device?
bypass_send_link_steps
Expand All @@ -43,6 +83,26 @@ def handle_mobile_selection
end
end

def handle_phone_submission
throttle.increment!
return throttled_failure if throttle.throttled?
telephony_result = send_link
failure_reason = nil
if !telephony_result.success?
failure_reason = { telephony: [telephony_result.error.class.name.demodulize] }
end
@flow.irs_attempts_api_tracker.idv_phone_upload_link_sent(
success: telephony_result.success?,
phone_number: formatted_destination_phone,
failure_reason: failure_reason,
)

mark_step_complete(:send_link)
mark_step_complete(:email_sent)

build_telephony_form_response(telephony_result)
end

def identity
current_user&.identities&.order('created_at DESC')&.first
end
Expand Down Expand Up @@ -76,6 +136,81 @@ def bypass_send_link_steps
form_response(destination: :document_capture)
end

def throttle
@throttle ||= Throttle.new(
user: current_user,
throttle_type: :idv_send_link,
)
end

def throttled_failure
@flow.analytics.throttler_rate_limit_triggered(
throttle_type: :idv_send_link,
)
message = I18n.t(
'errors.doc_auth.send_link_throttle',
timeout: distance_of_time_in_words(
Time.zone.now,
[throttle.expires_at, Time.zone.now].compact.max,
except: :seconds,
),
)

@flow.irs_attempts_api_tracker.idv_phone_send_link_rate_limited(
phone_number: formatted_destination_phone,
)

failure(message)
end

def formatted_destination_phone
raw_phone = permit(:phone)[:phone]
PhoneFormatter.format(raw_phone, country_code: 'US')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recognizing there's a lot of legacy here being copied verbatim, I still want to flag that it's a bit problematic how we assume phone numbers are U.S., especially since PhoneInputComponent will provide us with a international_code parameter we can plug in here. I suspect this is a hold-over logic from previous implementation where the phone input was a plain input field.

end

def update_document_capture_session_requested_at(session_uuid)
document_capture_session = DocumentCaptureSession.find_by(uuid: session_uuid)
return unless document_capture_session
document_capture_session.update!(
requested_at: Time.zone.now,
cancelled_at: nil,
issuer: sp_session[:issuer],
)
end

def sp_or_app_name
current_sp&.friendly_name.presence || APP_NAME
end

def link_for_send_link(session_uuid)
idv_capture_doc_dashes_url(
'document-capture-session': session_uuid,
request_id: sp_session[:request_id],
)
end

def send_link
session_uuid = flow_session[:document_capture_session_uuid]
update_document_capture_session_requested_at(session_uuid)
Telephony.send_doc_auth_link(
to: formatted_destination_phone,
link: link_for_send_link(session_uuid),
country_code: Phonelib.parse(formatted_destination_phone).country,
sp_or_app_name: sp_or_app_name,
)
end

def build_telephony_form_response(telephony_result)
FormResponse.new(
success: telephony_result.success?,
errors: { message: telephony_result.error&.friendly_message },
extra: {
telephony_response: telephony_result.to_h,
destination: :link_sent,
},
)
end

def mobile_device?
# See app/javascript/packs/document-capture-welcome.js
# And app/services/idv/steps/agreement_step.rb
Expand Down
74 changes: 74 additions & 0 deletions app/views/idv/doc_auth/_combined_upload.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<% title t('titles.doc_auth.upload') %>

<%= render 'idv/doc_auth/error_messages', flow_session: flow_session %>

<%= render PageHeadingComponent.new do %>
<%= t('doc_auth.headings.combined_upload') %>
<% end %>

<p>
<%= t('doc_auth.info.combined_upload') %>
</p>

<div class="grid-row grid-gap grid-gap-1">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the design reference, it looks like the gap should be 1rem, which would be 2 units in the design system.

Suggested change
<div class="grid-row grid-gap grid-gap-1">
<div class="grid-row grid-gap grid-gap-2">

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This grid-gap-2 update was missed

<div class="grid-col-12 tablet:grid-col-auto">
<%= image_tag(
asset_url('idv/phone-icon.svg'),
alt: t('image_description.camera_mobile_phone'),
width: 88,
height: 88,
) %>
</div>
<div class="grid-col-12 tablet:grid-col-fill">
<div class="usa-tag usa-tag--informative">
<%= t('doc_auth.info.tag') %>
</div>
<h2 class="margin-y-105">
<%= t('doc_auth.headings.combined_upload_from_phone') %>
Copy link
Contributor

@aduth aduth Feb 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, maybe we circle back to unqualify these as "combined", since once the feature is enabled and the feature flag removed, I don't think we need to consider this as anything other than the default text for the screen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that was the plan. Anything with "combined" will be renamed, including querystring params.

</h2>
<%= t('doc_auth.info.combined_upload_from_phone') %>
<%= simple_form_for(
idv_phone_form,
as: :doc_auth,
url: url_for(type: :mobile, combined: true),
method: 'PUT',
html: { autocomplete: 'off' },
) do |f| %>
<%= render PhoneInputComponent.new(
form: f,
required: true,
delivery_methods: [:sms],
class: 'margin-bottom-4',
) %>
<%= f.submit t('forms.buttons.send_link') %>
<% end %>
</div>
</div>

<hr class="margin-y-4" />
<div class="grid-row grid-gap grid-gap-2">
<div class="grid-col-12 tablet:grid-col-auto">
<%= image_tag(
asset_url('idv/laptop-icon.svg'),
alt: t('image_description.laptop'),
width: 88,
height: 88,
) %>
</div>
<div class="grid-col-12 tablet:grid-col-fill">
<h2 class="margin-y-105">
<%= t('doc_auth.headings.combined_upload_from_computer') %>
</h2>
<%= t('doc_auth.info.combined_upload_from_computer') %>&nbsp;
<%= simple_form_for(
:doc_auth,
url: url_for(type: :desktop),
method: 'PUT',
class: 'margin-bottom-4',
) do |f| %>
<%= f.submit t('forms.buttons.upload_photos'), outline: true %>
<% end %>
</div>
</div>

<%= render 'idv/doc_auth/cancel', step: 'upload' %>
55 changes: 55 additions & 0 deletions app/views/idv/doc_auth/_upload.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<% title t('titles.doc_auth.upload') %>

<%= render 'idv/doc_auth/error_messages', flow_session: flow_session %>

<%= render PageHeadingComponent.new do %>
<%= t('doc_auth.headings.upload') %>
<% end %>

<p>
<%= t('doc_auth.info.upload') %>
</p>

<hr class="margin-y-4" />

<div class="grid-row">
<div class="grid-col-12 tablet:grid-col-3">
<%= image_tag(
asset_url('idv/phone.png'),
alt: t('image_description.camera_mobile_phone'),
width: 80,
height: 119,
) %>
</div>
<div class="grid-col-12 tablet:grid-col-9">
<div class="usa-tag text-ink bg-primary-lighter margin-top-1">
<%= t('doc_auth.info.tag') %>
</div>
<h2 class="margin-y-105">
<%= t('doc_auth.headings.upload_from_phone') %>
</h2>
<%= t('doc_auth.info.upload_from_phone') %>
<%= simple_form_for(
:doc_auth,
url: url_for(type: :mobile),
method: 'PUT',
html: { autocomplete: 'off', class: 'margin-top-2' },
) do |f| %>
<%= f.submit t('doc_auth.buttons.use_phone'), wide: false, class: 'margin-top-05' %>
<% end %>
</div>
</div>

<hr class="margin-y-4" />

<%= t('doc_auth.info.upload_from_computer') %>&nbsp;
<%= simple_form_for(
:doc_auth,
url: url_for(type: :desktop),
method: 'PUT',
html: { class: 'display-inline' },
) do |f| %>
<%= f.submit t('doc_auth.info.upload_computer_link'), unstyled: true, big: false %>
<% end %>

<%= render 'idv/doc_auth/cancel', step: 'upload' %>
Loading