]> source.dussan.org Git - redmine.git/commitdiff
User bulk destroy (#37674).
authorGo MAEDA <maeda@farend.jp>
Tue, 20 Sep 2022 03:36:40 +0000 (03:36 +0000)
committerGo MAEDA <maeda@farend.jp>
Tue, 20 Sep 2022 03:36:40 +0000 (03:36 +0000)
includes a confirmation page that also gives the opportunity to lock
users instead of deleting them.

Patch by Jens Krämer.

git-svn-id: https://svn.redmine.org/redmine/trunk@21824 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/users_controller.rb
app/views/context_menus/users.html.erb
app/views/users/bulk_destroy.html.erb [new file with mode: 0644]
config/locales/en.yml
config/routes.rb
test/functional/users_controller_test.rb

index 5cd9eb9314bfee3b415e5c6fffed8b049deba791..0d80fc33a238f9333c6d0b0c1fd8f337a2102bff 100644 (file)
@@ -215,6 +215,21 @@ class UsersController < ApplicationController
     end
   end
 
+  def bulk_destroy
+    @users = User.logged.where(id: params[:ids]).where.not(id: User.current)
+    (render_404; return) unless @users.any?
+
+    if params[:lock]
+      @users.update_all status: User::STATUS_LOCKED
+      flash[:notice] = l(:notice_successful_update)
+      redirect_to users_path
+    elsif params[:confirm] == I18n.t(:general_text_Yes)
+      @users.destroy_all
+      flash[:notice] = l(:notice_successful_delete)
+      redirect_to users_path
+    end
+  end
+
   private
 
   def find_user(logged = true)
index 2a0c12be1f8df53b05bc97dfd1a239dc7c3bfd99..3bd4f7d836f55e3500d1cb7da2647527ccc785d2 100644 (file)
           method: :delete, class: 'icon icon-del' %>
       </li>
     <% end %>
+  <% else %>
+    <li>
+      <%= context_menu_link l(:button_delete),
+        {controller: 'users', action: 'bulk_destroy', ids: @users.map(&:id)},
+        method: :delete, class: 'icon icon-del' %>
+    </li>
   <% end %>
 </ul>
diff --git a/app/views/users/bulk_destroy.html.erb b/app/views/users/bulk_destroy.html.erb
new file mode 100644 (file)
index 0000000..f18eb81
--- /dev/null
@@ -0,0 +1,22 @@
+<%= title l(:label_confirmation) %>
+
+<%= form_tag(bulk_destroy_users_path(ids: @users.map(&:id)), method: :delete) do %>
+<div class="warning">
+
+<p><%= simple_format l :text_users_bulk_destroy_head %></p>
+
+<% @users.each do |user| %>
+  <p><strong><%= user.name %></strong> (<%= user.login %>)</p>
+<% end %>
+
+<p><%= l :text_users_bulk_destroy_confirm, yes: l(:general_text_Yes) %></p>
+<p><%= text_field_tag 'confirm' %></p>
+
+</div>
+
+<p>
+  <%= submit_tag l(:button_delete), class: 'btn-alert btn-small' %>
+  <%= submit_tag l(:button_lock), class: 'btn', name: 'lock' %>
+  <%= link_to l(:button_cancel), users_path %>
+</p>
+<% end %>
index 8f80d309e0cf38b0fdeae79bd1668feaa53d9525..335614dfbeb86d467771320bbe8d54fbd1903e4b 100644 (file)
@@ -1230,6 +1230,8 @@ en:
   text_project_close_confirmation: Are you sure you want to close the '%{value}' project to make it read-only?
   text_project_reopen_confirmation: Are you sure you want to reopen the '%{value}' project?
   text_project_archive_confirmation: Are you sure you want to archive the '%{value}' project?
+  text_users_bulk_destroy_head: 'You are about to delete the following users and remove all references to them. This cannot be undone. Often, locking users instead of deleting them is the better solution.'
+  text_users_bulk_destroy_confirm: 'To confirm, please enter "%{yes}" below.'
   text_workflow_edit: Select a role and a tracker to edit the workflow
   text_are_you_sure: Are you sure?
   text_journal_changed: "%{label} changed from %{old} to %{new}"
index f2106d90f7c5258deb19ea195ade79fdc913233e..fa65b4417dc9286fed5a9f6ff80741cf57ac4f40 100644 (file)
@@ -110,6 +110,9 @@ Rails.application.routes.draw do
 
   match '/users/context_menu', to: 'context_menus#users', as: :users_context_menu, via: [:get, :post]
   resources :users do
+    collection do
+      delete 'bulk_destroy'
+    end
     resources :memberships, :controller => 'principal_memberships'
     resources :email_addresses, :only => [:index, :create, :update, :destroy]
   end
index af2f1871f98b471fe3e8a8b1ed50f9d6ecef57fd..c17737fe16e95927694583f9b5e804afd27f3e43 100644 (file)
@@ -1092,4 +1092,61 @@ class UsersControllerTest < Redmine::ControllerTest
       assert_response 422
     end
   end
+
+  def test_bulk_destroy
+    assert_difference 'User.count', -1 do
+      delete :bulk_destroy, :params => {:ids => [2], :confirm => 'Yes'}
+    end
+    assert_redirected_to '/users'
+    assert_nil User.find_by_id(2)
+  end
+
+  def test_bulk_destroy_should_not_destroy_current_user
+    assert_difference 'User.count', -1 do
+      delete :bulk_destroy, :params => {:ids => [2, 1], :confirm => 'Yes'}
+    end
+    assert_redirected_to '/users'
+    assert_nil User.find_by_id(2)
+  end
+
+  def test_bulk_destroy_with_lock_param_should_lock_instead
+    assert_no_difference 'User.count' do
+      delete :bulk_destroy, :params => {:ids => [2], :lock => 'lock'}
+    end
+    assert_redirected_to '/users'
+    assert User.find_by_id(2).locked?
+  end
+
+  def test_bulk_destroy_should_require_confirmation
+    assert_no_difference 'User.count' do
+      delete :bulk_destroy, :params => {:ids => [2]}
+    end
+    assert_response :success
+    assert_select '.warning', :text => /You are about to delete the following users/
+  end
+
+  def test_bulk_destroy_should_require_correct_confirmation
+    assert_no_difference 'User.count' do
+      delete :bulk_destroy, :params => {:ids => [2], :confirm => 'wrong'}
+    end
+    assert_response :success
+    assert_select '.warning', :text => /You are about to delete the following users/
+  end
+
+  def test_bulk_destroy_should_be_denied_for_non_admin_users
+    @request.session[:user_id] = 3
+
+    assert_no_difference 'User.count' do
+      delete :bulk_destroy, :params => {:ids => [2], :confirm => 'Yes'}
+    end
+    assert_response 403
+  end
+
+  def test_bulk_destroy_should_be_denied_for_anonymous
+    assert User.find(6).anonymous?
+    assert_no_difference 'User.count' do
+      delete :bulk_destroy, :params => {:ids => [6], :confirm => "Yes"}
+    end
+    assert_response 404
+  end
 end