module Entrance module Model def self.included(base) base.extend(ClassMethods) end module ClassMethods def provides_entrance(&block) Entrance.config.model = self.name # if the target model class does not have a Model.where() method, # then login_by_session wont work, nor the ClassMethods below. # won't work so we cannot continue. unless self.respond_to?(:where) raise "#{self.name} does not have a .where() finder class method. Cannot continue." end fields = Entrance.fields yield fields if block_given? fields.validate! if self.respond_to?(:validates) validates :password, :presence => true, :length => 6..32, :if => :password_required? validates :password, :confirmation => true, :if => :password_required? validates :password_confirmation, :presence => true, :if => :password_required? end end def authenticate(username, password) return if [username, password].any? { |v| v.nil? || v.strip == '' } query = {} query[Entrance.fields.username] = username.to_s.downcase.strip if u = where(query).first return u.authenticated?(password) ? u : nil end end def with_password_reset_token(token) Entrance.config.permit!(:reset) return if token.nil? query = {} query[Entrance.fields.reset_token] = token.to_s.strip if u = where(query).first \ and (!Entrance.fields.reset_until || u.send(Entrance.fields.reset_until) > Time.now) return u end end end module ResetMethods def request_password_reset! send(Entrance.fields.reset_token + '=', Entrance.generate_token) if Entrance.fields.reset_until timestamp = Time.now + Entrance.config.reset_password_window update_attribute(Entrance.fields.reset_until, timestamp) end if save(:validate => false) method = Entrance.config.reset_password_method Entrance.config.reset_password_mailer.constantize.send(method, self).deliver end end end module RememberMethods def remember_me!(until_date = nil) token = Entrance.generate_token update_attribute(Entrance.fields.remember_token, token) or return update_remember_token_expiration!(until_date) if Entrance.fields.remember_until token end def update_remember_token_expiration!(until_date = nil) timestamp = Time.now + (until_date || Entrance.config.remember_for).to_i update_attribute(Entrance.fields.remember_until, timestamp) end def forget_me! update_attribute(Entrance.fields.remember_token, nil) update_attribute(Entrance.fields.remember_until, nil) if Entrance.fields.remember_until end end def authenticated?(string) Entrance.config.cipher.match?(read_password, string, get_salt) end def password @password || read_password end def password=(new_password) return if new_password.nil? @password = new_password # for validation @password_changed = true # if we're using salt and it is empty, generate one if Entrance.fields.salt \ and send(Entrance.fields.salt).nil? self.send(Entrance.fields.salt + '=', Entrance.generate_token) end self.send(Entrance.fields.password + '=', encrypt_password(new_password)) end private def read_password send(Entrance.fields.password) end def encrypt_password(string) Entrance.config.cipher.encrypt(string, get_salt) end def get_salt Entrance.fields.salt && send(Entrance.fields.salt) end def password_required? password.nil? || @password_changed end end end