From 50f9e8f24023a9f2a117e20c46cd985051fb23f5 Mon Sep 17 00:00:00 2001
From: Sarah Mei <sarahmei@gmail.com>
Date: Sat, 16 Oct 2010 23:58:01 -0700
Subject: [PATCH] Reorganize User model. Preserve case of username.

---
 app/models/user.rb       | 30 ++++++++++++++----------------
 spec/models/user_spec.rb | 27 +++++++++++++++++----------
 2 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index 8bf6763848..7d29fd7dfa 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -17,17 +17,18 @@ end
 
 class User
   include MongoMapper::Document
-  plugin MongoMapper::Devise
   include Diaspora::UserModules
   include Encryptor::Private
+
+  plugin MongoMapper::Devise
+
   QUEUE = MessageHandler.new
 
   devise :invitable, :database_authenticatable, :registerable,
          :recoverable, :rememberable, :trackable, :validatable
 
-  key :username, :unique => true
+  key :username
   key :serialized_private_key, String
-
   key :invites, Integer, :default => 5
   key :invitation_token, String
   key :invitation_sent_at, DateTime
@@ -37,9 +38,13 @@ class User
   key :visible_post_ids, Array
   key :visible_person_ids, Array
 
+  before_validation :strip_username, :on => :create
   validates_presence_of :username
+  validates_uniqueness_of :username, :case_sensitive => false
   validates_format_of :username, :without => /\s/
 
+  validates_with InvitedUserValidator
+
   one :person, :class_name => 'Person', :foreign_key => :owner_id
 
   many :inviters, :in => :inviter_ids, :class_name => 'User'
@@ -47,21 +52,21 @@ class User
   many :visible_people, :in => :visible_person_ids, :class_name => 'Person' # One of these needs to go
   many :pending_requests, :in => :pending_request_ids, :class_name => 'Request'
   many :raw_visible_posts, :in => :visible_post_ids, :class_name => 'Post'
-
   many :aspects, :class_name => 'Aspect'
 
   after_create :seed_aspects
 
-  before_validation :strip_and_downcase_username, :on => :create
-  validates_with InvitedUserValidator
-
   before_destroy :unfriend_everyone, :remove_person
 
+  def strip_username
+    if username.present?
+      username.strip!
+    end
+  end
+
   def self.find_for_authentication(conditions={})
     if conditions[:username] =~ /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i # email regex
       conditions[:email] = conditions.delete(:username)
-    else
-      conditions[:username].downcase!
     end
     super
   end
@@ -360,13 +365,6 @@ class User
     "#{self.username}@#{APP_CONFIG[:terse_pod_url]}"
   end
 
-  def strip_and_downcase_username
-    if username.present?
-      username.strip!
-      username.downcase!
-    end
-  end
-
   def as_json(opts={})
     {
       :user => {
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index be5986a756..5296fbeaf4 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -13,7 +13,6 @@ describe User do
   let(:aspect3) { user3.aspect(:name => 'stuff') }
 
   describe "validation" do
-
     describe "of passwords" do
       it "fails if password doesn't match confirmation" do
         user = Factory.build(:user, :password => "password", :password_confirmation => "nope")
@@ -27,24 +26,25 @@ describe User do
     end
 
     describe "of username" do
-      it "requires a username" do
+      it "requires presence" do
         user = Factory.build(:user, :username => nil)
         user.should_not be_valid
       end
 
-      it "requires a unique username" do
+      it "requires uniqueness" do
         duplicate_user = Factory.build(:user, :username => user.username)
         duplicate_user.should_not be_valid
       end
 
-      it "downcases the username" do
-        user = Factory.build(:user, :username => "ALLUPPERCASE")
-        user.valid?
-        user.username.should == "alluppercase"
+      it "keeps the original case" do
+        user = Factory.build(:user, :username => "WeIrDcAsE")
+        user.should be_valid
+        user.username.should == "WeIrDcAsE"
+      end
 
-        user = Factory.build(:user, :username => "someUPPERCASE")
-        user.valid?
-        user.username.should == "someuppercase"
+      it "fails if the requested username is only different in case from an existing username" do
+        duplicate_user = Factory.build(:user, :username => user.username.upcase)
+        duplicate_user.should_not be_valid
       end
 
       it "strips leading and trailing whitespace" do
@@ -72,6 +72,13 @@ describe User do
     end
   end
 
+  describe ".find_for_authentication" do
+    it "preserves case" do
+      User.find_for_authentication(:username => user.username).should == user
+      User.find_for_authentication(:username => user.username.upcase).should be_nil
+    end
+  end
+
   describe '#diaspora_handle' do
     it 'uses the pod config url to set the diaspora_handle' do
       user.diaspora_handle.should == user.username + "@" + APP_CONFIG[:terse_pod_url]
-- 
GitLab