attr_protected :login, :admin, :password, :password_confirmation, :hashed_password, :group_ids
validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
- validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }
+ validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }, :case_sensitive => false
validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }, :case_sensitive => false
# Login must contain lettres, numbers, underscores only
validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
def self.try_to_login(login, password)
# Make sure no one can sign in with an empty password
return nil if password.to_s.empty?
- user = find(:first, :conditions => ["login=?", login])
+ user = find_by_login(login)
if user
# user is already in local database
return nil if !user.active?
notified_projects_ids
end
+ # case-insensitive fall-over
+ def self.find_by_login(login)
+ # First look for an exact match
+ user = find(:first, :conditions => ["login = ?", login])
+ # Fail over to case-insensitive if none was found
+ user = find(:first, :conditions => ["LOWER(login) = ?", login.to_s.downcase]) if user.nil?
+ return user
+ end
+
def self.find_by_rss_key(key)
token = Token.find_by_value(key)
token && token.user.active? ? token.user : nil
assert user.save
end
+ context "User.login" do
+ should "be case-insensitive." do
+ u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
+ u.login = 'newuser'
+ u.password, u.password_confirmation = "password", "password"
+ assert u.save
+
+ u = User.new(:firstname => "Similar", :lastname => "User", :mail => "similaruser@somenet.foo")
+ u.login = 'NewUser'
+ u.password, u.password_confirmation = "password", "password"
+ assert !u.save
+ assert_equal I18n.translate('activerecord.errors.messages.taken'), u.errors.on(:login)
+ end
+ end
+
def test_mail_uniqueness_should_not_be_case_sensitive
u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
u.login = 'newuser1'
assert_equal 1, @admin.errors.count
end
+ context "User#try_to_login" do
+ should "fall-back to case-insensitive if user login is not found as-typed." do
+ user = User.try_to_login("AdMin", "admin")
+ assert_kind_of User, user
+ assert_equal "admin", user.login
+ end
+
+ should "select the exact matching user first" do
+ case_sensitive_user = User.generate_with_protected!(:login => 'changed', :password => 'admin', :password_confirmation => 'admin')
+ # bypass validations to make it appear like existing data
+ case_sensitive_user.update_attribute(:login, 'ADMIN')
+
+ user = User.try_to_login("ADMIN", "admin")
+ assert_kind_of User, user
+ assert_equal "ADMIN", user.login
+
+ end
+ end
+
def test_password
user = User.try_to_login("admin", "admin")
assert_kind_of User, user