diff --git a/app/assets/javascripts/admin/controllers/admin_users_list_controller.js b/app/assets/javascripts/admin/controllers/admin_users_list_controller.js index c9e8bd93907..5794941d3fa 100644 --- a/app/assets/javascripts/admin/controllers/admin_users_list_controller.js +++ b/app/assets/javascripts/admin/controllers/admin_users_list_controller.js @@ -119,6 +119,24 @@ Discourse.AdminUsersListController = Ember.ArrayController.extend(Discourse.Pres approveUsers: function() { Discourse.AdminUser.bulkApprove(this.get('content').filterProperty('selected')); this.refreshUsers(); + }, + + /** + Reject all the currently selected users. + + @method rejectUsers + **/ + rejectUsers: function() { + var controller = this; + Discourse.AdminUser.bulkReject(this.get('content').filterProperty('selected')).then(function(result){ + var message = I18n.t("admin.users.reject_successful", {count: result.success}); + if (result.failed > 0) { + message += ' ' + I18n.t("admin.users.reject_failures", {count: result.failed}); + message += ' ' + I18n.t("admin.user.delete_forbidden", {count: Discourse.SiteSettings.delete_user_max_age}); + } + bootbox.alert(message); + controller.refreshUsers(); + }); } }); diff --git a/app/assets/javascripts/admin/models/admin_user.js b/app/assets/javascripts/admin/models/admin_user.js index 853cf484a6f..6e43b8698f2 100644 --- a/app/assets/javascripts/admin/models/admin_user.js +++ b/app/assets/javascripts/admin/models/admin_user.js @@ -343,6 +343,21 @@ Discourse.AdminUser.reopenClass({ }); }, + bulkReject: function(users) { + _.each(users, function(user){ + user.set('can_approve', false); + user.set('selected', false); + }); + + return Discourse.ajax("/admin/users/reject-bulk", { + type: 'DELETE', + data: { + users: users.map(function(u) { return u.id; }), + context: window.location.pathname + } + }); + }, + find: function(username) { return Discourse.ajax("/admin/users/" + username).then(function (result) { result.loadedDetails = true; diff --git a/app/assets/javascripts/admin/templates/users_list.js.handlebars b/app/assets/javascripts/admin/templates/users_list.js.handlebars index 22fa72799f8..f08e54b6066 100644 --- a/app/assets/javascripts/admin/templates/users_list.js.handlebars +++ b/app/assets/javascripts/admin/templates/users_list.js.handlebars @@ -20,6 +20,7 @@ {{#if hasSelection}}
+
{{/if}} diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index d158ca42775..3a3c0a70a95 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -114,6 +114,15 @@ class Admin::UsersController < Admin::AdminController render nothing: true end + def reject_bulk + d = UserDestroyer.new(current_user) + success_count = 0 + User.where(id: params[:users]).each do |u| + success_count += 1 if guardian.can_delete_user?(u) and d.destroy(u, params.slice(:context)) rescue UserDestroyer::PostsExistError + end + render json: {success: success_count, failed: (params[:users].try(:size) || 0) - success_count} + end + def destroy user = User.where(id: params[:id]).first guardian.ensure_can_delete_user!(user) diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 94d693b7d43..68a7acc2209 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1233,6 +1233,9 @@ en: approved_selected: one: "approve user" other: "approve users ({{count}})" + reject_selected: + one: "reject user" + other: "reject users ({{count}})" titles: active: 'Active Users' new: 'New Users' @@ -1246,6 +1249,12 @@ en: moderators: 'Moderators' blocked: 'Blocked Users' banned: 'Banned Users' + reject_successful: + one: "Successfully rejected 1 user." + other: "Successfully rejected %{count} users." + reject_failures: + one: "Failed to reject 1 user." + other: "Failed to reject %{count} users." user: ban_failed: "Something went wrong banning this user {{error}}" diff --git a/config/routes.rb b/config/routes.rb index 6f1863bf84d..632ec2db4c4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -36,6 +36,7 @@ Discourse::Application.routes.draw do collection do get 'list/:query' => 'users#index' put 'approve-bulk' => 'users#approve_bulk' + delete 'reject-bulk' => 'users#reject_bulk' end put 'ban' put 'delete_all_posts' diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index 9661ac05579..b3ea66a2fd1 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -196,6 +196,57 @@ describe Admin::UsersController do end end + context '.reject_bulk' do + let(:reject_me) { Fabricate(:user) } + let(:reject_me_too) { Fabricate(:user) } + + it 'does nothing without users' do + UserDestroyer.any_instance.expects(:destroy).never + xhr :delete, :reject_bulk + end + + it "won't delete users if not allowed" do + Guardian.any_instance.stubs(:can_delete_user?).returns(false) + UserDestroyer.any_instance.expects(:destroy).never + xhr :delete, :reject_bulk, users: [reject_me.id] + end + + it "reports successes" do + Guardian.any_instance.stubs(:can_delete_user?).returns(true) + UserDestroyer.any_instance.stubs(:destroy).returns(true) + xhr :delete, :reject_bulk, users: [reject_me.id, reject_me_too.id] + response.should be_success + json = ::JSON.parse(response.body) + json['success'].to_i.should == 2 + json['failed'].to_i.should == 0 + end + + context 'failures' do + before do + Guardian.any_instance.stubs(:can_delete_user?).returns(true) + end + + it 'can handle some successes and some failures' do + UserDestroyer.any_instance.stubs(:destroy).with(reject_me, anything).returns(false) + UserDestroyer.any_instance.stubs(:destroy).with(reject_me_too, anything).returns(true) + xhr :delete, :reject_bulk, users: [reject_me.id, reject_me_too.id] + response.should be_success + json = ::JSON.parse(response.body) + json['success'].to_i.should == 1 + json['failed'].to_i.should == 1 + end + + it 'reports failure due to a user still having posts' do + UserDestroyer.any_instance.expects(:destroy).with(reject_me, anything).raises(UserDestroyer::PostsExistError) + xhr :delete, :reject_bulk, users: [reject_me.id] + response.should be_success + json = ::JSON.parse(response.body) + json['success'].to_i.should == 0 + json['failed'].to_i.should == 1 + end + end + end + context '.destroy' do before do @delete_me = Fabricate(:user)