From 80bec6efc9cbed8a9f901d1e9bc46fb0a0922144 Mon Sep 17 00:00:00 2001 From: Ismael Abreu Date: Tue, 12 Feb 2013 22:58:08 +0000 Subject: [PATCH] Adds grant and revoke moderation buttons so admins can make users moderators --- .../admin/models/admin_user.js.coffee | 13 ++++++ .../admin/templates/user.js.handlebars | 15 +++++++ app/controllers/admin/users_controller.rb | 16 +++++++ app/models/user.rb | 5 +++ .../admin_detailed_user_serializer.rb | 12 ++++- config/locales/en.yml | 2 + config/routes.rb | 2 + lib/guardian.rb | 17 +++++++ spec/components/guardian_spec.rb | 40 +++++++++++++++++ .../admin/users_controller_spec.rb | 45 +++++++++++++++++-- 10 files changed, 163 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/admin/models/admin_user.js.coffee b/app/assets/javascripts/admin/models/admin_user.js.coffee index 950fb624ac7..42d97bf2b08 100644 --- a/app/assets/javascripts/admin/models/admin_user.js.coffee +++ b/app/assets/javascripts/admin/models/admin_user.js.coffee @@ -17,6 +17,19 @@ window.Discourse.AdminUser = Discourse.Model.extend @set('can_revoke_admin',true) $.ajax "/admin/users/#{@get('id')}/grant_admin", type: 'PUT' + # Revoke the user's moderation access + revokeModeration: -> + @set('moderator',false) + @set('can_grant_moderation',true) + @set('can_revoke_moderation',false) + $.ajax "/admin/users/#{@get('id')}/revoke_moderation", type: 'PUT' + + grantModeration: -> + @set('moderator',true) + @set('can_grant_moderation',false) + @set('can_revoke_moderation',true) + $.ajax "/admin/users/#{@get('id')}/grant_moderation", type: 'PUT' + refreshBrowsers: -> $.ajax "/admin/users/#{@get('id')}/refresh_browsers", type: 'POST' diff --git a/app/assets/javascripts/admin/templates/user.js.handlebars b/app/assets/javascripts/admin/templates/user.js.handlebars index 1d29846be58..ddfbfec07ef 100644 --- a/app/assets/javascripts/admin/templates/user.js.handlebars +++ b/app/assets/javascripts/admin/templates/user.js.handlebars @@ -84,6 +84,21 @@
{{i18n admin.user.moderator}}
{{content.moderator}}
+
+ {{#if content.can_revoke_moderation}} + + {{/if}} + {{#if content.can_grant_moderation}} + + {{/if}} +
+
{{i18n trust_level}}
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index a378f907997..ada4943a005 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -63,6 +63,22 @@ class Admin::UsersController < Admin::AdminController render_serialized(@user, AdminUserSerializer) end + def revoke_moderation + @moderator = User.where(id: params[:user_id]).first + guardian.ensure_can_revoke_moderation!(@moderator) + @moderator.change_trust_level(:advanced) + @moderator.save + render nothing: true + end + + def grant_moderation + @user = User.where(id: params[:user_id]).first + guardian.ensure_can_grant_moderation!(@user) + @user.change_trust_level(:moderator) + @user.save + render_serialized(@user, AdminUserSerializer) + end + def approve @user = User.where(id: params[:user_id]).first guardian.ensure_can_approve!(@user) diff --git a/app/models/user.rb b/app/models/user.rb index 56cdff20ade..5d484acff3d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -401,6 +401,11 @@ class User < ActiveRecord::Base (self.trust_level || TrustLevel.Levels[:new]) >= TrustLevel.Levels[level] end + def change_trust_level(level) + raise "Invalid trust level #{level}" unless TrustLevel.Levels.has_key?(level) + self.trust_level = TrustLevel.Levels[level] + end + def guardian Guardian.new(self) end diff --git a/app/serializers/admin_detailed_user_serializer.rb b/app/serializers/admin_detailed_user_serializer.rb index 24694d11b50..ab458b4301c 100644 --- a/app/serializers/admin_detailed_user_serializer.rb +++ b/app/serializers/admin_detailed_user_serializer.rb @@ -2,8 +2,10 @@ class AdminDetailedUserSerializer < AdminUserSerializer attributes :moderator, :can_grant_admin, - :can_impersonate, :can_revoke_admin, + :can_grant_moderation, + :can_revoke_moderation, + :can_impersonate, :like_count, :post_count, :flags_given_count, @@ -21,6 +23,14 @@ class AdminDetailedUserSerializer < AdminUserSerializer scope.can_grant_admin?(object) end + def can_revoke_moderation + scope.can_revoke_moderation?(object) + end + + def can_grant_moderation + scope.can_grant_moderation?(object) + end + def can_delete_all_posts scope.can_delete_all_posts?(object) end diff --git a/config/locales/en.yml b/config/locales/en.yml index a1bd47e8b3a..920e5f16347 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -390,6 +390,8 @@ en: impersonate: 'Impersonate' revoke_admin: 'Revoke Admin' grant_admin: 'Grant Admin' + revoke_moderation: 'Revoke Moderation' + grant_moderation: 'Grant Moderation' basics: Basics reputation: Reputation permissions: Permissions diff --git a/config/routes.rb b/config/routes.rb index a5980b3e695..855654b7279 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -34,6 +34,8 @@ Discourse::Application.routes.draw do put 'unban' => 'users#unban' put 'revoke_admin' => 'users#revoke_admin' put 'grant_admin' => 'users#grant_admin' + put 'revoke_moderation' => 'users#revoke_moderation' + put 'grant_moderation' => 'users#grant_moderation' put 'approve' => 'users#approve' post 'refresh_browsers' => 'users#refresh_browsers' end diff --git a/lib/guardian.rb b/lib/guardian.rb index d8df070ffac..7577afaf2fe 100644 --- a/lib/guardian.rb +++ b/lib/guardian.rb @@ -131,6 +131,23 @@ class Guardian true end + def can_revoke_moderation?(moderator) + return false unless @user.try(:admin?) + return false if moderator.blank? + return false if @user.id == moderator.id + return false unless moderator.trust_level == TrustLevel.Levels[:moderator] + true + end + + def can_grant_moderation?(user) + return false unless @user.try(:admin?) + return false if user.blank? + return false if @user.id == user.id + return false if user.admin? + return false if user.has_trust_level?(:moderator) + true + end + # Can we see who acted on a post in a particular way? def can_see_post_actors?(topic, post_action_type_id) return false unless topic.present? diff --git a/spec/components/guardian_spec.rb b/spec/components/guardian_spec.rb index 4c12e0e8de8..a63005a034b 100644 --- a/spec/components/guardian_spec.rb +++ b/spec/components/guardian_spec.rb @@ -761,6 +761,46 @@ describe Guardian do end end + context 'can_grant_moderation?' do + it "wont allow a non logged in user to grant an moderator's access" do + Guardian.new.can_grant_moderation?(user).should be_false + end + + it "wont allow a regular user to revoke an modearator's access" do + Guardian.new(user).can_grant_moderation?(moderator).should be_false + end + + it 'wont allow an admin to grant their own access' do + Guardian.new(admin).can_grant_moderation?(admin).should be_false + end + + it 'wont allow an admin to grant it to an already moderator' do + Guardian.new(admin).can_grant_moderation?(moderator).should be_false + end + + it "allows an admin to grant a regular user access" do + Guardian.new(admin).can_grant_moderation?(user).should be_true + end + end + + context 'can_revoke_moderation?' do + it "wont allow a non logged in user to revoke an moderator's access" do + Guardian.new.can_revoke_moderation?(moderator).should be_false + end + + it "wont allow a regular user to revoke an moderator's access" do + Guardian.new(user).can_revoke_moderation?(moderator).should be_false + end + + it 'wont allow an moderator to revoke their own moderator' do + Guardian.new(moderator).can_revoke_moderation?(moderator).should be_false + end + + it "allows an admin to revoke a moderator's access" do + Guardian.new(admin).can_revoke_moderation?(moderator).should be_true + end + end + context "can_see_pending_invites_from?" do it 'is false without a logged in user' do diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index 1268fddba62..e882b7ab86f 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -111,8 +111,47 @@ describe Admin::UsersController do end end + describe '.revoke_moderation' do + before do + @moderator = Fabricate(:moderator) + end + + it 'raises an error unless the user can revoke access' do + Guardian.any_instance.expects(:can_revoke_moderation?).with(@moderator).returns(false) + xhr :put, :revoke_moderation, user_id: @moderator.id + response.should be_forbidden + end + + it 'updates the moderator flag' do + xhr :put, :revoke_moderation, user_id: @moderator.id + @moderator.reload + @moderator.has_trust_level?(:moderator).should_not be_true + end + end + + context '.grant_moderation' do + before do + @another_user = Fabricate(:coding_horror) + end + + it "raises an error when the user doesn't have permission" do + Guardian.any_instance.expects(:can_grant_moderation?).with(@another_user).returns(false) + xhr :put, :grant_moderation, user_id: @another_user.id + response.should be_forbidden + end + + it "returns a 404 if the username doesn't exist" do + xhr :put, :grant_moderation, user_id: 123123 + response.should be_forbidden + end + + it 'updates the moderator flag' do + xhr :put, :grant_moderation, user_id: @another_user.id + @another_user.reload + @another_user.has_trust_level?(:moderator).should be_true + end + end + end - - -end \ No newline at end of file +end