module OTP::ActiveRecord

ActiveRecord

concern.

Constants

OTP_DIGITS

Length of the generated OTP, defaults to 4.

Public Instance Methods

deliver_otp() click to toggle source

Helper to deliver the OTP

Will use the SMS job if the phone number is available. Will default to the email delivery.

@return [ActiveJob::Base] instance of the job

# File lib/otp/active_record.rb, line 70
def deliver_otp
  return unless persisted?
  sms_otp || email_otp || raise(NotImplementedError, self)
end
email_otp() click to toggle source

Helper to email the OTP using a job

Does nothing. Implement your own handler.

@return [OTP::API::Mailer] instance of the job

# File lib/otp/active_record.rb, line 61
def email_otp
end
otp() click to toggle source

Generates the OTP

@return [String] or nil if no OTP is set

# File lib/otp/active_record.rb, line 21
def otp
  return nil if !valid? || !persisted? || otp_secret.blank?

  otp_digits = self.class.const_get(:OTP_DIGITS)
  hotp = ROTP::HOTP.new(otp_secret, digits: otp_digits)

  transaction do
    increment!(:otp_counter)
    hotp.at(otp_counter)
  end
end
sms_otp() click to toggle source

Helper to send the OTP using the SMS job

Does nothing. Implement your own handler.

@return [OTP::API::SMSOTPJob] instance of the job

# File lib/otp/active_record.rb, line 53
def sms_otp
end
verify_otp(otp) click to toggle source

Verifies the OTP

@return true on success, false on failure

# File lib/otp/active_record.rb, line 36
def verify_otp(otp)
  return nil if !valid? || !persisted? || otp_secret.blank?

  otp_digits = self.class.const_get(:OTP_DIGITS)
  hotp = ROTP::HOTP.new(otp_secret, digits: otp_digits)
  transaction do
    otp_status = hotp.verify(otp.to_s, otp_counter)
    increment!(:otp_counter)
    otp_status
  end
end

Private Instance Methods

setup_otp() click to toggle source

Provides a default value for the OTP secret attribute

@return [String]

# File lib/otp/active_record.rb, line 79
def setup_otp
  self.otp_secret ||= ROTP::Base32.random_base32
  self.otp_counter ||= 0
end