Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 2 additions & 3 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"no-restricted-syntax": [
"error",
{
"selector": "AssignmentExpression[left.property.name='href'][right.type=/(Template)?Literal/],NewExpression[callee.name=URL][arguments.0.type=/(Template)?Literal/]",
"message": "Avoid hard-coded string URLs, since they will not include the current locale"
"selector": "AssignmentExpression[left.property.name='href'][right.type=/(Template)?Literal/]",
"message": "Do not assign window.location.href to a string or string template to avoid losing i18n parameters"
}
],
"react-hooks/exhaustive-deps": "error"
Expand All @@ -42,7 +42,6 @@
"packageDir": "."
}
],
"no-restricted-syntax": "off",
"testing-library/await-async-events": "error",
"testing-library/await-async-queries": "error",
"testing-library/await-async-utils": "error",
Expand Down
76 changes: 27 additions & 49 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ stages:

workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "external_pull_request_event" || $CI_PIPELINE_SOURCE == "schedule"'
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "external_pull_request_event"'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "external_pull_request_event" || $CI_PIPELINE_SOURCE == "web"'
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "stages/prod"'
- if: '$CI_MERGE_REQUEST_IID || $CI_EXTERNAL_PULL_REQUEST_IID'
Expand Down Expand Up @@ -339,6 +341,30 @@ js_tests:
- *yarn_install
- yarn test

pinpoint-check:
needs:
- job: install
stage: test
cache:
- <<: *ruby_cache
- <<: *yarn_cache
script:
- *bundle_install
- *yarn_install
- make lint_country_dialing_codes

audit_packages:
needs:
- job: install
stage: test
cache:
- <<: *ruby_cache
- <<: *yarn_cache
script:
- *bundle_install
- *yarn_install
- make audit

prepare_deploy:
# Runs in parallel with tests so we can deploy more quickly after passing
stage: test
Expand Down Expand Up @@ -812,51 +838,3 @@ ecr-scan-ci:
stage: scan
variables:
ecr_repo: idp/ci

pinpoint_check_scheduled:
needs:
- job: install
cache:
- <<: *ruby_cache
- <<: *yarn_cache
script:
- *bundle_install
- *yarn_install
- make lint_country_dialing_codes
after_script:
- |-
if [ "$CI_JOB_STATUS" != "success" ]; then
./scripts/notify-slack \
--icon ":gitlab:" \
--username "gitlab-notify" \
--channel "#login-appdev" \
--webhook "${SLACK_WEBHOOK}" \
--raise \
--text "Pinpoint supported countries check in GitLab failed.\nBuild Results: ${CI_JOB_URL}.\nCheck results locally with 'make lint_country_dialing_codes'"
fi
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"

audit_packages_scheduled:
needs:
- job: install
cache:
- <<: *ruby_cache
- <<: *yarn_cache
script:
- *bundle_install
- *yarn_install
- make audit
after_script:
- |-
if [ "$CI_JOB_STATUS" != "success" ]; then
./scripts/notify-slack \
--icon ":gitlab:" \
--username "gitlab-notify" \
--channel "#login-appdev" \
--webhook "${SLACK_WEBHOOK}" \
--raise \
--text "Dependencies audit in GitLab failed.\nBuild Results: ${CI_JOB_URL}\nCheck results locally with 'make audit'"
fi
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
52 changes: 0 additions & 52 deletions app/controllers/concerns/idv/verify_by_mail_concern.rb

This file was deleted.

4 changes: 2 additions & 2 deletions app/controllers/concerns/idv_step_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ module IdvStepConcern
include RateLimitConcern
include FraudReviewConcern
include Idv::AbTestAnalyticsConcern
include Idv::VerifyByMailConcern

included do
before_action :confirm_two_factor_authenticated
Expand Down Expand Up @@ -51,7 +50,8 @@ def check_for_mail_only_outage
end

def redirect_for_mail_only
if gpo_verify_by_mail_policy.send_letter_available?
policy = Idv::GpoVerifyByMailPolicy.new(current_user)
if policy.send_letter_available?
redirect_to idv_mail_only_warning_url
else
redirect_to vendor_outage_url
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/concerns/rate_limit_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ def confirm_not_rate_limited_for_phone_address_verification
private

def confirm_not_rate_limited_for_phone_and_letter_address_verification
if idv_attempter_rate_limited?(:proof_address) && gpo_verify_by_mail_policy.rate_limited?
gpo_policy = Idv::GpoVerifyByMailPolicy.new(current_user)
if idv_attempter_rate_limited?(:proof_address) && gpo_policy.rate_limited?
rate_limit_redirect!(:proof_address)
return true
end
Expand Down
20 changes: 9 additions & 11 deletions app/controllers/idv/by_mail/enter_code_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ class EnterCodeController < ApplicationController
include IdvSessionConcern
include Idv::StepIndicatorConcern
include FraudReviewConcern
include AbTestAnalyticsConcern
include VerifyByMailConcern

prepend_before_action :note_if_user_did_not_receive_letter
before_action :confirm_two_factor_authenticated
Expand All @@ -18,7 +16,7 @@ def index
analytics.idv_verify_by_mail_enter_code_visited(
source: user_did_not_receive_letter? ? 'gpo_reminder_email' : nil,
otp_rate_limited: rate_limiter.limited?,
user_can_request_another_letter: gpo_verify_by_mail_policy.resend_letter_available?,
user_can_request_another_letter: user_can_request_another_letter?,
)

if rate_limiter.limited?
Expand All @@ -28,12 +26,7 @@ def index
end

prefilled_code = session[:last_gpo_confirmation_code] if FeatureManagement.reveal_gpo_code?
@gpo_verify_form = GpoVerifyForm.new(
user: current_user,
pii: pii,
resolved_authn_context_result: resolved_authn_context_result,
otp: prefilled_code,
)
@gpo_verify_form = GpoVerifyForm.new(user: current_user, pii: pii, otp: prefilled_code)
render_enter_code_form
end

Expand Down Expand Up @@ -70,7 +63,7 @@ def create
private

def render_enter_code_form
@can_request_another_letter = gpo_verify_by_mail_policy.resend_letter_available?
@can_request_another_letter = user_can_request_another_letter?
@user_did_not_receive_letter = user_did_not_receive_letter?
@last_date_letter_was_sent = last_date_letter_was_sent
render :index
Expand Down Expand Up @@ -126,7 +119,6 @@ def build_gpo_verify_form
GpoVerifyForm.new(
user: current_user,
pii: pii,
resolved_authn_context_result: resolved_authn_context_result,
otp: params_otp,
)
end
Expand Down Expand Up @@ -154,6 +146,12 @@ def user_did_not_receive_letter?
params[:did_not_receive_letter].present?
end

def user_can_request_another_letter?
return @user_can_request_another_letter if defined?(@user_can_request_another_letter)
policy = Idv::GpoVerifyByMailPolicy.new(current_user)
@user_can_request_another_letter = policy.resend_letter_available?
end

def last_date_letter_was_sent
return @last_date_letter_was_sent if defined?(@last_date_letter_was_sent)

Expand Down
96 changes: 91 additions & 5 deletions app/controllers/idv/by_mail/request_letter_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,42 @@ module ByMail
class RequestLetterController < ApplicationController
include Idv::AvailabilityConcern
include IdvStepConcern
skip_before_action :confirm_no_pending_gpo_profile
include Idv::StepIndicatorConcern
include VerifyByMailConcern

before_action :confirm_mail_not_rate_limited
before_action :confirm_step_allowed
before_action :confirm_profile_not_too_old

def index
@applicant = idv_session.applicant
@presenter = RequestLetterPresenter.new(current_user, url_options)

Funnel::DocAuth::RegisterStep.new(current_user.id, current_sp&.issuer).
call(:usps_address, :view, true)
analytics.idv_request_letter_visited
analytics.idv_request_letter_visited(
letter_already_sent: @presenter.resend_requested?,
)
end

def create
clear_future_steps!
update_tracking
idv_session.address_verification_mechanism = :gpo
redirect_to idv_enter_password_url

if resend_requested? && pii_locked?
redirect_to capture_password_url
elsif resend_requested?
resend_letter
flash[:success] = t('idv.messages.gpo.another_letter_on_the_way')
redirect_to idv_letter_enqueued_url
else
redirect_to idv_enter_password_url
end
end

def gpo_mail_policy
@gpo_mail_policy ||= Idv::GpoVerifyByMailPolicy.new(current_user)
end

def self.step_info
Expand All @@ -41,18 +58,87 @@ def self.step_info

private

def confirm_profile_not_too_old
redirect_to idv_path if gpo_mail_policy.profile_too_old?
end

def update_tracking
Funnel::DocAuth::RegisterStep.new(current_user.id, current_sp&.issuer).
call(:usps_letter_sent, :update, true)

log_letter_requested_analytics(resend: false)
analytics.idv_gpo_address_letter_requested(
resend: resend_requested?,
first_letter_requested_at: first_letter_requested_at,
hours_since_first_letter:
hours_since_first_letter(first_letter_requested_at),
phone_step_attempts: RateLimiter.new(
user: current_user,
rate_limit_type: :proof_address,
).attempts,
**ab_test_analytics_buckets,
)
create_user_event(:gpo_mail_sent, current_user)

ProofingComponent.find_or_create_by(user: current_user).update(address_check: 'gpo_letter')
end

def resend_requested?
current_user.gpo_verification_pending_profile?
end

def first_letter_requested_at
current_user.gpo_verification_pending_profile&.gpo_verification_pending_at
end

def hours_since_first_letter(first_letter_requested_at)
first_letter_requested_at ?
(Time.zone.now - first_letter_requested_at).to_i.seconds.in_hours.to_i : 0
end

def confirm_mail_not_rate_limited
redirect_to idv_enter_password_url if gpo_verify_by_mail_policy.rate_limited?
redirect_to idv_enter_password_url if gpo_mail_policy.rate_limited?
end

def resend_letter
analytics.idv_gpo_address_letter_enqueued(
enqueued_at: Time.zone.now,
resend: true,
first_letter_requested_at: first_letter_requested_at,
hours_since_first_letter:
hours_since_first_letter(first_letter_requested_at),
phone_step_attempts: RateLimiter.new(
user: current_user,
rate_limit_type: :proof_address,
).attempts,
**ab_test_analytics_buckets,
)
confirmation_maker = confirmation_maker_perform
send_reminder
return unless FeatureManagement.reveal_gpo_code?
session[:last_gpo_confirmation_code] = confirmation_maker.otp
end

def confirmation_maker_perform
confirmation_maker = GpoConfirmationMaker.new(
pii: pii,
service_provider: current_sp,
profile: current_user.pending_profile,
)
confirmation_maker.perform
confirmation_maker
end

def pii
Pii::Cacher.new(current_user, user_session).
fetch(current_user.gpo_verification_pending_profile.id)
end

def send_reminder
current_user.send_email_to_all_addresses(:verify_by_mail_letter_requested)
end

def pii_locked?
!Pii::Cacher.new(current_user, user_session).exists_in_session?
end

def step_indicator_steps
Expand Down
Loading