18F/identity-idp

View on GitHub
app/forms/webauthn_visit_form.rb

Summary

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

class WebauthnVisitForm
  include ActiveModel::Model
  include ActionView::Helpers::UrlHelper
  include Rails.application.routes.url_helpers

  attr_reader :url_options, :in_mfa_selection_flow

  INVALID_STATE_ERROR = 'InvalidStateError'
  NOT_SUPPORTED_ERROR = 'NotSupportedError'

  def initialize(user:, url_options:, in_mfa_selection_flow:)
    @user = user
    @url_options = url_options
    @in_mfa_selection_flow = in_mfa_selection_flow
  end

  def submit(params)
    @platform_authenticator = params[:platform].to_s == 'true'
    check_params(params)
    FormResponse.new(success: errors.empty?, errors: errors, extra: extra_analytics_attributes)
  end

  def platform_authenticator?
    @platform_authenticator
  end

  def current_mfa_setup_path
    if mfa_user.two_factor_enabled? && !in_mfa_selection_flow
      account_path
    else
      authentication_methods_setup_path
    end
  end

  private

  def check_params(params)
    error = params[:error]
    return unless error

    if @platform_authenticator
      errors.add error, translate_platform_authenticator_error(error),
                 type: :"#{translate_platform_authenticator_error(error).split('.').last}"
    else
      errors.add error, translate_error(error), type: :"#{translate_error(error).split('.').last}"
    end
  end

  def translate_platform_authenticator_error(error)
    case error
    when INVALID_STATE_ERROR
      I18n.t('errors.webauthn_platform_setup.already_registered')
    when NOT_SUPPORTED_ERROR
      I18n.t('errors.webauthn_platform_setup.not_supported')
    else
      webauthn_platform_general_error
    end
  end

  def translate_error(error)
    case error
    when INVALID_STATE_ERROR
      I18n.t('errors.webauthn_setup.already_registered')
    when NOT_SUPPORTED_ERROR
      I18n.t('errors.webauthn_setup.not_supported')
    else
      webauthn_general_error
    end
  end

  def webauthn_platform_general_error
    if current_mfa_setup_path == account_path
      I18n.t(
        'errors.webauthn_platform_setup.account_setup_error',
        link: I18n.t('errors.webauthn_platform_setup.choose_another_method'),
      )
    else
      I18n.t(
        'errors.webauthn_platform_setup.account_setup_error',
        link: link_to(
          I18n.t('errors.webauthn_platform_setup.choose_another_method'),
          current_mfa_setup_path,
        ),
      )
    end
  end

  def webauthn_general_error
    if current_mfa_setup_path == account_path
      I18n.t(
        'errors.webauthn_setup.general_error_html',
        link_html: I18n.t('errors.webauthn_setup.additional_methods_link'),
      )
    else
      I18n.t(
        'errors.webauthn_setup.general_error_html',
        link_html: link_to(
          I18n.t('errors.webauthn_setup.additional_methods_link'),
          current_mfa_setup_path,
        ),
      )
    end
  end

  def mfa_user
    @mfa_user ||= MfaContext.new(@user)
  end

  def extra_analytics_attributes
    {
      platform_authenticator: platform_authenticator?,
      enabled_mfa_methods_count: mfa_user.enabled_mfa_methods_count,
    }
  end
end