summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/models/project.rb17
-rw-r--r--app/views/projects/_form.html.erb2
-rw-r--r--config/locales/de.yml1
-rw-r--r--config/locales/en.yml1
-rw-r--r--db/migrate/20221214173537_add_select_project_publicity_permission.rb15
-rw-r--r--lib/redmine/preparation.rb1
-rw-r--r--test/fixtures/roles.yml3
-rw-r--r--test/functional/projects_controller_test.rb57
8 files changed, 93 insertions, 4 deletions
diff --git a/app/models/project.rb b/app/models/project.rb
index d182dadce..80bea61d9 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -823,7 +823,6 @@ class Project < ActiveRecord::Base
'name',
'description',
'homepage',
- 'is_public',
'identifier',
'custom_field_values',
'custom_fields',
@@ -835,6 +834,22 @@ class Project < ActiveRecord::Base
'default_assigned_to_id')
safe_attributes(
+ 'is_public',
+ :if =>
+ lambda do |project, user|
+ if project.new_record?
+ if user.admin?
+ true
+ else
+ default_member_role&.has_permission?(:select_project_publicity)
+ end
+ else
+ user.allowed_to?(:select_project_publicity, project)
+ end
+ end
+ )
+
+ safe_attributes(
'enabled_module_names',
:if =>
lambda do |project, user|
diff --git a/app/views/projects/_form.html.erb b/app/views/projects/_form.html.erb
index 7c988fb0e..3cde41599 100644
--- a/app/views/projects/_form.html.erb
+++ b/app/views/projects/_form.html.erb
@@ -11,7 +11,7 @@
<% end %></p>
<p><%= f.text_field :homepage, :size => 60 %></p>
<p>
- <%= f.check_box :is_public %>
+ <%= f.check_box :is_public, :disabled => !@project.safe_attribute?(:is_public) %>
<em class="info"><%= Setting.login_required? ? l(:text_project_is_public_non_member) : l(:text_project_is_public_anonymous) %></em>
</p>
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 69513f96f..9ac76f852 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -953,6 +953,7 @@ de:
permission_rename_wiki_pages: Wiki-Seiten umbenennen
permission_save_queries: Filter speichern
permission_select_project_modules: Projektmodule auswählen
+ permission_select_project_publicity: Projekt als privat oder öffentlich markieren
permission_set_issues_private: Tickets als privat oder öffentlich markieren
permission_set_notes_private: Kommentar als privat markieren
permission_set_own_issues_private: Eigene Tickets als privat oder öffentlich markieren
diff --git a/config/locales/en.yml b/config/locales/en.yml
index d12c54497..64d09c8cf 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -522,6 +522,7 @@ en:
permission_edit_project: Edit project
permission_close_project: Close / reopen the project
permission_delete_project: Delete the project
+ permission_select_project_publicity: Set project public or private
permission_select_project_modules: Select project modules
permission_manage_members: Manage members
permission_manage_project_activities: Manage project activities
diff --git a/db/migrate/20221214173537_add_select_project_publicity_permission.rb b/db/migrate/20221214173537_add_select_project_publicity_permission.rb
new file mode 100644
index 000000000..9b3db0cdc
--- /dev/null
+++ b/db/migrate/20221214173537_add_select_project_publicity_permission.rb
@@ -0,0 +1,15 @@
+class AddSelectProjectPublicityPermission < ActiveRecord::Migration[5.2]
+ def up
+ Role.find_each do |r|
+ r.add_permission!(:select_project_publicity) if r.permissions.include?(:edit_project)
+ end
+ end
+
+ def down
+ Role.find_each do |r|
+ r.remove_permission!(:select_project_publicity)
+ end
+ end
+
+ def run_in_request?; true end
+end
diff --git a/lib/redmine/preparation.rb b/lib/redmine/preparation.rb
index 54b623973..c51ecfdb9 100644
--- a/lib/redmine/preparation.rb
+++ b/lib/redmine/preparation.rb
@@ -39,6 +39,7 @@ module Redmine
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, :read => true
+ map.permission :select_project_publicity, {}, :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 076d347ff..df15c9c0f 100644
--- a/test/fixtures/roles.yml
+++ b/test/fixtures/roles.yml
@@ -11,6 +11,7 @@ roles_001:
- :edit_project
- :close_project
- :delete_project
+ - :select_project_publicity
- :select_project_modules
- :manage_members
- :manage_versions
@@ -85,6 +86,7 @@ roles_002:
---
- :edit_project
- :delete_project
+ - :select_project_publicity
- :manage_members
- :manage_versions
- :manage_categories
@@ -137,6 +139,7 @@ roles_003:
permissions: |
---
- :edit_project
+ - :select_project_publicity
- :manage_members
- :manage_versions
- :manage_categories
diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb
index a18850e66..0ac0ecc36 100644
--- a/test/functional/projects_controller_test.rb
+++ b/test/functional/projects_controller_test.rb
@@ -407,6 +407,22 @@ class ProjectsControllerTest < Redmine::ControllerTest
end
end
+ def test_new_by_non_admin_should_enable_setting_public_if_default_role_is_allowed_to_set_public
+ Role.non_member.add_permission!(:add_project)
+ default_role = Role.generate!(permissions: [:add_project])
+ user = User.generate!
+ @request.session[:user_id] = user.id
+
+ with_settings new_project_user_role_id: default_role.id.to_s do
+ get :new
+ assert_select 'input[name=?][disabled=disabled]', 'project[is_public]'
+
+ default_role.add_permission!(:select_project_publicity)
+ get :new
+ assert_select 'input[name=?]:not([disabled])', 'project[is_public]'
+ end
+ end
+
def test_new_should_not_display_invalid_search_link
@request.session[:user_id] = 1
@@ -504,7 +520,6 @@ class ProjectsControllerTest < Redmine::ControllerTest
:name => "blog",
:description => "weblog",
:identifier => "blog",
- :is_public => 1,
:custom_field_values => {
'3' => 'Beta'
},
@@ -518,7 +533,6 @@ class ProjectsControllerTest < Redmine::ControllerTest
project = Project.find_by_name('blog')
assert_kind_of Project, project
assert_equal 'weblog', project.description
- assert_equal true, project.is_public?
assert_equal [1, 3], project.trackers.map(&:id).sort
assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
@@ -527,6 +541,45 @@ class ProjectsControllerTest < Redmine::ControllerTest
assert_equal 1, project.members.size
end
+ test "#create by user without select_project_publicity permission should not create a new private project" do
+ Role.non_member.add_permission! :add_project
+ default_role = Project.default_member_role
+ default_role.remove_permission!(:select_project_publicity)
+ @request.session[:user_id] = 9
+
+ post(
+ :create, :params => {
+ :project => {
+ :name => "blog",
+ :identifier => "blog",
+ :enabled_module_names => ['issue_tracking', 'news', 'repository'],
+ :is_public => 0
+ }
+ }
+ )
+
+ project = Project.find_by_name('blog')
+ assert_equal true, project.is_public?
+ end
+
+ test "#create by non-admin user with add_project and select_project_publicity permission should create a new private project" do
+ @request.session[:user_id] = 2
+
+ post(
+ :create, :params => {
+ :project => {
+ :name => "blog",
+ :identifier => "blog",
+ :enabled_module_names => ['issue_tracking', 'news', 'repository'],
+ :is_public => 0
+ }
+ }
+ )
+
+ project = Project.find_by_name('blog')
+ assert_equal false, project.is_public?
+ end
+
test "#create by non-admin user with add_project permission should fail with parent_id" do
Role.non_member.add_permission! :add_project
User.find(9).update! :language => 'en'