42 lines
861 B
Ruby
42 lines
861 B
Ruby
class MagicLink < ApplicationRecord
|
|
CODE_LENGTH = 6
|
|
EXPIRATION_TIME = 15.minutes
|
|
|
|
belongs_to :identity
|
|
|
|
scope :active, -> { where(expires_at: Time.current...) }
|
|
scope :stale, -> { where(expires_at: ..Time.current) }
|
|
|
|
before_validation :generate_code, on: :create
|
|
before_validation :set_expiration, on: :create
|
|
|
|
validates :code, uniqueness: true, presence: true
|
|
|
|
class << self
|
|
def consume(code)
|
|
active.find_by(code: Code.sanitize(code))&.consume
|
|
end
|
|
|
|
def cleanup
|
|
stale.delete_all
|
|
end
|
|
end
|
|
|
|
def consume
|
|
destroy
|
|
identity
|
|
end
|
|
|
|
private
|
|
def generate_code
|
|
self.code ||= loop do
|
|
candidate = Code.generate(CODE_LENGTH)
|
|
break candidate unless self.class.exists?(code: candidate)
|
|
end
|
|
end
|
|
|
|
def set_expiration
|
|
self.expires_at ||= EXPIRATION_TIME.from_now
|
|
end
|
|
end
|