Skip to content

Commit

Permalink
Merge pull request #11562 from 18F/stages/rc-2024-11-26
Browse files Browse the repository at this point in the history
Deploy RC 434 to Production
  • Loading branch information
amirbey authored Nov 26, 2024
2 parents ab4568c + a5dcf58 commit d654ec4
Show file tree
Hide file tree
Showing 94 changed files with 2,865 additions and 1,405 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ gem 'rqrcode'
gem 'ruby-progressbar'
gem 'ruby-saml'
gem 'safe_target_blank', '>= 1.0.2'
gem 'saml_idp', github: '18F/saml_idp', tag: '0.23.0-18f'
gem 'saml_idp', github: '18F/saml_idp', tag: '0.23.3-18f'
gem 'scrypt'
gem 'simple_form', '>= 5.0.2'
gem 'stringex', require: false
Expand Down
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ GIT

GIT
remote: https://github.com/18F/saml_idp.git
revision: 23b69117593e9b9217910af1dd627febd8d18cf4
tag: 0.23.0-18f
revision: 752085a6f88cd3ce75ecc7a64afe064a0e4f9e35
tag: 0.23.3-18f
specs:
saml_idp (0.23.0.pre.18f)
saml_idp (0.23.3.pre.18f)
activesupport
builder
faraday
Expand Down
8 changes: 7 additions & 1 deletion app/controllers/idv/enter_password_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,13 @@ def confirm_current_password
def init_profile
idv_session.create_profile_from_applicant_with_password(
password,
resolved_authn_context_result.enhanced_ipp?,
is_enhanced_ipp: resolved_authn_context_result.enhanced_ipp?,
proofing_components: ProofingComponents.new(
user: current_user,
idv_session:,
session:,
user_session:,
).to_h,
)
if idv_session.verify_by_mail?
current_user.send_email_to_all_addresses(:verify_by_mail_letter_requested)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ module Idv
module HybridMobile
module Socure
class DocumentCaptureController < ApplicationController
include Idv::AvailabilityConcern
include AvailabilityConcern
include DocumentCaptureConcern
include Idv::HybridMobile::HybridMobileConcern
include RenderConditionConcern
include DocumentCaptureConcern

check_or_render_not_found -> { IdentityConfig.store.socure_docv_enabled }
before_action :check_valid_document_capture_session, except: [:update]
Expand Down Expand Up @@ -50,17 +49,64 @@ def show
end

def update
return if wait_for_result?

result = handle_stored_result(
user: document_capture_session.user,
store_in_session: false,
)
# TODO: new analytics event?
analytics.idv_doc_auth_document_capture_submitted(
**result.to_h.merge(analytics_arguments),
)

if result.success?
redirect_to idv_hybrid_mobile_capture_complete_url
else
redirect_to idv_hybrid_mobile_socure_document_capture_url
end
end

private

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
else
@refresh_interval =
IdentityConfig.store.doc_auth_socure_wait_polling_refresh_max_seconds
render 'idv/socure/document_capture/wait'
end

true
end

def wait_timed_out?
if session[:socure_docv_wait_polling_started_at].nil?
session[:socure_docv_wait_polling_started_at] = Time.zone.now.to_s
return false
end
start = DateTime.parse(session[:socure_docv_wait_polling_started_at])
timeout_period =
IdentityConfig.store.doc_auth_socure_wait_polling_timeout_minutes.minutes || 2.minutes
start + timeout_period < Time.zone.now
end

def analytics_arguments
{
flow_path: 'hybrid',
step: 'socure_document_capture',
analytics_id: 'Doc Auth',
liveness_checking_required: false,
selfie_check_required: false,
}
end
end
end
end
Expand Down
38 changes: 21 additions & 17 deletions app/controllers/idv/socure/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,13 @@ def show
end

def update
return if wait_for_result?

clear_future_steps!
idv_session.redo_document_capture = nil # done with this redo
# Not used in standard flow, here for data consistency with hybrid flow.
document_capture_session.confirm_ocr

# If the stored_result is nil, the job fetching the results has not completed.
if stored_result.nil?
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
else
@refresh_interval =
IdentityConfig.store.doc_auth_socure_wait_polling_refresh_max_seconds
render 'idv/socure/document_capture/wait'
end

return
end

result = handle_stored_result
# TODO: new analytics event?
analytics.idv_doc_auth_document_capture_submitted(**result.to_h.merge(analytics_arguments))
Expand Down Expand Up @@ -121,14 +107,32 @@ def self.step_info

private

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
else
@refresh_interval =
IdentityConfig.store.doc_auth_socure_wait_polling_refresh_max_seconds
render 'idv/socure/document_capture/wait'
end

true
end

def wait_timed_out?
if idv_session.socure_docv_wait_polling_started_at.nil?
idv_session.socure_docv_wait_polling_started_at = Time.zone.now.to_s
return false
end
start = DateTime.parse(idv_session.socure_docv_wait_polling_started_at)
timeout_period =
IdentityConfig.store.doc_auth_socure_wait_polling_timeout_minutes.minutes || 5.minutes
IdentityConfig.store.doc_auth_socure_wait_polling_timeout_minutes.minutes || 2.minutes
start + timeout_period < Time.zone.now
end

Expand Down
24 changes: 24 additions & 0 deletions app/controllers/saml_idp_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ def capture_analytics

if result.success? && saml_request.signed?
analytics_payload[:cert_error_details] = saml_request.cert_errors

# analytics to determine if turning on SHA256 validation will break
# existing partners
if certs_different?
analytics_payload[:certs_different] = true
analytics_payload[:sha256_matching_cert] = sha256_alg_matching_cert_serial
end
end

analytics.saml_auth(**analytics_payload)
Expand All @@ -147,6 +154,21 @@ def matching_cert_serial
nil
end

def sha256_alg_matching_cert
# if sha256_alg_matching_cert is nil, fallback to the "first" cert
saml_request.sha256_validation_matching_cert ||
saml_request_service_provider&.ssl_certs&.first
rescue SamlIdp::XMLSecurity::SignedDocument::ValidationError
end

def sha256_alg_matching_cert_serial
sha256_alg_matching_cert&.serial&.to_s
end

def certs_different?
encryption_cert != sha256_alg_matching_cert
end

def log_external_saml_auth_request
return unless external_saml_request?

Expand All @@ -158,6 +180,8 @@ def log_external_saml_auth_request
force_authn: saml_request&.force_authn?,
final_auth_request: sp_session[:final_auth_request],
service_provider: saml_request&.issuer,
request_signed: saml_request.signed?,
matching_cert_serial:,
unknown_authn_contexts:,
user_fully_authenticated: user_fully_authenticated?,
)
Expand Down
10 changes: 1 addition & 9 deletions app/controllers/users/reset_passwords_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
module Users
class ResetPasswordsController < Devise::PasswordsController
include AuthorizationCountConcern
include AbTestingConcern

before_action :store_sp_metadata_in_session, only: [:edit]
before_action :store_token_in_session, only: [:edit]

Expand Down Expand Up @@ -44,13 +42,7 @@ def edit

def update
self.resource = user_matching_token(user_params[:reset_password_token])
@reset_password_form = ResetPasswordForm.new(
user: resource,
log_password_matches_existing: ab_test_bucket(
:LOG_PASSWORD_RESET_MATCHES_EXISTING,
user: resource,
) == :log,
)
@reset_password_form = ResetPasswordForm.new(user: resource)

result = @reset_password_form.submit(user_params)

Expand Down
10 changes: 10 additions & 0 deletions app/controllers/users/webauthn_platform_recommended_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,22 @@ def new

def create
analytics.webauthn_platform_recommended_submitted(opted_to_add: opted_to_add?)
store_webauthn_platform_recommended_in_session if opted_to_add?
current_user.update(webauthn_platform_recommended_dismissed_at: Time.zone.now)
redirect_to dismiss_redirect_path
end

private

def store_webauthn_platform_recommended_in_session
user_session[:webauthn_platform_recommended] =
if in_account_creation_flow?
:account_creation
else
:authentication
end
end

def opted_to_add?
params[:add_method].present?
end
Expand Down
1 change: 1 addition & 0 deletions app/controllers/users/webauthn_setup_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def process_valid_webauthn(form)
def analytics_properties
{
in_account_creation_flow: user_session[:in_account_creation_flow] || false,
webauthn_platform_recommended: user_session[:webauthn_platform_recommended],
attempts: mfa_attempts_count,
}
end
Expand Down
8 changes: 1 addition & 7 deletions app/forms/reset_password_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ class ResetPasswordForm
include FormPasswordValidator

attr_accessor :reset_password_token
private attr_reader :log_password_matches_existing
alias_method :log_password_matches_existing?, :log_password_matches_existing

validate :valid_token

def initialize(user:, log_password_matches_existing: false)
def initialize(user:)
@user = user
@log_password_matches_existing = log_password_matches_existing
@reset_password_token = @user.reset_password_token
@validate_confirmation = true
@active_profile = user.active_profile
Expand Down Expand Up @@ -50,8 +47,6 @@ def handle_valid_password
end

def update_user
@password_matches_existing = user.valid_password?(password) if log_password_matches_existing?

attributes = { password: password }

ActiveRecord::Base.transaction do
Expand Down Expand Up @@ -92,7 +87,6 @@ def extra_analytics_attributes
{
user_id: user.uuid,
profile_deactivated: active_profile.present?,
password_matches_existing: @password_matches_existing,
pending_profile_invalidated: pending_profile.present?,
pending_profile_pending_reasons: (pending_profile&.pending_reasons || [])&.join(','),
}
Expand Down
22 changes: 17 additions & 5 deletions app/helpers/script_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,26 @@ def render_javascript_pack_once_tags(...)
javascript_packs_tag_once(...)
return if @scripts.blank?
concat javascript_assets_tag
crossorigin = local_crossorigin_sources?.presence
@scripts.each do |name, (url_params, attributes)|
asset_sources.get_sources(name).each do |source|
concat javascript_include_tag(
UriService.add_params(source, url_params),
integrity = asset_sources.get_integrity(source)

if attributes[:preload_links_header] != false
AssetPreloadLinker.append(
headers: response.headers,
as: :script,
url: source,
crossorigin:,
integrity:,
)
end

concat tag.script(
src: UriService.add_params(source, url_params),
**attributes,
crossorigin: local_crossorigin_sources? ? true : nil,
integrity: asset_sources.get_integrity(source),
nopush: false,
crossorigin:,
integrity:,
)
end
end
Expand Down
8 changes: 7 additions & 1 deletion app/helpers/stylesheet_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ def stylesheet_tag_once(*names)
def render_stylesheet_once_tags(*names)
stylesheet_tag_once(*names) if names.present?
return if @stylesheets.blank?
safe_join(@stylesheets.map { |stylesheet| stylesheet_link_tag(stylesheet, nopush: false) })
safe_join(
@stylesheets.map do |stylesheet|
url = stylesheet_path(stylesheet)
AssetPreloadLinker.append(headers: response.headers, as: :style, url:)
tag.link(rel: :stylesheet, href: url)
end,
)
end
end
# rubocop:enable Rails/HelperInstanceVariable
2 changes: 1 addition & 1 deletion app/javascript/packages/analytics/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DAP_SHA ?= 7c14bb3
DAP_SHA ?= eebc4d1

digital-analytics-program.js: digital-analytics-program-$(DAP_SHA).js digital-analytics-program.patch
patch -p1 $^ --output $@
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
73a74
> GA4Object.defer = true;
785d785
< var piiRegex = [];
900c900
< piiRegex.forEach(function (pii) {
---
> window.piiRegex.forEach(function (pii) {
87a88
> GA4Object.defer = true;
2 changes: 1 addition & 1 deletion app/jobs/resolution_proofing_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def perform(

if IdentityConfig.store.idv_socure_shadow_mode_enabled
SocureShadowModeProofingJob.perform_later(
document_capture_session_result_id: document_capture_session.result_id,
document_capture_session_result_id: document_capture_session&.result_id,
encrypted_arguments:,
service_provider_issuer:,
user_email: user_email_for_proofing(user),
Expand Down
2 changes: 1 addition & 1 deletion app/jobs/socure_docv_results_job.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

class SocureDocvResultsJob < ApplicationJob
queue_as :default
queue_as :high_socure_docv

attr_reader :document_capture_session_uuid

Expand Down
Loading

0 comments on commit d654ec4

Please sign in to comment.