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