Sha256: 6528bf9b2dfc09bd6afde6af966b598fa9cc0f37039583e25af3e007f55c9dd7

Contents?: true

Size: 1.78 KB

Versions: 1

Compression:

Stored size: 1.78 KB

Contents

# frozen_string_literal: true

module Aikotoba
  class Account::Service::Authentication
    def self.call!(email:, password:)
      new(email: email, password: password).call!
    end

    def initialize(email:, password:,
      account_class: Account,
      lock_service: Account::Service::Lock,
      lockable: Account.lockable?,
      prevent_timing_atack: Aikotoba.prevent_timing_atack)
      @account_class = account_class
      @lock_service = lock_service
      @lockable = lockable
      @email = email
      @password = password
      @aikotoba_prevent_timing_atack = prevent_timing_atack
    end

    def call!
      account = find_by_identifier
      return prevent_timing_atack && nil unless account

      authenticate(account).tap do |result|
        ActiveRecord::Base.transaction do
          result ? success_callback(account) : failed_callback(account)
        end
      end
    end

    private

    # NOTE: Verify passwords even when accounts are not found to prevent timing attacks.
    def prevent_timing_atack
      return true unless @aikotoba_prevent_timing_atack
      account = @account_class.build_by(attributes: {email: @email, password: @password})
      account.password_match?(@password)
      true
    end

    def success_callback(account)
      account.authentication_success!
    end

    def failed_callback(account)
      account.authentication_failed!
      lock_when_should_lock!(account) if @lockable
    end

    def find_by_identifier
      @account_class.authenticatable.find_by(email: @email)
    end

    def authenticate(account)
      account.password_match?(@password) ? account : nil
    end

    concerning :Lockable do
      def lock_when_should_lock!(account)
        @lock_service.lock!(account: account, notify: true) if account.should_lock?
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
aikotoba-0.1.1 app/models/aikotoba/account/service/authentication.rb