require 'dm-types/bcrypt_hash' require 'dm-validations' module DataMapper module Is module Authenticatable # # Adds the `encrypted_password property` and mixs in {ClassMethods} # and {InstanceMethods}. # def is_authenticatable(options={}) # The encrypted password property :encrypted_password, DataMapper::Property::BCryptHash extend DataMapper::Is::Authenticatable::ClassMethods include DataMapper::Is::Authenticatable::InstanceMethods validates_confirmation_of :password end # # Class methods. # module ClassMethods # # Finds and authenticates a resource. # # @param [Hash] attributes # The attributes to search with. # # @option attributes [String] :password # The clear-text password to authenticate with. # # @return [DataMapper::Resource, nil] # The authenticated resource. If the resource could not be found, # or the password did not match, `nil` will be returned. # def authenticate(attributes) password = attributes.delete(:password) resource = self.first(attributes) if (resource && resource.has_password?(password)) return resource end end end # # Instance methods. # module InstanceMethods # The clear-text password attr_reader :password # The confirmed clear-text password attr_accessor :password_confirmation # # Updates the password of the resource. # # @param [String] new_password # The new password for the resource. # # @return [String] # The new password of the resource. # def password=(new_password) self.encrypted_password = new_password @password = new_password end # # Determines if a password is required for authentication. # # @return [Boolean] # Specifies whether a password is required or not. # # @since 0.2.0 # def password_required? !self.encrypted_password.nil? end # # Determines if the submitted password matches the `encrypted_password`. # # @param [String] submitted_password # The submitted password. # # @return [Boolean] # Specifies whether the submitted password matches. # # @since 0.2.0 # def has_password?(submitted_password) if password_required? self.encrypted_password == submitted_password else submitted_password.nil? || submitted_password.empty? end end end end end end