Skip to content

Commit

Permalink
Merge pull request #11695 from 18F/stages/rc-2024-12-31
Browse files Browse the repository at this point in the history
Deploy RC 441 to Production
  • Loading branch information
mitchellhenke authored Dec 31, 2024
2 parents 56ea064 + 9b33a89 commit faae3a7
Show file tree
Hide file tree
Showing 76 changed files with 1,288 additions and 382 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def identity
end

def last_email
EmailContext.new(current_user).last_sign_in_email_address.id
current_user.last_sign_in_email_address.id
end
end
end
Expand Down
2 changes: 0 additions & 2 deletions app/controllers/concerns/authorization_count_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
module AuthorizationCountConcern
extend ActiveSupport::Concern

# :reek:DuplicateMethodCall
def auth_count
session[:sp_auth_count] ||= {}
session[:sp_auth_count][sp_session[:request_id]]
end

# :reek:DuplicateMethodCall
def auth_count=(value)
session[:sp_auth_count] ||= {}
session[:sp_auth_count][sp_session[:request_id]] = value
Expand Down
14 changes: 0 additions & 14 deletions app/controllers/concerns/idv/socure_errors_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,6 @@

module Idv
module SocureErrorsConcern
def errors
@presenter = socure_errors_presenter(handle_stored_result)
end

def goto_in_person
InPersonEnrollment.find_or_initialize_by(
user: document_capture_session.user,
status: :establishing,
sponsor_id: IdentityConfig.store.usps_ipp_sponsor_id,
).save!

redirect_to idv_in_person_url
end

private

def remaining_attempts
Expand Down
19 changes: 19 additions & 0 deletions app/controllers/concerns/idv/verify_info_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ def async_state_done(current_async_state)
if form_response.success?
save_threatmetrix_status(form_response)
save_source_check_vendor(form_response)
save_resolution_vendors(form_response)
move_applicant_to_idv_session
idv_session.mark_verify_info_step_complete!

Expand All @@ -247,6 +248,24 @@ def next_step_url
idv_phone_url
end

def save_resolution_vendors(form_response)
idv_session.resolution_vendor = form_response.extra.dig(
:proofing_results,
:context,
:stages,
:resolution,
:vendor_name,
)

idv_session.residential_resolution_vendor = form_response.extra.dig(
:proofing_results,
:context,
:stages,
:residential_address,
:vendor_name,
)
end

def save_threatmetrix_status(form_response)
review_status = form_response.extra.dig(:proofing_results, :threatmetrix_review_status)
idv_session.threatmetrix_review_status = review_status
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/concerns/mfa_setup_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ def threatmetrix_attrs
{
user_id: current_user.id,
request_ip: request&.remote_ip,
threatmetrix_session_id: session[:threatmetrix_session_id],
email: EmailContext.new(current_user).last_sign_in_email_address.email,
threatmetrix_session_id: user_session[:sign_up_threatmetrix_session_id],
email: current_user.last_sign_in_email_address.email,
uuid_prefix: current_sp&.app_id,
}
end
Expand Down
19 changes: 15 additions & 4 deletions app/controllers/idv/by_mail/enter_code_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ def create
result = @gpo_verify_form.submit(resolved_authn_context_result.enhanced_ipp?)
analytics.idv_verify_by_mail_enter_code_submitted(**result)

send_please_call_email_if_necessary(result:)

if !result.success?
if rate_limiter.limited?
redirect_to idv_enter_code_rate_limited_url
Expand Down Expand Up @@ -120,6 +122,19 @@ def rate_limiter
)
end

# @param [FormResponse] result GpoVerifyForm result
def send_please_call_email_if_necessary(result:)
return if !result.success?

return if result.extra[:pending_in_person_enrollment]

return if !result.extra[:fraud_check_failed]

return if !FeatureManagement.proofing_device_profiling_decisioning_enabled?

current_user.send_email_to_all_addresses(:idv_please_call)
end

def build_gpo_verify_form
GpoVerifyForm.new(
user: current_user,
Expand All @@ -138,10 +153,6 @@ def confirm_verification_needed
redirect_to account_url
end

def threatmetrix_enabled?
FeatureManagement.proofing_device_profiling_decisioning_enabled?
end

def pii_locked?
!Pii::Cacher.new(current_user, user_session).exists_in_session?
end
Expand Down
70 changes: 43 additions & 27 deletions app/controllers/idv/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ class DocumentCaptureController < ApplicationController
include IdvStepConcern
include StepIndicatorConcern

before_action :confirm_not_rate_limited, except: [:update]
before_action :confirm_not_rate_limited, except: [:update, :direct_in_person]
before_action :confirm_step_allowed, unless: -> { allow_direct_ipp? }
before_action :override_csp_to_allow_acuant
before_action :set_usps_form_presenter
before_action -> { redirect_to_correct_vendor(Idp::Constants::Vendors::LEXIS_NEXIS, false) },
only: :show
only: [:show], unless: -> { allow_direct_ipp? }

def show
analytics.idv_doc_auth_document_capture_visited(**analytics_arguments)
Expand Down Expand Up @@ -43,20 +43,15 @@ def update
end
end

def extra_view_variables
{
document_capture_session_uuid: document_capture_session_uuid,
mock_client: doc_auth_vendor == 'mock',
flow_path: 'standard',
sp_name: decorated_sp_session.sp_name,
failure_to_proof_url: return_to_sp_failure_to_proof_url(step: 'document_capture'),
skip_doc_auth_from_how_to_verify: idv_session.skip_doc_auth_from_how_to_verify,
skip_doc_auth_from_handoff: idv_session.skip_doc_auth_from_handoff,
opted_in_to_in_person_proofing: idv_session.opted_in_to_in_person_proofing,
doc_auth_selfie_capture: resolved_authn_context_result.facial_match?,
}.merge(
acuant_sdk_upgrade_a_b_testing_variables,
)
# Given that the start of the IPP flow is in the TrueID doc_auth React app,
# we need a generic, direct way to start the IPP flow
def direct_in_person
attributes = {
remaining_submit_attempts: rate_limiter.remaining_count,
}.merge(ab_test_analytics_buckets)
analytics.idv_in_person_direct_start(**attributes)

redirect_to idv_document_capture_url(step: :idv_doc_auth)
end

def self.step_info
Expand All @@ -65,15 +60,15 @@ def self.step_info
controller: self,
next_steps: [:ssn, :ipp_ssn], # :ipp_state_id
preconditions: ->(idv_session:, user:) {
idv_session.flow_path == 'standard' && (
# mobile
idv_session.skip_doc_auth_from_handoff ||
idv_session.skip_hybrid_handoff ||
idv_session.skip_doc_auth_from_how_to_verify ||
!idv_session.selfie_check_required || # desktop but selfie not required
idv_session.desktop_selfie_test_mode_enabled?
)
},
idv_session.flow_path == 'standard' && (
# mobile
idv_session.skip_doc_auth_from_handoff ||
idv_session.skip_hybrid_handoff ||
idv_session.skip_doc_auth_from_how_to_verify ||
!idv_session.selfie_check_required || # desktop but selfie not required
idv_session.desktop_selfie_test_mode_enabled?
)
},
undo_step: ->(idv_session:, user:) do
idv_session.pii_from_doc = nil
idv_session.invalidate_in_person_pii_from_user!
Expand All @@ -86,6 +81,22 @@ def self.step_info

private

def extra_view_variables
{
document_capture_session_uuid: document_capture_session_uuid,
mock_client: doc_auth_vendor == 'mock',
flow_path: 'standard',
sp_name: decorated_sp_session.sp_name,
failure_to_proof_url: return_to_sp_failure_to_proof_url(step: 'document_capture'),
skip_doc_auth_from_how_to_verify: idv_session.skip_doc_auth_from_how_to_verify,
skip_doc_auth_from_handoff: idv_session.skip_doc_auth_from_handoff,
opted_in_to_in_person_proofing: idv_session.opted_in_to_in_person_proofing,
doc_auth_selfie_capture: resolved_authn_context_result.facial_match?,
}.merge(
acuant_sdk_upgrade_a_b_testing_variables,
)
end

def analytics_arguments
{
flow_path: flow_path,
Expand All @@ -102,8 +113,9 @@ def allow_direct_ipp?
return false unless idv_session.welcome_visited &&
idv_session.idv_consent_given?
# not allowed when no step param and action:show(get request)
return false if params[:step].blank? || params[:action].to_s != 'show' ||
idv_session.flow_path == 'hybrid'
return false if params[:step].blank?
return false if params[:action].to_s != 'show' && params[:action] != 'direct_in_person'
return false if idv_session.flow_path == 'hybrid'
# Only allow direct access to document capture if IPP available
return false unless IdentityConfig.store.in_person_doc_auth_button_enabled &&
Idv::InPersonConfig.enabled_for_issuer?(decorated_sp_session.sp_issuer)
Expand All @@ -118,5 +130,9 @@ def allow_direct_ipp?
def set_usps_form_presenter
@presenter = Idv::InPerson::UspsFormPresenter.new
end

def rate_limiter
RateLimiter.new(user: idv_session.current_user, rate_limit_type: :idv_doc_auth)
end
end
end
4 changes: 4 additions & 0 deletions app/controllers/idv/enter_password_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ def init_profile
log_letter_enqueued_analytics(resend: false)
end

if profile.fraud_review_pending? && !profile.in_person_verification_pending?
current_user.send_email_to_all_addresses(:idv_please_call)
end

if profile.active?
create_user_event(:account_verified)
UserAlerts::AlertUserAboutAccountVerified.call(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,19 @@ def update
end
end

def errors
@presenter = socure_errors_presenter(handle_stored_result)
end

private

def socure_errors_presenter(result)
SocureErrorPresenter.new(
error_code: error_code_for(result),
remaining_attempts:,
sp_name: decorated_sp_session&.sp_name || APP_NAME,
hybrid_mobile: true,
issuer: decorated_sp_session&.sp_issuer,
flow_path: :hybrid,
)
end

Expand Down
2 changes: 2 additions & 0 deletions app/controllers/idv/in_person/verify_info_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ def self.step_info
idv_session.ssn && idv_session.ipp_document_capture_complete?
end,
undo_step: ->(idv_session:, user:) do
idv_session.residential_resolution_vendor = nil
idv_session.resolution_successful = nil
idv_session.resolution_vendor = nil
idv_session.verify_info_step_document_capture_session_uuid = nil
idv_session.threatmetrix_review_status = nil
idv_session.source_check_vendor = nil
Expand Down
14 changes: 1 addition & 13 deletions app/controllers/idv/socure/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ class DocumentCaptureController < ApplicationController
include IdvStepConcern
include DocumentCaptureConcern
include RenderConditionConcern
include SocureErrorsConcern

check_or_render_not_found -> { IdentityConfig.store.socure_docv_enabled }
before_action :confirm_not_rate_limited
Expand Down Expand Up @@ -112,24 +111,13 @@ def self.step_info

private

def socure_errors_presenter(result)
SocureErrorPresenter.new(
error_code: error_code_for(result),
remaining_attempts:,
sp_name: decorated_sp_session&.sp_name || APP_NAME,
hybrid_mobile: false,
)
end

def wait_for_result?
return false if stored_result.present?

# If the stored_result is nil, the job fetching the results has not completed.
analytics.idv_doc_auth_document_capture_polling_wait_visited(**analytics_arguments)
if wait_timed_out?
# flash[:error] = I18n.t('errors.doc_auth.polling_timeout')
# TODO: redirect to try again page LG-14873/14952/15059
render plain: 'Technical difficulties!!!', status: :ok
redirect_to idv_socure_errors_timeout_path
else
@refresh_interval =
IdentityConfig.store.doc_auth_socure_wait_polling_refresh_max_seconds
Expand Down
80 changes: 80 additions & 0 deletions app/controllers/idv/socure/errors_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# frozen_string_literal: true

module Idv
module Socure
class ErrorsController < ApplicationController
include DocumentCaptureConcern
include AvailabilityConcern
include IdvStepConcern
include StepIndicatorConcern
include AbTestAnalyticsConcern

before_action :confirm_step_allowed

def show
error_code = error_code_for(handle_stored_result)
track_event(error_code: error_code)
@presenter = socure_errors_presenter(error_code)
end

def timeout
track_event(error_code: :timeout)
@presenter = socure_errors_presenter(:timeout)
render :show
end

def self.step_info
Idv::StepInfo.new(
key: :socure_errors,
controller: self,
action: :timeout,
next_steps: [FlowPolicy::FINAL],
preconditions: ->(idv_session:, user:) do
# idv_session.socure_docv_wait_polling_started_at.present?
true
end,
undo_step: ->(idv_session:, user:) {},
)
end

private

def rate_limiter
RateLimiter.new(user: idv_session.current_user, rate_limit_type: :idv_doc_auth)
end

def remaining_submit_attempts
@remaining_submit_attempts ||= rate_limiter.remaining_count
end

def track_event(error_code:)
attributes = { error_code: }.merge(ab_test_analytics_buckets)
attributes[:remaining_submit_attempts] = remaining_submit_attempts

analytics.idv_doc_auth_socure_error_visited(**attributes)
end

def socure_errors_presenter(error_code)
SocureErrorPresenter.new(
error_code:,
remaining_attempts: remaining_submit_attempts,
sp_name: decorated_sp_session&.sp_name || APP_NAME,
issuer: decorated_sp_session&.sp_issuer,
flow_path:,
)
end

def error_code_for(result)
if result.errors[:socure]
result.errors.dig(:socure, :reason_codes).first
elsif result.errors[:network]
:network
else
# No error information available (shouldn't happen). Default
# to :network if it does.
:network
end
end
end
end
end
Loading

0 comments on commit faae3a7

Please sign in to comment.