From 1cb4f0bc1cddc76baa51ab81d0e6c496cfb69797 Mon Sep 17 00:00:00 2001 From: Holger Just Date: Tue, 1 Sep 2020 17:04:57 +0200 Subject: [PATCH] Allow normal users to delete a project --- app/controllers/projects_controller.rb | 11 +++++-- app/models/project.rb | 8 +++++ app/views/projects/destroy.html.erb | 2 +- app/views/projects/show.html.erb | 3 ++ config/locales/de.yml | 1 + config/locales/en.yml | 1 + lib/redmine.rb | 1 + test/fixtures/roles.yml | 2 ++ test/functional/projects_controller_test.rb | 34 +++++++++++++++++++++ 9 files changed, 59 insertions(+), 4 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index aa2927c83a..ade724dddd 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -23,9 +23,9 @@ class ProjectsController < ApplicationController menu_item :projects, :only => [:index, :new, :copy, :create] before_action :find_project, :except => [ :index, :autocomplete, :list, :new, :create, :copy ] - before_action :authorize, :except => [ :index, :autocomplete, :list, :new, :create, :copy, :archive, :unarchive, :destroy] + before_action :authorize, :except => [ :index, :autocomplete, :list, :new, :create, :copy, :archive, :unarchive] before_action :authorize_global, :only => [:new, :create] - before_action :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ] + before_action :require_admin, :only => [ :copy, :archive, :unarchive ] accept_rss_auth :index accept_api_auth :index, :show, :create, :update, :destroy require_sudo_mode :destroy @@ -259,11 +259,16 @@ class ProjectsController < ApplicationController # Delete @project def destroy + unless @project.deletable? + deny_access + return + end + @project_to_destroy = @project if api_request? || params[:confirm] @project_to_destroy.destroy respond_to do |format| - format.html { redirect_to admin_projects_path } + format.html { redirect_to User.current.admin? ? admin_projects_path : projects_path } format.api { render_api_ok } end end diff --git a/app/models/project.rb b/app/models/project.rb index 0119b12281..0c3b54630a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -709,6 +709,14 @@ class Project < ActiveRecord::Base end end + def deletable?(user = User.current) + if user.admin? + return true + else + user.allowed_to?(:delete_project, self) && leaf? + end + end + # Return the enabled module with the given name # or nil if the module is not enabled for the project def enabled_module(name) diff --git a/app/views/projects/destroy.html.erb b/app/views/projects/destroy.html.erb index 11137f75e1..15a54d1cca 100644 --- a/app/views/projects/destroy.html.erb +++ b/app/views/projects/destroy.html.erb @@ -19,6 +19,6 @@

<%= submit_tag l(:button_delete) %> - <%= link_to l(:button_cancel), :controller => 'admin', :action => 'projects' %> + <%= link_to l(:button_cancel), User.current.admin? ? admin_projects_path : projects_path %>

<% end %> diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb index c8745be148..18b15d840b 100644 --- a/app/views/projects/show.html.erb +++ b/app/views/projects/show.html.erb @@ -12,6 +12,9 @@ <%= link_to l(:button_reopen), reopen_project_path(@project), :data => {:confirm => l(:text_are_you_sure)}, :method => :post, :class => 'icon icon-unlock' %> <% end %> <% end %> + <% if @project.deletable? %> + <%= link_to l(:button_delete), project_path(@project), :method => :delete, :class => 'icon icon-del' %> + <% end %> <%= link_to_if_authorized l(:label_settings), {:controller => 'projects', :action => 'settings', :id => @project}, :class => 'icon icon-settings' if User.current.allowed_to?(:edit_project, @project) %> diff --git a/config/locales/de.yml b/config/locales/de.yml index 99b7adea8d..c926a89d37 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -917,6 +917,7 @@ de: permission_delete_issues: Tickets löschen permission_delete_messages: Forenbeiträge löschen permission_delete_own_messages: Eigene Forenbeiträge löschen + permission_delete_project: Projekt löschen permission_delete_wiki_pages: Wiki-Seiten löschen permission_delete_wiki_pages_attachments: Anhänge löschen permission_delete_documents: Dokumente löschen diff --git a/config/locales/en.yml b/config/locales/en.yml index 7e7def09af..a5f739185f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -500,6 +500,7 @@ en: permission_add_subprojects: Create subprojects permission_edit_project: Edit project permission_close_project: Close / reopen the project + permission_delete_project: Delete the project permission_select_project_modules: Select project modules permission_manage_members: Manage members permission_manage_project_activities: Manage project activities diff --git a/lib/redmine.rb b/lib/redmine.rb index 666111d346..d7a8b241eb 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -84,6 +84,7 @@ Redmine::AccessControl.map do |map| map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member map.permission :close_project, {:projects => [:close, :reopen]}, :require => :member, :read => true + map.permission :delete_project, {:projects => :destroy}, :require => :member map.permission :select_project_modules, {:projects => :modules}, :require => :member map.permission :view_members, {:members => [:index, :show]}, :public => true, :read => true map.permission :manage_members, {:projects => :settings, :members => [:index, :show, :new, :create, :edit, :update, :destroy, :autocomplete]}, :require => :member diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml index 13433874e8..650511e2dd 100644 --- a/test/fixtures/roles.yml +++ b/test/fixtures/roles.yml @@ -10,6 +10,7 @@ roles_001: - :add_project - :edit_project - :close_project + - :delete_project - :select_project_modules - :manage_members - :manage_versions @@ -77,6 +78,7 @@ roles_002: permissions: | --- - :edit_project + - :delete_project - :manage_members - :manage_versions - :manage_categories diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index fb186d6624..8d20704deb 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -1059,6 +1059,40 @@ class ProjectsControllerTest < Redmine::ControllerTest assert_nil Project.find_by_id(1) end + def test_destroy_with_normal_user_should_destroy + set_tmp_attachments_directory + @request.session[:user_id] = 2 # non-admin + + assert_difference 'Project.count', -1 do + delete( + :destroy, + :params => { + :id => 2, + :confirm => 1 + } + ) + assert_redirected_to '/projects' + end + assert_nil Project.find_by_id(2) + end + + def test_destroy_with_normal_user_should_not_destroy_with_subprojects + set_tmp_attachments_directory + @request.session[:user_id] = 2 # non-admin + + assert_difference 'Project.count', 0 do + delete( + :destroy, + :params => { + :id => 1, + :confirm => 1 + } + ) + assert_response 403 + end + assert Project.find(1) + end + def test_archive @request.session[:user_id] = 1 # admin post(:archive, :params => {:id => 1}) -- 2.26.2