module Authlogic module ORMAdapters module ActiveRecordAdapter module ActsAsAuthentic # = Credentials # # Handles any credential specific code, such as validating the login, encrpyting the password, etc. # # === Class Methods # # * friendly_unique_token - returns a random string of 20 alphanumeric characters. Used when resetting the password. This is a more user friendly token then a long Sha512 hash. # # === Instance Methods # # * {options[:password_field]}=(value) - encrypts a raw password and sets it to your crypted_password_field. Also sets the password_salt to a random token. # * valid_{options[:password_field]}?(password_to_check) - checks is the password is valid. The password passed can be the raw password or the encrypted password. # * reset_{options[:password_field]} - resets the password using the friendly_unique_token class method # * reset_{options[:password_field]}! - calls reset_password and then saves the record module Credentials def acts_as_authentic_with_credentials(options = {}) acts_as_authentic_without_credentials(options) # Validations case options[:login_field_type] when :email validates_length_of options[:login_field], :within => 6..100 validates_format_of options[:login_field], :with => options[:login_field_regex], :message => options[:login_field_regex_failed_message] else validates_length_of options[:login_field], :within => 2..100, :allow_blank => true validates_format_of options[:login_field], :with => options[:login_field_regex], :message => options[:login_field_regex_failed_message] end validates_uniqueness_of options[:login_field], :scope => options[:scope] validate :validate_password attr_writer "confirm_#{options[:password_field]}" attr_accessor "tried_to_set_#{options[:password_field]}" class_eval <<-"end_eval", __FILE__, __LINE__ def self.friendly_unique_token chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a newpass = "" 1.upto(20) { |i| newpass << chars[rand(chars.size-1)] } newpass end def #{options[:password_field]}=(pass) return if pass.blank? self.tried_to_set_#{options[:password_field]} = true @#{options[:password_field]} = pass self.#{options[:password_salt_field]} = self.class.unique_token self.#{options[:crypted_password_field]} = #{options[:crypto_provider]}.encrypt(@#{options[:password_field]} + #{options[:password_salt_field]}) end def valid_#{options[:password_field]}?(attempted_password) return false if attempted_password.blank? || #{options[:crypted_password_field]}.blank? || #{options[:password_salt_field]}.blank? attempted_password == #{options[:crypted_password_field]} || (#{options[:crypto_provider]}.respond_to?(:decrypt) && #{options[:crypto_provider]}.decrypt(#{options[:crypted_password_field]}) == attempted_password + #{options[:password_salt_field]}) || (!#{options[:crypto_provider]}.respond_to?(:decrypt) && #{options[:crypto_provider]}.encrypt(attempted_password + #{options[:password_salt_field]}) == #{options[:crypted_password_field]}) end def #{options[:password_field]}; end def confirm_#{options[:password_field]}; end def reset_#{options[:password_field]} friendly_token = self.class.friendly_unique_token self.#{options[:password_field]} = friendly_token self.confirm_#{options[:password_field]} = friendly_token end alias_method :randomize_password, :reset_password def reset_#{options[:password_field]}! reset_#{options[:password_field]} save_without_session_maintenance(false) end alias_method :randomize_password!, :reset_password! protected def tried_to_set_password? tried_to_set_password == true end def validate_password if new_record? || tried_to_set_#{options[:password_field]}? if @#{options[:password_field]}.blank? errors.add(:#{options[:password_field]}, #{options[:password_blank_message].inspect}) else errors.add(:confirm_#{options[:password_field]}, #{options[:confirm_password_did_not_match_message].inspect}) if @confirm_#{options[:password_field]} != @#{options[:password_field]} end end end end_eval end end end end end end ActiveRecord::Base.class_eval do class << self include Authlogic::ORMAdapters::ActiveRecordAdapter::ActsAsAuthentic::Credentials alias_method_chain :acts_as_authentic, :credentials end end