Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Reorganized ORM code and tests

  • Loading branch information...
commit 9bca67d7d9fe8d507685c35dbe3564ad3d4c6a9f 1 parent f606857
@binarylogic authored
View
6 CHANGELOG.rdoc
@@ -2,7 +2,11 @@
* Moved Rack standards into abstract_adapter for the controllers.
* Added logging_in_with_credentials?, logging_in_with_unauthorized_record?
-* Fixed typo in abstract_adapter, black to block
+* Fixed typo in abstract_adapter, black to block.
+* Cleaned up / reorganized tests.
+* Moved ActiveRecord additions to ORM Adapters name space to make way for Data Mapper.
+* Reorganized and modified acts_as_authentic to be free standing and not get info from the related session.
+* The session now gets its configuration from the model, since determining which fields are present is ORM specific.
== 1.0.0 released 2008-11-05
View
4 README.rdoc
@@ -4,7 +4,9 @@ Authlogic is a clean and simple ruby authentication solution. Put simply, its th
The last thing we need is another authentication solution, right? That's what I thought until I tried out some of the current solutions in both rails and merb. None of them felt right. They were either too complicated, bloated, littered my application with tons of code, or were just confusing. This is not the simple / elegant ruby we all fell in love with. We need a "ruby like" authentication solution. Authlogic is my attempt to satisfy that need...
-Let's take a rails application, wouldn't it be nice to keep your app up to date with the latest and greatest security techniques with a simple update of a plugin?
+Let's take a rails application...
+
+Wouldn't it be nice to keep your app up to date with the latest and greatest security techniques with a simple update of a plugin?
What if you could have authentication up and running in minutes without having to run a generator? All because it's simple, like everything else.
View
6 lib/authlogic.rb
@@ -9,7 +9,11 @@
require File.dirname(__FILE__) + "/authlogic/sha512_crypto_provider"
if defined?(ActiveRecord)
- require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/acts_as_authentic"
+ require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/acts_as_authentic"
+ require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/credentials"
+ require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/logged_in"
+ require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/persistence"
+ require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/session_maintenance"
require File.dirname(__FILE__) + "/authlogic/orm_adapters/active_record_adapter/authenticates_many"
end
View
215 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic.rb
@@ -71,225 +71,14 @@ module ActsAsAuthentic
# * <tt>logged_in_timeout:</tt> default: 10.minutes,
# This is really just a nifty feature to tell if a user is logged in or not. It's based on activity. So if the user in inactive longer than
# the value you pass here they are assumed "logged out".
- #
+ #
# * <tt>session_ids:</tt> default: [nil],
# The sessions that we want to automatically reset when a user is created or updated so you don't have to worry about this. Set to [] to disable.
# Should be an array of ids. See the Authlogic::Session documentation for information on ids. The order is important.
# The first id should be your main session, the session they need to log into first. This is generally nil. When you don't specify an id
# in your session you are really just inexplicitly saying you want to use the id of nil.
def acts_as_authentic(options = {})
- # If we don't have a database, skip all of this, solves initial setup errors
- begin
- column_names
- rescue Exception
- return
- end
-
- # Setup default options
- begin
- options[:session_class] ||= "#{name}Session".constantize
- rescue NameError
- raise NameError.new("You must create a #{name}Session class before a model can act_as_authentic. If that is not the name of the class pass the class constant via the :session_class option.")
- end
-
- options[:crypto_provider] ||= Sha512CryptoProvider
- options[:crypto_provider_type] ||= options[:crypto_provider].respond_to?(:decrypt) ? :encryption : :hash
- options[:login_field] ||= options[:session_class].login_field
- options[:login_field_type] ||= options[:login_field] == :email ? :email : :login
- options[:password_field] ||= options[:session_class].password_field
- options[:crypted_password_field] ||=
- (column_names.include?("crypted_password") && :crypted_password) ||
- (column_names.include?("encrypted_password") && :encrypted_password) ||
- (column_names.include?("password_hash") && :password_hash) ||
- (column_names.include?("pw_hash") && :pw_hash) ||
- :crypted_password
- options[:password_salt_field] ||=
- (column_names.include?("password_salt") && :password_salt) ||
- (column_names.include?("pw_salt") && :pw_salt) ||
- (column_names.include?("salt") && :salt) ||
- :password_salt
- options[:remember_token_field] ||= options[:session_class].remember_token_field
- options[:logged_in_timeout] ||= 10.minutes
- options[:session_ids] ||= [nil]
-
- # Validations
- case options[:login_field_type]
- when :email
- validates_length_of options[:login_field], :within => 6..100
- email_name_regex = '[\w\.%\+\-]+'
- domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
- domain_tld_regex = '(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)'
- options[:login_field_regex] ||= /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
- options[:login_field_regex_message] ||= "should look like an email address."
- validates_format_of options[:login_field], :with => options[:login_field_regex], :message => options[:login_field_regex_message]
- else
- validates_length_of options[:login_field], :within => 2..100
- options[:login_field_regex] ||= /\A\w[\w\.\-_@ ]+\z/
- options[:login_field_regex_message] ||= "use only letters, numbers, spaces, and .-_@ please."
- validates_format_of options[:login_field], :with => options[:login_field_regex], :message => options[:login_field_regex_message]
- end
-
- validates_uniqueness_of options[:login_field], :scope => options[:scope]
- validates_uniqueness_of options[:remember_token_field]
- validate :validate_password
- validates_numericality_of :login_count, :only_integer => :true, :greater_than_or_equal_to => 0, :allow_nil => true if column_names.include?("login_count")
-
- if column_names.include?("last_request_at")
- named_scope :logged_in, lambda { {:conditions => ["last_request_at > ?", options[:logged_in_timeout].ago]} }
- named_scope :logged_out, lambda { {:conditions => ["last_request_at is NULL or last_request_at <= ?", options[:logged_in_timeout].ago]} }
- end
-
- before_save :get_session_information, :if => :update_sessions?
- after_save :maintain_sessions!, :if => :update_sessions?
-
- # Attributes
- attr_writer "confirm_#{options[:password_field]}"
- attr_accessor "tried_to_set_#{options[:password_field]}"
-
- # Class methods
- class_eval <<-"end_eval", __FILE__, __LINE__
- def self.unique_token
- # Force using the Sha512 because all that we are doing is creating a unique token, a hash is perfect for this
- Authlogic::Sha512CryptoProvider.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)
- end
-
- def self.crypto_provider
- #{options[:crypto_provider]}
- end
-
- def self.forget_all!
- # Paginate these to save on memory
- records = nil
- i = 0
- begin
- records = find(:all, :limit => 50, :offset => i)
- records.each { |record| record.forget! }
- i += 50
- end while !records.blank?
- end
- end_eval
-
- # Instance methods
- if column_names.include?("last_request_at")
- class_eval <<-"end_eval", __FILE__, __LINE__
- def logged_in?
- !last_request_at.nil? && last_request_at > #{options[:logged_in_timeout].to_i}.seconds.ago
- end
- end_eval
- end
-
- class_eval <<-"end_eval", __FILE__, __LINE__
- def #{options[:password_field]}=(pass)
- return if pass.blank?
- self.tried_to_set_#{options[:password_field]} = true
- @#{options[:password_field]} = pass
- self.#{options[:remember_token_field]} = self.class.unique_token
- self.#{options[:password_salt_field]} = self.class.unique_token
- self.#{options[:crypted_password_field]} = 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]} ||
- (crypto_provider.respond_to?(:decrypt) && crypto_provider.decrypt(#{options[:crypted_password_field]}) == attempted_password + #{options[:password_salt_field]}) ||
- (!crypto_provider.respond_to?(:decrypt) && crypto_provider.encrypt(attempted_password + #{options[:password_salt_field]}) == #{options[:crypted_password_field]})
- end
- end_eval
-
- class_eval <<-"end_eval", __FILE__, __LINE__
- def #{options[:password_field]}; end
- def confirm_#{options[:password_field]}; end
-
- def crypto_provider
- self.class.crypto_provider
- end
-
- def forget!
- self.#{options[:remember_token_field]} = self.class.unique_token
- save_without_session_maintenance(false)
- end
-
- def reset_#{options[:password_field]}!
- chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
- newpass = ""
- 1.upto(10) { |i| newpass << chars[rand(chars.size-1)] }
- self.#{options[:password_field]} = newpass
- self.confirm_#{options[:password_field]} = newpass
- save_without_session_maintenance(false)
- end
- alias_method :randomize_password!, :reset_password!
-
- def save_without_session_maintenance(*args)
- @skip_session_maintenance = true
- result = save(*args)
- @skip_session_maintenance = false
- result
- end
-
- protected
- def update_sessions?
- !@skip_session_maintenance && #{options[:session_class]}.activated? && !#{options[:session_ids].inspect}.blank? && #{options[:remember_token_field]}_changed?
- end
-
- def get_session_information
- # Need to determine if we are completely logged out, or logged in as another user
- @_sessions = []
- @_logged_out = true
-
- #{options[:session_ids].inspect}.each do |session_id|
- session = #{options[:session_class]}.find(*[session_id].compact)
- if session
- if !session.record.blank?
- @_logged_out = false
- @_sessions << session if session.record == self
- end
- end
- end
- end
-
- def maintain_sessions!
- if @_logged_out
- create_session!
- elsif !@_sessions.blank?
- update_sessions!
- end
- end
-
- def create_session!
- # We only want to automatically login into the first session, since this is the main session. The other sessions are sessions
- # that need to be created after logging into the main session.
- session_id = #{options[:session_ids].inspect}.first
-
- # If we are already logged in, ignore this completely. All that we care about is updating ourself.
- next if #{options[:session_class]}.find(*[session_id].compact)
-
- # Log me in
- args = [self, session_id].compact
- #{options[:session_class]}.create(*args)
- end
-
- def update_sessions!
- # We found sessions above, let's update them with the new info
- @_sessions.each do |stale_session|
- stale_session.unauthorized_record = self
- stale_session.save
- end
- end
-
- 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]}, "can not be blank")
- else
- errors.add(:confirm_#{options[:password_field]}, "did not match") if @confirm_#{options[:password_field]} != @#{options[:password_field]}
- end
- end
- end
- end_eval
+ # All logic for this method is split up into sub modules. This a stub to create a method chain off of and provide documentation.
end
end
end
View
131 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/credentials.rb
@@ -0,0 +1,131 @@
+module Authlogic
+ module ORMAdapters
+ module ActiveRecordAdapter
+ module Credentials # :nodoc:
+ def acts_as_authentic_with_credentials(options = {})
+ acts_as_authentic_without_credentials(options)
+
+ class_eval <<-"end_eval", __FILE__, __LINE__
+ def self.login_field
+ @login_field ||= #{options[:login_field].inspect} ||
+ (column_names.include?("login") && :login) ||
+ (column_names.include?("username") && :username) ||
+ (column_names.include?("email") && :email) ||
+ :login
+ end
+
+ def self.password_field
+ @password_field ||= #{options[:password_field].inspect} ||
+ (column_names.include?("password") && :password) ||
+ (column_names.include?("pass") && :pass) ||
+ :password
+ end
+
+ def self.crypted_password_field
+ @crypted_password_field ||= #{options[:crypted_password_field].inspect} ||
+ (column_names.include?("crypted_password") && :crypted_password) ||
+ (column_names.include?("encrypted_password") && :encrypted_password) ||
+ (column_names.include?("password_hash") && :password_hash) ||
+ (column_names.include?("pw_hash") && :pw_hash) ||
+ :crypted_password
+ end
+
+ def self.password_salt_field
+ @password_salt_field ||= #{options[:password_salt_field].inspect} ||
+ (column_names.include?("password_salt") && :password_salt) ||
+ (column_names.include?("pw_salt") && :pw_salt) ||
+ (column_names.include?("salt") && :salt) ||
+ :password_salt
+ end
+ end_eval
+
+ options[:crypto_provider] ||= Sha512CryptoProvider
+ options[:login_field_type] ||= login_field == :email ? :email : :login
+
+ # Validations
+ case options[:login_field_type]
+ when :email
+ validates_length_of login_field, :within => 6..100
+ email_name_regex = '[\w\.%\+\-]+'
+ domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
+ domain_tld_regex = '(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)'
+ options[:login_field_regex] ||= /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
+ options[:login_field_regex_message] ||= "should look like an email address."
+ validates_format_of login_field, :with => options[:login_field_regex], :message => options[:login_field_regex_message]
+ else
+ validates_length_of login_field, :within => 2..100
+ options[:login_field_regex] ||= /\A\w[\w\.\-_@ ]+\z/
+ options[:login_field_regex_message] ||= "use only letters, numbers, spaces, and .-_@ please."
+ validates_format_of login_field, :with => options[:login_field_regex], :message => options[:login_field_regex_message]
+ end
+
+ validates_uniqueness_of login_field, :scope => options[:scope]
+ validate :validate_password
+
+ attr_writer "confirm_#{password_field}"
+ attr_accessor "tried_to_set_#{password_field}"
+
+ class_eval <<-"end_eval", __FILE__, __LINE__
+ def self.crypto_provider
+ #{options[:crypto_provider]}
+ end
+
+ def crypto_provider
+ self.class.crypto_provider
+ end
+
+ def #{password_field}=(pass)
+ return if pass.blank?
+ self.tried_to_set_#{password_field} = true
+ @#{password_field} = pass
+ self.#{password_salt_field} = self.class.unique_token
+ self.#{crypted_password_field} = crypto_provider.encrypt(@#{password_field} + #{password_salt_field})
+ end
+
+ def valid_#{password_field}?(attempted_password)
+ return false if attempted_password.blank? || #{crypted_password_field}.blank? || #{password_salt_field}.blank?
+ attempted_password == #{crypted_password_field} ||
+ (crypto_provider.respond_to?(:decrypt) && crypto_provider.decrypt(#{crypted_password_field}) == attempted_password + #{password_salt_field}) ||
+ (!crypto_provider.respond_to?(:decrypt) && crypto_provider.encrypt(attempted_password + #{password_salt_field}) == #{crypted_password_field})
+ end
+
+ def #{password_field}; end
+ def confirm_#{password_field}; end
+
+ def reset_#{password_field}!
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
+ newpass = ""
+ 1.upto(10) { |i| newpass << chars[rand(chars.size-1)] }
+ self.#{password_field} = newpass
+ self.confirm_#{password_field} = newpass
+ 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_#{password_field}?
+ if @#{password_field}.blank?
+ errors.add(:#{password_field}, "can not be blank")
+ else
+ errors.add(:confirm_#{password_field}, "did not match") if @confirm_#{password_field} != @#{password_field}
+ end
+ end
+ end
+ end_eval
+ end
+ end
+ end
+ end
+end
+
+ActiveRecord::Base.class_eval do
+ class << self
+ include Authlogic::ORMAdapters::ActiveRecordAdapter::Credentials
+ alias_method_chain :acts_as_authentic, :credentials
+ end
+end
View
41 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/logged_in.rb
@@ -0,0 +1,41 @@
+module Authlogic
+ module ORMAdapters
+ module ActiveRecordAdapter
+ module LoggedIn # :nodoc:
+ def acts_as_authentic_with_logged_in(options = {})
+ acts_as_authentic_without_logged_in(options)
+
+ options[:logged_in_timeout] ||= 10.minutes
+
+ validates_numericality_of :login_count, :only_integer => :true, :greater_than_or_equal_to => 0, :allow_nil => true if column_names.include?("login_count")
+
+ if column_names.include?("last_request_at")
+ named_scope :logged_in, lambda { {:conditions => ["last_request_at > ?", options[:logged_in_timeout].ago]} }
+ named_scope :logged_out, lambda { {:conditions => ["last_request_at is NULL or last_request_at <= ?", options[:logged_in_timeout].ago]} }
+ end
+
+ class_eval <<-"end_eval", __FILE__, __LINE__
+ def self.logged_in_timeout
+ #{options[:logged_in_timeout].to_i}.seconds
+ end
+ end_eval
+
+ if column_names.include?("last_request_at")
+ class_eval <<-"end_eval", __FILE__, __LINE__
+ def logged_in?
+ !last_request_at.nil? && last_request_at > self.class.logged_in_timeout.ago
+ end
+ end_eval
+ end
+ end
+ end
+ end
+ end
+end
+
+ActiveRecord::Base.class_eval do
+ class << self
+ include Authlogic::ORMAdapters::ActiveRecordAdapter::LoggedIn
+ alias_method_chain :acts_as_authentic, :logged_in
+ end
+end
View
60 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/persistence.rb
@@ -0,0 +1,60 @@
+module Authlogic
+ module ORMAdapters
+ module ActiveRecordAdapter
+ module Persistence # :nodoc:
+ def acts_as_authentic_with_persistence(options = {})
+ acts_as_authentic_without_persistence(options)
+
+ class_eval <<-"end_eval", __FILE__, __LINE__
+ def self.remember_token_field
+ @remember_token_field ||= #{options[:remember_token_field].inspect} ||
+ (column_names.include?("remember_token") && :remember_token) ||
+ (column_names.include?("remember_key") && :remember_key) ||
+ (column_names.include?("cookie_token") && :cookie_token) ||
+ (column_names.include?("cookie_key") && :cookie_key) ||
+ :remember_token
+ end
+ end_eval
+
+ validates_uniqueness_of remember_token_field
+
+ def unique_token
+ # Force using the Sha512 because all that we are doing is creating a unique token, a hash is perfect for this
+ Authlogic::Sha512CryptoProvider.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)
+ end
+
+ def forget_all!
+ # Paginate these to save on memory
+ records = nil
+ i = 0
+ begin
+ records = find(:all, :limit => 50, :offset => i)
+ records.each { |record| record.forget! }
+ i += 50
+ end while !records.blank?
+ end
+
+ class_eval <<-"end_eval", __FILE__, __LINE__
+ def forget!
+ self.#{remember_token_field} = self.class.unique_token
+ save_without_session_maintenance(false)
+ end
+
+ def password_with_persistence=(value)
+ self.#{remember_token_field} = self.class.unique_token
+ self.password_without_persistence = value
+ end
+ alias_method_chain :password=, :persistence
+ end_eval
+ end
+ end
+ end
+ end
+end
+
+ActiveRecord::Base.class_eval do
+ class << self
+ include Authlogic::ORMAdapters::ActiveRecordAdapter::Persistence
+ alias_method_chain :acts_as_authentic, :persistence
+ end
+end
View
83 lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/session_maintenance.rb
@@ -0,0 +1,83 @@
+module Authlogic
+ module ORMAdapters
+ module ActiveRecordAdapter
+ module SessionMaintenance # :nodoc:
+ def acts_as_authentic_with_session_maintenance(options = {})
+ acts_as_authentic_without_session_maintenance(options)
+
+ options[:session_class] ||= "#{name}Session"
+ options[:session_ids] ||= [nil]
+
+ before_save :get_session_information, :if => :update_sessions?
+ after_save :maintain_sessions!, :if => :update_sessions?
+
+ class_eval <<-"end_eval", __FILE__, __LINE__
+ def save_without_session_maintenance(*args)
+ @skip_session_maintenance = true
+ result = save(*args)
+ @skip_session_maintenance = false
+ result
+ end
+
+ protected
+ def update_sessions?
+ !@skip_session_maintenance && #{options[:session_class]}.activated? && !#{options[:session_ids].inspect}.blank? && #{remember_token_field}_changed?
+ end
+
+ def get_session_information
+ # Need to determine if we are completely logged out, or logged in as another user
+ @_sessions = []
+ @_logged_out = true
+
+ #{options[:session_ids].inspect}.each do |session_id|
+ session = #{options[:session_class]}.find(*[session_id].compact)
+ if session
+ if !session.record.blank?
+ @_logged_out = false
+ @_sessions << session if session.record == self
+ end
+ end
+ end
+ end
+
+ def maintain_sessions!
+ if @_logged_out
+ create_session!
+ elsif !@_sessions.blank?
+ update_sessions!
+ end
+ end
+
+ def create_session!
+ # We only want to automatically login into the first session, since this is the main session. The other sessions are sessions
+ # that need to be created after logging into the main session.
+ session_id = #{options[:session_ids].inspect}.first
+
+ # If we are already logged in, ignore this completely. All that we care about is updating ourself.
+ next if #{options[:session_class]}.find(*[session_id].compact)
+
+ # Log me in
+ args = [self, session_id].compact
+ #{options[:session_class]}.create(*args)
+ end
+
+ def update_sessions!
+ # We found sessions above, let's update them with the new info
+ @_sessions.each do |stale_session|
+ stale_session.unauthorized_record = self
+ stale_session.save
+ end
+ end
+ end_eval
+ end
+ end
+ end
+ end
+end
+
+ActiveRecord::Base.class_eval do
+ class << self
+ include Authlogic::ORMAdapters::ActiveRecordAdapter::SessionMaintenance
+ alias_method_chain :acts_as_authentic, :session_maintenance
+ end
+end
View
35 lib/authlogic/session/config.rb
@@ -6,9 +6,11 @@ def self.included(klass)
klass.send(:include, InstanceMethods)
end
- # = Config
+ # = Session Config
#
- # Configuration is simple. The configuration options are just class methods. Just put this in your config/initializers directory
+ # This deals with configuration for your session. If you are wanting to configure your model please look at Authlogic::ORMAdapters::ActiveRecord::ActsAsAuthentic
+ #
+ # Configuration for your session is simple. The configuration options are just class methods. Just put this in your config/initializers directory
#
# UserSession.configure do |config|
# config.authenticate_with = User
@@ -46,6 +48,9 @@ def configure
# The name of the cookie or the key in the cookies hash. Be sure and use a unique name. If you have multiple sessions and they use the same cookie it will cause problems.
# Also, if a id is set it will be inserted into the beginning of the string. Exmaple:
#
+ # session = UserSession.new
+ # session.cookie_key => "user_credentials"
+ #
# session = UserSession.new(:super_high_secret)
# session.cookie_key => "super_high_secret_user_credentials"
#
@@ -60,12 +65,17 @@ def cookie_key(value = nil)
end
alias_method :cookie_key=, :cookie_key
- # The name of the method used to find the record by the login. What's nifty about this is that you can do anything in your method, Authlogic will just pass you the login.
+ # Authlogic tries to validate the credentials passed to it. One part of validation is actually finding the user and making sure it exists. What method it uses the do this is up to you.
+ #
+ # Let's say you have a UserSession that is authenticating a User. By default UserSession will call User.find_by_login(login). You can change what method UserSession calls by specifying it here. Then
+ # in your User model you can make that method do anything you want, giving you complete control of how users are found by the UserSession.
#
- # Let's say you allow users to login by username or email. Set this to "find_login", or whatever method you want. Then in your model create a class method like:
+ # Let's take an example: You want to allow users to login by username or email. Set this to the name of the class method that does this in the User model. Let's call it "find_by_username_or_email"
#
- # def self.find_login(login)
- # find_by_login(login) || find_by_email(login)
+ # class User < ActiveRecord::Base
+ # def self.find_by_username_or_email(login)
+ # find_by_username(login) || find_by_email(login)
+ # end
# end
#
# * <tt>Default:</tt> "find_by_#{login_field}"
@@ -101,7 +111,7 @@ def find_with(*values)
# * <tt>Accepts:</tt> Symbol or String
def login_field(value = nil)
if value.nil?
- read_inheritable_attribute(:login_field) || login_field((klass.column_names.include?("login") && :login) || (klass.column_names.include?("username") && :username) || (klass.column_names.include?("email") && :email) || :login)
+ read_inheritable_attribute(:login_field) || login_field(klass.login_field)
else
write_inheritable_attribute(:login_field, value)
end
@@ -114,7 +124,7 @@ def login_field(value = nil)
# * <tt>Accepts:</tt> Symbol or String
def password_field(value = nil)
if value.nil?
- read_inheritable_attribute(:password_field) || password_field((klass.column_names.include?("password") && :password) || (klass.column_names.include?("pass") && :pass) || :password)
+ read_inheritable_attribute(:password_field) || password_field(klass.password_field)
else
write_inheritable_attribute(:password_field, value)
end
@@ -155,14 +165,7 @@ def remember_me_for(value = :_read)
# * <tt>Accepts:</tt> Symbol or String
def remember_token_field(value = nil)
if value.nil?
- read_inheritable_attribute(:remember_token_field) ||
- remember_token_field(
- (klass.column_names.include?("remember_token") && :remember_token) ||
- (klass.column_names.include?("remember_key") && :remember_key) ||
- (klass.column_names.include?("cookie_token") && :cookie_token) ||
- (klass.column_names.include?("cookie_key") && :cookie_key) ||
- :remember_token
- )
+ read_inheritable_attribute(:remember_token_field) || remember_token_field(klass.remember_token_field)
else
write_inheritable_attribute(:remember_token_field, value)
end
Please sign in to comment.
Something went wrong with that request. Please try again.