18F/identity-idp

View on GitHub
app/controllers/two_factor_authentication/sms_opt_in_controller.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# frozen_string_literal: true

module TwoFactorAuthentication
  class SmsOptInController < ApplicationController
    before_action :load_phone

    def new
      @cancel_url = cancel_url
      @presenter = TwoFactorAuthCode::SmsOptInPresenter.new

      analytics.sms_opt_in_visit(
        new_user: new_user?,
        has_other_auth_methods: has_other_auth_methods?,
        phone_configuration_id: @phone_configuration.id,
      )
    end

    def create
      response = opt_out_manager.opt_in_phone_number(@phone_configuration.formatted_phone)

      analytics.sms_opt_in_submitted(
        **response.to_h.merge(
          new_user: new_user?,
          has_other_auth_methods: has_other_auth_methods?,
          phone_configuration_id: @phone_configuration.id,
        ),
      )

      if response.success?
        @phone_number_opt_out.opt_in
        redirect_to otp_send_url(otp_delivery_selection_form: { otp_delivery_preference: :sms })
      else
        @cancel_url = cancel_url
        @presenter = TwoFactorAuthCode::SmsOptInPresenter.new

        if !response.error
          # unsuccessful, but didn't throw an exception: already opted in last 30 days
          render :error
        else
          # one-off error, show form so users can try again
          flash[:error] = t('two_factor_authentication.opt_in.error_retry')
          render :new
        end
      end
    end

    private

    def opt_out_manager
      Telephony::Pinpoint::OptOutManager.new
    end

    def mfa_context
      @mfa_context ||= MfaContext.new(current_user)
    end

    def load_phone
      @phone_number_opt_out = PhoneNumberOptOut.from_param(params[:opt_out_uuid])
      @phone_configuration = mfa_context.phone_configurations.find do |phone_config|
        phone_config.formatted_phone == @phone_number_opt_out.formatted_phone
      end || PhoneConfiguration.new(phone: @phone_number_opt_out.formatted_phone)
    rescue ActiveRecord::RecordNotFound
      render_not_found
    end

    def cancel_url
      if user_fully_authenticated?
        account_path
      elsif decorated_sp_session.sp_name
        return_to_sp_cancel_path(step: :sms_opt_in)
      else
        sign_out_path
      end
    end

    def has_other_auth_methods?
      two_factor_configurations.
        any? { |config| config.mfa_enabled? && config != @phone_configuration }
    end

    def new_user?
      two_factor_configurations.none?
    end

    def two_factor_configurations
      @two_factor_configurations ||= mfa_context.two_factor_configurations
    end
  end
end