summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2011-01-16 15:23:11 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2011-01-16 15:23:11 +0000
commite9f62d1209bfa81df33bcb390eb67ba4cab90c0a (patch)
tree40dff8ceb02a30dce788799904d4a8c145d0d6e2
parent0e3017dc62c672a291cda6053aaba6bda39b2de4 (diff)
downloadredmine-e9f62d1209bfa81df33bcb390eb67ba4cab90c0a.tar.gz
redmine-e9f62d1209bfa81df33bcb390eb67ba4cab90c0a.zip
Enable ability for administrators to delete users (#7296).
User's personal data (eg. preferences, tokens, private queries...) are deleted, public data (eg. issues, wiki edits, attachments...) are reassigned to the anonymous user. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4729 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r--app/controllers/users_controller.rb13
-rw-r--r--app/views/users/edit.rhtml1
-rw-r--r--app/views/users/index.rhtml5
-rw-r--r--config/routes.rb3
-rw-r--r--test/functional/users_controller_test.rb24
-rw-r--r--test/integration/api_test/users_test.rb40
-rw-r--r--test/integration/routing_test.rb3
7 files changed, 69 insertions, 20 deletions
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 2a213f5e8..c7f9dcf1b 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -19,8 +19,8 @@ class UsersController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => :show
- before_filter :find_user, :only => [:show, :edit, :update, :edit_membership, :destroy_membership]
- accept_key_auth :index, :show, :create, :update
+ before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
+ accept_key_auth :index, :show, :create, :update, :destroy
helper :sort
include SortHelper
@@ -177,6 +177,15 @@ class UsersController < ApplicationController
redirect_to :controller => 'users', :action => 'edit', :id => @user
end
+ verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
+ def destroy
+ @user.destroy
+ respond_to do |format|
+ format.html { redirect_to(users_url) }
+ format.api { head :ok }
+ end
+ end
+
def edit_membership
@membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
@membership.save if request.post?
diff --git a/app/views/users/edit.rhtml b/app/views/users/edit.rhtml
index 0d9cb0133..0c5883e8b 100644
--- a/app/views/users/edit.rhtml
+++ b/app/views/users/edit.rhtml
@@ -1,6 +1,7 @@
<div class="contextual">
<%= link_to l(:label_profile), user_path(@user), :class => 'icon icon-user' %>
<%= change_status_link(@user) %>
+<%= link_to(l(:button_delete), @user, :confirm => l(:text_are_you_sure), :method => :delete, :class => 'icon icon-del') if User.current != @user %>
</div>
<h2><%= link_to l(:label_user_plural), :controller => 'users', :action => 'index' %> &#187; <%=h @user.login %></h2>
diff --git a/app/views/users/index.rhtml b/app/views/users/index.rhtml
index 69ad73747..07308265e 100644
--- a/app/views/users/index.rhtml
+++ b/app/views/users/index.rhtml
@@ -37,7 +37,10 @@
<td align="center"><%= checked_image user.admin? %></td>
<td class="created_on" align="center"><%= format_time(user.created_on) %></td>
<td class="last_login_on" align="center"><%= format_time(user.last_login_on) unless user.last_login_on.nil? %></td>
- <td><small><%= change_status_link(user) %></small></td>
+ <td class="buttons">
+ <%= change_status_link(user) %>
+ <%= link_to(l(:button_delete), user, :confirm => l(:text_are_you_sure), :method => :delete, :class => 'icon icon-del') unless User.current == user %>
+ </td>
</tr>
<% end -%>
</tbody>
diff --git a/config/routes.rb b/config/routes.rb
index 3b37b5150..383d9cf89 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -122,8 +122,7 @@ ActionController::Routing::Routes.draw do |map|
map.resources :users, :member => {
:edit_membership => :post,
:destroy_membership => :post
- },
- :except => [:destroy]
+ }
# For nice "roadmap" in the url for the index action
map.connect 'projects/:project_id/roadmap', :controller => 'versions', :action => 'index'
diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb
index 8aa311ebb..6837deab4 100644
--- a/test/functional/users_controller_test.rb
+++ b/test/functional/users_controller_test.rb
@@ -264,6 +264,30 @@ class UsersControllerTest < ActionController::TestCase
assert u.check_password?('newpass')
end
+ def test_destroy
+ assert_difference 'User.count', -1 do
+ delete :destroy, :id => 2
+ end
+ assert_redirected_to '/users'
+ assert_nil User.find_by_id(2)
+ end
+
+ def test_destroy_should_not_accept_get_requests
+ assert_no_difference 'User.count' do
+ get :destroy, :id => 2
+ end
+ assert_response 405
+ end
+
+ def test_destroy_should_be_denied_for_non_admin_users
+ @request.session[:user_id] = 3
+
+ assert_no_difference 'User.count' do
+ get :destroy, :id => 2
+ end
+ assert_response 403
+ end
+
def test_edit_membership
post :edit_membership, :id => 2, :membership_id => 1,
:membership => { :role_ids => [2]}
diff --git a/test/integration/api_test/users_test.rb b/test/integration/api_test/users_test.rb
index e1eb7a237..00dc4cc95 100644
--- a/test/integration/api_test/users_test.rb
+++ b/test/integration/api_test/users_test.rb
@@ -245,26 +245,36 @@ class ApiTest::UsersTest < ActionController::IntegrationTest
end
end
end
+ end
- context "DELETE /users/2" do
- context ".xml" do
- should "not be allowed" do
- assert_no_difference('User.count') do
- delete '/users/2.xml'
- end
-
- assert_response :method_not_allowed
+ context "DELETE /users/2" do
+ context ".xml" do
+ should_allow_api_authentication(:delete,
+ '/users/2.xml',
+ {},
+ {:success_code => :ok})
+
+ should "delete user" do
+ assert_difference('User.count', -1) do
+ delete '/users/2.xml', {}, :authorization => credentials('admin')
end
+
+ assert_response :ok
end
-
- context ".json" do
- should "not be allowed" do
- assert_no_difference('User.count') do
- delete '/users/2.json'
- end
+ end
+
+ context ".json" do
+ should_allow_api_authentication(:delete,
+ '/users/2.xml',
+ {},
+ {:success_code => :ok})
- assert_response :method_not_allowed
+ should "delete user" do
+ assert_difference('User.count', -1) do
+ delete '/users/2.json', {}, :authorization => credentials('admin')
end
+
+ assert_response :ok
end
end
end
diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb
index 4b18e317a..1198081fc 100644
--- a/test/integration/routing_test.rb
+++ b/test/integration/routing_test.rb
@@ -302,6 +302,9 @@ class RoutingTest < ActionController::IntegrationTest
should_route :put, "/users/444", :controller => 'users', :action => 'update', :id => '444'
should_route :put, "/users/444.xml", :controller => 'users', :action => 'update', :id => '444', :format => 'xml'
+
+ should_route :delete, "/users/44", :controller => 'users', :action => 'destroy', :id => '44'
+ should_route :delete, "/users/44.xml", :controller => 'users', :action => 'destroy', :id => '44', :format => 'xml'
end
# TODO: should they all be scoped under /projects/:project_id ?