lib/tiny_auth/model.rb in tiny_auth-2.0.0 vs lib/tiny_auth/model.rb in tiny_auth-3.0.0.rc1
- old
+ new
@@ -1,22 +1,22 @@
require "active_record"
-require "globalid"
require "active_support/core_ext/numeric/time"
-require "active_support/core_ext/securerandom"
module TinyAuth
module Model
def self.included(base)
base.extend ClassMethods
+ base.has_secure_password
+ base.before_save :invalidate_tokens, if: :password_digest_changed?
end
module ClassMethods
# Find a resource by email, ignoring case
# @param email [String]
# @return [ActiveRecord::Base,nil]
def find_by_email(email)
- find_by arel_table[:email].lower.eq(email.downcase)
+ find_by(arel_table[:email].lower.eq(email.downcase))
end
# Find a resource by their email address and password
# This assumes that you've added `has_secure_password` to your model.
# @param email [String]
@@ -27,49 +27,40 @@
resource if resource&.authenticate(password)
end
# Finds a resource by a token
# @param token [String]
+ # @param purpose [Symbol] defaults to `:access`
# @return [ActiveRecord::Base,nil]
- def find_by_token(token)
- resource = GlobalID::Locator.locate_signed(token, for: :access)
- resource if resource.kind_of?(self)
- rescue ActiveRecord::RecordNotFound
+ def find_by_token(token, purpose: :access)
+ id, token_version = TinyAuth.verifier.verify(token, purpose: purpose)
+ find_by(id: id, token_version: token_version)
+ rescue ActiveSupport::MessageVerifier::InvalidSignature
end
-
- # Finds a resource by their reset token and nillifies `reset_password_digest`
- # and `reset_token_expires_at` fields
- # @param token [String]
- # @return [ActiveRecord::Base,nil]
- def exchange_reset_token(token)
- digest = TinyAuth.hexdigest(token)
- not_expired = arel_table[:reset_token_expires_at].gt(Time.now)
- resource = where(not_expired).find_by(reset_token_digest: digest)
- resource&.reset_token_digest = nil
- resource&.reset_token_expires_at = nil
- resource
- end
end
- # Generates a stateless token for a resource
+ # Generates a token for this resource.
# @param expires_in [ActiveSupport::Duration] defaults to 24 hours
- def generate_token(expires_in: 24.hours)
- to_signed_global_id(expires_in: expires_in, for: :access).to_s
+ # @param purpose [Symbol] defaults to `:access`
+ # @return [String]
+ def generate_token(purpose: :access, expires_in: 24.hours)
+ TinyAuth.verifier.generate(
+ [id, token_version],
+ purpose: purpose,
+ expires_in: expires_in
+ )
end
- # Generates a reset token for a resource. A hashed version of the token
- # is stored in the database
- # @param expires_in [ActiveSupport::Duration] defaults to 2 hours
- def generate_reset_token(expires_in: 2.hours)
- token = SecureRandom.base58(24)
- digest = TinyAuth.hexdigest(token)
- expiry = expires_in.from_now
+ # Invalidate all tokens for this resource. The token version will
+ # be incremented and written to the database.
+ # @return [self]
+ def invalidate_tokens!
+ increment!(:token_version)
+ end
- update_columns(
- reset_token_digest: digest,
- reset_token_expires_at: expiry
- )
-
- token
+ # Invalidate all tokens for this resource. The token version will
+ # be incremented, but it will not be written to the database.
+ def invalidate_tokens
+ increment(:token_version)
end
end
end