From e904b2faadc2449e1781e57706d65cf6c77c9627 Mon Sep 17 00:00:00 2001
From: Forest Carlisle <forestcarlisle@gmail.com>
Date: Thu, 13 Mar 2014 13:26:40 -0700
Subject: [PATCH] Adding name to the list of uneditable items in preferences UI

  * If enable_names,  enable_sso, and sso_overrides_name settings are true.
  * Added serialization of can_edit_name so the UI has access to the right.
---
 .../templates/user/preferences.js.handlebars  |   8 +-
 app/serializers/user_serializer.rb            |   5 +
 lib/guardian/user_guardian.rb                 |   9 +-
 spec/components/guardian_spec.rb              | 111 ++++++++++++++++++
 4 files changed, 130 insertions(+), 3 deletions(-)

diff --git a/app/assets/javascripts/discourse/templates/user/preferences.js.handlebars b/app/assets/javascripts/discourse/templates/user/preferences.js.handlebars
index 5eefb97e2a3..216ea07a705 100644
--- a/app/assets/javascripts/discourse/templates/user/preferences.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/user/preferences.js.handlebars
@@ -25,7 +25,11 @@
       <div class="control-group">
         <label class="control-label">{{i18n user.name.title}}</label>
         <div class="controls">
-          {{textField value=newNameInput classNames="input-xxlarge"}}
+          {{#if can_edit_name}}
+            {{textField value=newNameInput classNames="input-xxlarge"}}
+          {{else}}
+            <span class='static'>{{name}}</span>
+          {{/if}}
         </div>
         <div class='instructions'>
           {{i18n user.name.instructions}}
@@ -73,7 +77,7 @@
         {{/if}}
       </div>
     </div>
-    
+
     {{#if Discourse.SiteSettings.allow_profile_backgrounds}}
     <div class="control-group">
       <label class="control-label">{{i18n user.change_profile_background.title}}</label>
diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb
index 1d47e991685..cdd25726af6 100644
--- a/app/serializers/user_serializer.rb
+++ b/app/serializers/user_serializer.rb
@@ -12,6 +12,7 @@ class UserSerializer < BasicUserSerializer
              :can_edit,
              :can_edit_username,
              :can_edit_email,
+             :can_edit_name,
              :stats,
              :can_send_private_message_to_user,
              :bio_excerpt,
@@ -93,6 +94,10 @@ class UserSerializer < BasicUserSerializer
     scope.can_edit_email?(object)
   end
 
+  def can_edit_name
+    scope.can_edit_name?(object)
+  end
+
   def stats
     UserAction.stats(object.id, scope)
   end
diff --git a/lib/guardian/user_guardian.rb b/lib/guardian/user_guardian.rb
index 7f810faf82e..3e2bafd3be5 100644
--- a/lib/guardian/user_guardian.rb
+++ b/lib/guardian/user_guardian.rb
@@ -19,6 +19,13 @@ module UserGuardian
     can_edit?(user)
   end
 
+  def can_edit_name?(user)
+    return false if not(SiteSetting.enable_names?)
+    return false if (SiteSetting.sso_overrides_name? && SiteSetting.enable_sso?)
+    return true if is_staff?
+    can_edit?(user)
+  end
+
   def can_block_user?(user)
     user && is_staff? && not(user.staff?)
   end
@@ -37,4 +44,4 @@ module UserGuardian
     end
   end
 
-end
\ No newline at end of file
+end
diff --git a/spec/components/guardian_spec.rb b/spec/components/guardian_spec.rb
index 9ffe9626b23..39267f94730 100644
--- a/spec/components/guardian_spec.rb
+++ b/spec/components/guardian_spec.rb
@@ -1487,5 +1487,116 @@ describe Guardian do
       end
     end
   end
+
+  describe 'can_edit_name?' do
+    it 'is false without a logged in user' do
+      Guardian.new(nil).can_edit_name?(build(:user, created_at: 1.minute.ago)).should be_false
+    end
+
+    it "is false for regular users to edit another user's name" do
+      Guardian.new(build(:user)).can_edit_name?(build(:user, created_at: 1.minute.ago)).should be_false
+    end
+
+    context 'for a new user' do
+      let(:target_user) { build(:user, created_at: 1.minute.ago) }
+
+      it 'is true for the user to change their own name' do
+        Guardian.new(target_user).can_edit_name?(target_user).should be_true
+      end
+
+      it 'is true for moderators' do
+        Guardian.new(moderator).can_edit_name?(user).should be_true
+      end
+
+      it 'is true for admins' do
+        Guardian.new(admin).can_edit_name?(user).should be_true
+      end
+    end
+
+    context 'when name is disabled in preferences' do
+      before do
+        SiteSetting.stubs(:enable_names).returns(false)
+      end
+
+      it 'is false for the user to change their own name' do
+        Guardian.new(user).can_edit_name?(user).should be_false
+      end
+
+      it 'is false for moderators' do
+        Guardian.new(moderator).can_edit_name?(user).should be_false
+      end
+
+      it 'is false for admins' do
+        Guardian.new(admin).can_edit_name?(user).should be_false
+      end
+    end
+
+    context 'when name is enabled in preferences' do
+      before do
+        SiteSetting.stubs(:enable_names).returns(true)
+      end
+
+      context 'when SSO is disabled' do
+        before do
+          SiteSetting.stubs(:enable_sso).returns(false)
+          SiteSetting.stubs(:sso_overrides_name).returns(false)
+        end
+
+        it 'is true for admins' do
+          Guardian.new(admin).can_edit_name?(admin).should be_true
+        end
+
+        it 'is true for moderators' do
+          Guardian.new(moderator).can_edit_name?(moderator).should be_true
+        end
+
+        it 'is true for users' do
+          Guardian.new(user).can_edit_name?(user).should be_true
+        end
+      end
+
+      context 'when SSO is enabled' do
+        before do
+          SiteSetting.stubs(:enable_sso).returns(true)
+        end
+
+        context 'when SSO name override is active' do
+          before do
+            SiteSetting.stubs(:sso_overrides_name).returns(true)
+          end
+
+          it 'is false for admins' do
+            Guardian.new(admin).can_edit_name?(admin).should be_false
+          end
+
+          it 'is false for moderators' do
+            Guardian.new(moderator).can_edit_name?(moderator).should be_false
+          end
+
+          it 'is false for users' do
+            Guardian.new(user).can_edit_name?(user).should be_false
+          end
+        end
+
+        context 'when SSO name override is not active' do
+          before do
+            SiteSetting.stubs(:sso_overrides_name).returns(false)
+          end
+
+          it 'is true for admins' do
+            Guardian.new(admin).can_edit_name?(admin).should be_true
+          end
+
+          it 'is true for moderators' do
+            Guardian.new(moderator).can_edit_name?(moderator).should be_true
+          end
+
+          it 'is true for users' do
+            Guardian.new(user).can_edit_name?(user).should be_true
+          end
+        end
+      end
+    end
+  end
 end