diff --git a/lib/devise.rb b/lib/devise.rb index 74a906f5..8e48e15c 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -59,17 +59,17 @@ module Devise mattr_accessor :stretches @@stretches = 10 - # Keys used when authenticating an user. + # Keys used when authenticating a user. mattr_accessor :authentication_keys @@authentication_keys = [ :email ] - # Request keys used when authenticating an user. + # Request keys used when authenticating a user. mattr_accessor :request_keys @@request_keys = [] - # If authentication keys should be case-insensitive by default. + # Keys that should be case-insensitive. mattr_accessor :case_insensitive_keys - @@case_insensitive_keys = false + @@case_insensitive_keys = [ :email ] # If http authentication is enabled by default. mattr_accessor :http_authenticatable diff --git a/lib/devise/models/authenticatable.rb b/lib/devise/models/authenticatable.rb index 52769f8f..84310e44 100644 --- a/lib/devise/models/authenticatable.rb +++ b/lib/devise/models/authenticatable.rb @@ -100,9 +100,7 @@ module Devise # end # def find_for_authentication(conditions) - if case_insensitive_keys - authentication_keys.each { |k| conditions[k].try(:downcase!) } - end + case_insensitive_keys.each { |k| attributes[k].try(:downcase!) } to_adapter.find_first(conditions) end @@ -113,9 +111,7 @@ module Devise # Find an initialize a group of attributes based on a list of required attributes. def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc: - if case_insensitive_keys - authentication_keys.each { |k| attributes[k].try(:downcase!) } - end + case_insensitive_keys.each { |k| attributes[k].try(:downcase!) } attributes = attributes.slice(*required_attributes) attributes.delete_if { |key, value| value.blank? } diff --git a/lib/devise/models/database_authenticatable.rb b/lib/devise/models/database_authenticatable.rb index 372cd00c..8fa4d06a 100644 --- a/lib/devise/models/database_authenticatable.rb +++ b/lib/devise/models/database_authenticatable.rb @@ -22,6 +22,7 @@ module Devise included do attr_reader :password, :current_password attr_accessor :password_confirmation + before_save :downcase_keys end # Generates password encryption based on the given value. @@ -73,13 +74,18 @@ module Devise protected + # Downcase case-insensitive keys + def downcase_keys + self.class.case_insensitive_keys.each { |k| self[k].try(:downcase!) } + end + # Digests the password using bcrypt. def password_digest(password) ::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s end module ClassMethods - Devise::Models.config(self, :pepper, :stretches) + Devise::Models.config(self, :pepper, :stretches, :case_insensitive_keys) # We assume this method already gets the sanitized values from the # DatabaseAuthenticatable strategy. If you are using this method on diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb index 5e0d7443..8ed9afc8 100644 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -15,24 +15,26 @@ Devise.setup do |config| require 'devise/orm/<%= options[:orm] %>' # ==> Configuration for any authentication mechanism - # Configure which keys are used when authenticating an user. By default is + # Configure which keys are used when authenticating a user. The default is # just :email. You can configure it to use [:username, :subdomain], so for - # authenticating an user, both parameters are required. Remember that those + # authenticating a user, both parameters are required. Remember that those # parameters are used only when authenticating and not when retrieving from # session. If you need permissions, you should implement that in a before filter. - # You can also supply hash where the value is a boolean expliciting if authentication - # should be aborted or not if the value is not present. By default is empty. + # You can also supply a hash where the value is a boolean determining whether + # or not authentication should be aborted when the value is not present. # config.authentication_keys = [ :email ] # Configure parameters from the request object used for authentication. Each entry - # given should be a request method and it will automatically be passed to + # given should be a request method and it will automatically be passed to the # find_for_authentication method and considered in your model lookup. For instance, # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. # The same considerations mentioned for authentication_keys also apply to request_keys. # config.request_keys = [] - # If authentication keys should be case-insensitive. False by default. - # config.case_insensitive_keys = false + # Configure which authentication keys should be case-insensitive. + # These keys will be downcased upon creating or modifying a user and when used + # to authenticate or find a user. Default is :email. + # config.case_insensitive_keys = [ :email ] # Tell if authentication through request.params is enabled. True by default. # config.params_authenticatable = true