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)