18F/identity-idp

View on GitHub
app/controllers/idv/by_mail/enter_code_controller.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

module Idv
  module ByMail
    class EnterCodeController < ApplicationController
      include Idv::AvailabilityConcern
      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
      before_action :confirm_verification_needed

      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?,
        )

        if rate_limiter.limited?
          return redirect_to idv_enter_code_rate_limited_url
        elsif pii_locked?
          return redirect_to capture_password_url
        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,
        )
        render_enter_code_form
      end

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

      def create
        if rate_limiter.limited?
          redirect_to idv_enter_code_rate_limited_url
          return
        end

        rate_limiter.increment!

        @gpo_verify_form = build_gpo_verify_form

        result = @gpo_verify_form.submit(resolved_authn_context_result.enhanced_ipp?)
        analytics.idv_verify_by_mail_enter_code_submitted(**result.to_h)

        if !result.success?
          if rate_limiter.limited?
            redirect_to idv_enter_code_rate_limited_url
          else
            render_enter_code_form
          end
        else
          prepare_for_personal_key
          redirect_to idv_personal_key_url
        end
      end

      private

      def render_enter_code_form
        @can_request_another_letter = gpo_verify_by_mail_policy.resend_letter_available?
        @user_did_not_receive_letter = user_did_not_receive_letter?
        @last_date_letter_was_sent = last_date_letter_was_sent
        render :index
      end

      def pending_in_person_enrollment?
        return false unless IdentityConfig.store.in_person_proofing_enabled
        current_user.pending_in_person_enrollment.present?
      end

      def account_not_ready_to_be_activated?
        fraud_check_failed? || pending_in_person_enrollment?
      end

      def note_if_user_did_not_receive_letter
        if !current_user && user_did_not_receive_letter?
          # Stash that the user didn't receive their letter.
          # Once the authentication process completes, they'll be redirected to complete their
          # GPO verification...
          session[:gpo_user_did_not_receive_letter] = true
        end

        if current_user && session.delete(:gpo_user_did_not_receive_letter)
          # ...and we can pick things up here.
          redirect_to idv_verify_by_mail_enter_code_path(did_not_receive_letter: 1)
        end
      end

      def prepare_for_personal_key
        unless account_not_ready_to_be_activated?
          event, _disavowal_token = create_user_event(:account_verified)

          UserAlerts::AlertUserAboutAccountVerified.call(
            user: current_user,
            date_time: event.created_at,
            sp_name: decorated_sp_session.sp_name,
          )
          flash[:success] = t('account.index.verification.success')
      end

        idv_session.address_verification_mechanism = 'gpo'
        idv_session.address_confirmed!
      end

      def rate_limiter
        @rate_limiter ||= RateLimiter.new(
          user: current_user,
          rate_limit_type: :verify_gpo_key,
        )
      end

      def build_gpo_verify_form
        GpoVerifyForm.new(
          user: current_user,
          pii: pii,
          resolved_authn_context_result: resolved_authn_context_result,
          otp: params_otp,
        )
      end

      def params_otp
        params.require(:gpo_verify_form).permit(:otp)[:otp]
      end

      def confirm_verification_needed
        return if current_user.gpo_verification_pending_profile?
        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

      # GPO reminder emails include an "I did not receive my letter!" link that results in
      # slightly different copy on this screen.
      def user_did_not_receive_letter?
        params[:did_not_receive_letter].present?
      end

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

        @last_date_letter_was_sent = current_user.
          gpo_verification_pending_profile&.
          gpo_confirmation_codes&.
          pluck(:updated_at)&.
          max
      end
    end
  end
end