diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 386807f55..722893798 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -73,7 +73,7 @@ class ProjectsController < ApplicationController
@project.enabled_module_names = Setting.default_projects_modules
else
@project.enabled_module_names = params[:enabled_modules]
- if @project.save
+ if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
unless User.current.admin?
@@ -104,7 +104,7 @@ class ProjectsController < ApplicationController
else
@project = Project.new(params[:project])
@project.enabled_module_names = params[:enabled_modules]
- if @project.copy(@source_project, :only => params[:only])
+ if validate_parent_id && @project.copy(@source_project, :only => params[:only])
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'admin', :action => 'projects'
@@ -156,7 +156,7 @@ class ProjectsController < ApplicationController
def edit
if request.post?
@project.attributes = params[:project]
- if @project.save
+ if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'settings', :id => @project
@@ -395,4 +395,19 @@ private
@selected_tracker_ids = (default_trackers || selectable_trackers).collect {|t| t.id.to_s }
end
end
+
+ # Validates parent_id param according to user's permissions
+ # TODO: move it to Project model in a validation that depends on User.current
+ def validate_parent_id
+ return true if User.current.admin?
+ parent_id = params[:project] && params[:project][:parent_id]
+ if parent_id || @project.new_record?
+ parent = parent_id.blank? ? nil : Project.find_by_id(parent_id.to_i)
+ unless @project.allowed_parents.include?(parent)
+ @project.errors.add :parent_id, :invalid
+ return false
+ end
+ end
+ true
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 7ab0186d5..a44d2fb82 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -36,7 +36,16 @@ module ProjectsHelper
end
def parent_project_select_tag(project)
- options = '' + project_tree_options_for_select(project.allowed_parents, :selected => project.parent)
+ selected = project.parent
+ # retrieve the requested parent project
+ parent_id = (params[:project] && params[:project][:parent_id]) || params[:parent_id]
+ if parent_id
+ selected = (parent_id.blank? ? nil : Project.find(parent_id))
+ end
+
+ options = ''
+ options << "" if project.allowed_parents.include?(nil)
+ options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected)
content_tag('select', options, :name => 'project[parent_id]')
end
diff --git a/app/models/project.rb b/app/models/project.rb
index d6526100f..3f34393b3 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -246,7 +246,11 @@ class Project < ActiveRecord::Base
# by the current user
def allowed_parents
return @allowed_parents if @allowed_parents
- @allowed_parents = (Project.find(:all, :conditions => Project.allowed_to_condition(User.current, :add_project, :member => true)) - self_and_descendants)
+ @allowed_parents = Project.find(:all, :conditions => Project.allowed_to_condition(User.current, :add_subprojects))
+ @allowed_parents = @allowed_parents - self_and_descendants
+ if User.current.allowed_to?(:add_project, nil, :global => true)
+ @allowed_parents << nil
+ end
unless parent.nil? || @allowed_parents.empty? || @allowed_parents.include?(parent)
@allowed_parents << parent
end
diff --git a/app/views/projects/_form.rhtml b/app/views/projects/_form.rhtml
index 0e286fcae..ef2a18855 100644
--- a/app/views/projects/_form.rhtml
+++ b/app/views/projects/_form.rhtml
@@ -4,7 +4,7 @@
<%= f.text_field :name, :required => true %>
<%= l(:text_caracters_maximum, 30) %>
-<% unless @project.allowed_parents.empty? %>
+<% unless @project.allowed_parents.compact.empty? %>
<%= parent_project_select_tag(@project) %>
<% end %>
diff --git a/app/views/projects/show.rhtml b/app/views/projects/show.rhtml
index a59c329c3..7d5412af0 100644
--- a/app/views/projects/show.rhtml
+++ b/app/views/projects/show.rhtml
@@ -1,3 +1,9 @@
+
+ <% if User.current.allowed_to?(:add_subprojects, @project) %>
+ <%= link_to l(:label_subproject_new), {:controller => 'projects', :action => 'add', :parent_id => @project}, :class => 'icon icon-add' %>
+ <% end %>
+
+
<%=l(:label_overview)%>
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index d70626c9d..4be997961 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -867,3 +867,5 @@ bg:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/bs.yml b/config/locales/bs.yml
index 860d1f254..015b05521 100644
--- a/config/locales/bs.yml
+++ b/config/locales/bs.yml
@@ -891,3 +891,5 @@ bs:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 0f4dbf010..59b3a44f4 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -870,3 +870,5 @@ ca:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 6165b6d6f..bcbf7ac99 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -873,3 +873,5 @@ cs:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 7877161e5..5123f241f 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -893,3 +893,5 @@ da:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/de.yml b/config/locales/de.yml
index da83637cb..81e69ef23 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -893,3 +893,5 @@ de:
label_missing_api_access_key: Missing an API access key
label_missing_feeds_access_key: Missing a RSS access key
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/el.yml b/config/locales/el.yml
index d4b9616d4..988002500 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -873,3 +873,5 @@ el:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 37709072a..1c421cb49 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -328,6 +328,7 @@ en:
setting_rest_api_enabled: Enable REST web service
permission_add_project: Create project
+ permission_add_subprojects: Create subprojects
permission_edit_project: Edit project
permission_select_project_modules: Select project modules
permission_manage_members: Manage members
@@ -463,6 +464,7 @@ en:
label_auth_source_new: New authentication mode
label_auth_source_plural: Authentication modes
label_subproject_plural: Subprojects
+ label_subproject_new: New subproject
label_and_its_subprojects: "{{value}} and its subprojects"
label_min_max_length: Min - Max length
label_list: List
diff --git a/config/locales/es.yml b/config/locales/es.yml
index e6a8447ea..bcf8bd21f 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -917,3 +917,5 @@ es:
button_show: Mostrar
text_line_separated: Múltiples valores permitidos (un valor en cada línea).
setting_mail_handler_body_delimiters: Truncar correos tras una de estas líneas
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 2dcf4574f..6f255d03e 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -903,3 +903,5 @@ fi:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index eb9b382ac..6ecfc240d 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -348,6 +348,7 @@ fr:
setting_rest_api_enabled: Activer l'API REST
permission_add_project: Créer un projet
+ permission_add_subprojects: Créer des sous-projets
permission_edit_project: Modifier le projet
permission_select_project_modules: Choisir les modules
permission_manage_members: Gérer les members
@@ -483,6 +484,7 @@ fr:
label_auth_source_new: Nouveau mode d'authentification
label_auth_source_plural: Modes d'authentification
label_subproject_plural: Sous-projets
+ label_subproject_new: Nouveau sous-projet
label_and_its_subprojects: "{{value}} et ses sous-projets"
label_min_max_length: Longueurs mini - maxi
label_list: Liste
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index 90a07f3d9..af1c6eb9a 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -893,3 +893,5 @@ gl:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/he.yml b/config/locales/he.yml
index 48300414a..f66970cc3 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -877,3 +877,5 @@ he:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index bc303fa45..a48228cdf 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -898,3 +898,5 @@
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/id.yml b/config/locales/id.yml
index 233b2fb49..e124764c7 100644
--- a/config/locales/id.yml
+++ b/config/locales/id.yml
@@ -885,3 +885,5 @@ id:
error_workflow_copy_source: Please select a source tracker or role
setting_start_of_week: Start calendars on
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/it.yml b/config/locales/it.yml
index b06e00c8f..b469099e3 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -880,3 +880,5 @@ it:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index d2dfb2bee..0de5160e0 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -902,3 +902,5 @@ ja:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index ce9dbf9b5..4b82b77f7 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -933,3 +933,5 @@ ko:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index 9294d2dc5..8c874065f 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -941,3 +941,5 @@ lt:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index 9ee414071..223df9b44 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -855,3 +855,5 @@ nl:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/no.yml b/config/locales/no.yml
index f6f9da3a3..461708b3b 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -868,3 +868,5 @@
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index affd8dcee..ad8040aa5 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -896,3 +896,5 @@ pl:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 1bb61edb1..ed8e83e33 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -900,3 +900,5 @@ pt-BR:
label_missing_feeds_access_key: Chave de acesso ao RSS faltando
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index 0a567a6bc..9441e56c2 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -885,3 +885,5 @@ pt:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/ro.yml b/config/locales/ro.yml
index 45956a4d8..f91525b73 100644
--- a/config/locales/ro.yml
+++ b/config/locales/ro.yml
@@ -870,3 +870,5 @@ ro:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index e484c3bcb..4c2822504 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -981,3 +981,5 @@ ru:
label_missing_api_access_key: Missing an API access key
label_missing_feeds_access_key: Missing a RSS access key
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index e95eefab6..53b06dc8d 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -872,3 +872,5 @@ sk:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 5845ee009..852ad6ac3 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -869,3 +869,5 @@ sl:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 5cbd59643..fd0a5db92 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -888,3 +888,5 @@
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index 81d287f2a..109ca7e6e 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -923,3 +923,5 @@ sv:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/th.yml b/config/locales/th.yml
index 07de4c4b6..294880baa 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -870,3 +870,5 @@ th:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index 056cb5656..42677a870 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -900,3 +900,5 @@ tr:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index f5b83b241..879b0aaa8 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -869,3 +869,5 @@ uk:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index 50ac2d8b9..afd63e9b4 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -932,3 +932,5 @@ vi:
button_show: Show
text_line_separated: Multiple values allowed (one line for each value).
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index ff0e1993b..44066dbd8 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -966,3 +966,5 @@
enumeration_doc_categories: 文件分類
enumeration_activities: 活動 (時間追蹤)
enumeration_system_activity: 系統活動
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/config/locales/zh.yml b/config/locales/zh.yml
index ea5ddb8fb..63143e1d9 100644
--- a/config/locales/zh.yml
+++ b/config/locales/zh.yml
@@ -897,3 +897,5 @@ zh:
label_missing_api_access_key: Missing an API access key
label_missing_feeds_access_key: Missing a RSS access key
setting_mail_handler_body_delimiters: Truncate emails after one of these lines
+ permission_add_subprojects: Create subprojects
+ label_subproject_new: New subproject
diff --git a/lib/redmine.rb b/lib/redmine.rb
index 50d090c4d..ecf9abc1c 100644
--- a/lib/redmine.rb
+++ b/lib/redmine.rb
@@ -32,6 +32,7 @@ Redmine::AccessControl.map do |map|
map.permission :select_project_modules, {:projects => :modules}, :require => :member
map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy, :autocomplete_for_member]}, :require => :member
map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :close_completed, :destroy]}, :require => :member
+ map.permission :add_subprojects, {:projects => :add}, :require => :member
map.project_module :issue_tracking do |map|
# Issue categories
diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb
index 6bdfc167c..6c88e41d7 100644
--- a/test/functional/projects_controller_test.rb
+++ b/test/functional/projects_controller_test.rb
@@ -89,71 +89,163 @@ class ProjectsControllerTest < ActionController::TestCase
)
end
- def test_get_add
- @request.session[:user_id] = 1
- get :add
- assert_response :success
- assert_template 'add'
- end
-
- def test_get_add_by_non_admin
- @request.session[:user_id] = 2
- get :add
- assert_response :success
- assert_template 'add'
- end
-
- def test_post_add
- @request.session[:user_id] = 1
- post :add, :project => { :name => "blog",
- :description => "weblog",
- :identifier => "blog",
- :is_public => 1,
- :custom_field_values => { '3' => 'Beta' }
- }
- assert_redirected_to '/projects/blog/settings'
+ context "#add" do
+ context "by admin user" do
+ setup do
+ @request.session[:user_id] = 1
+ end
+
+ should "accept get" do
+ get :add
+ assert_response :success
+ assert_template 'add'
+ end
+
+ should "accept post" do
+ post :add, :project => { :name => "blog",
+ :description => "weblog",
+ :identifier => "blog",
+ :is_public => 1,
+ :custom_field_values => { '3' => 'Beta' }
+ }
+ assert_redirected_to '/projects/blog/settings'
+
+ project = Project.find_by_name('blog')
+ assert_kind_of Project, project
+ assert_equal 'weblog', project.description
+ assert_equal true, project.is_public?
+ assert_nil project.parent
+ end
+
+ should "accept post with parent" do
+ post :add, :project => { :name => "blog",
+ :description => "weblog",
+ :identifier => "blog",
+ :is_public => 1,
+ :custom_field_values => { '3' => 'Beta' },
+ :parent_id => 1
+ }
+ assert_redirected_to '/projects/blog/settings'
+
+ project = Project.find_by_name('blog')
+ assert_kind_of Project, project
+ assert_equal Project.find(1), project.parent
+ end
+ end
- project = Project.find_by_name('blog')
- assert_kind_of Project, project
- assert_equal 'weblog', project.description
- assert_equal true, project.is_public?
- assert_nil project.parent
- end
-
- def test_post_add_subproject
- @request.session[:user_id] = 1
- post :add, :project => { :name => "blog",
- :description => "weblog",
- :identifier => "blog",
- :is_public => 1,
- :custom_field_values => { '3' => 'Beta' },
- :parent_id => 1
- }
- assert_redirected_to '/projects/blog/settings'
+ context "by non-admin user with add_project permission" do
+ setup do
+ Role.non_member.add_permission! :add_project
+ @request.session[:user_id] = 9
+ end
+
+ should "accept get" do
+ get :add
+ assert_response :success
+ assert_template 'add'
+ assert_no_tag :select, :attributes => {:name => 'project[parent_id]'}
+ end
+
+ should "accept post" do
+ post :add, :project => { :name => "blog",
+ :description => "weblog",
+ :identifier => "blog",
+ :is_public => 1,
+ :custom_field_values => { '3' => 'Beta' }
+ }
+
+ assert_redirected_to '/projects/blog/settings'
+
+ project = Project.find_by_name('blog')
+ assert_kind_of Project, project
+ assert_equal 'weblog', project.description
+ assert_equal true, project.is_public?
+
+ # User should be added as a project member
+ assert User.find(9).member_of?(project)
+ assert_equal 1, project.members.size
+ end
+
+ should "fail with parent_id" do
+ assert_no_difference 'Project.count' do
+ post :add, :project => { :name => "blog",
+ :description => "weblog",
+ :identifier => "blog",
+ :is_public => 1,
+ :custom_field_values => { '3' => 'Beta' },
+ :parent_id => 1
+ }
+ end
+ assert_response :success
+ project = assigns(:project)
+ assert_kind_of Project, project
+ assert_not_nil project.errors.on(:parent_id)
+ end
+ end
- project = Project.find_by_name('blog')
- assert_kind_of Project, project
- assert_equal Project.find(1), project.parent
- end
-
- def test_post_add_by_non_admin
- @request.session[:user_id] = 2
- post :add, :project => { :name => "blog",
- :description => "weblog",
- :identifier => "blog",
- :is_public => 1,
- :custom_field_values => { '3' => 'Beta' }
- }
- assert_redirected_to '/projects/blog/settings'
-
- project = Project.find_by_name('blog')
- assert_kind_of Project, project
- assert_equal 'weblog', project.description
- assert_equal true, project.is_public?
-
- # User should be added as a project member
- assert User.find(2).member_of?(project)
- assert_equal 1, project.members.size
+ context "by non-admin user with add_subprojects permission" do
+ setup do
+ Role.find(1).remove_permission! :add_project
+ Role.find(1).add_permission! :add_subprojects
+ @request.session[:user_id] = 2
+ end
+
+ should "accept get" do
+ get :add, :parent_id => 'ecookbook'
+ assert_response :success
+ assert_template 'add'
+ # parent project selected
+ assert_tag :select, :attributes => {:name => 'project[parent_id]'},
+ :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
+ # no empty value
+ assert_no_tag :select, :attributes => {:name => 'project[parent_id]'},
+ :child => {:tag => 'option', :attributes => {:value => ''}}
+ end
+
+ should "accept post with parent_id" do
+ post :add, :project => { :name => "blog",
+ :description => "weblog",
+ :identifier => "blog",
+ :is_public => 1,
+ :custom_field_values => { '3' => 'Beta' },
+ :parent_id => 1
+ }
+ assert_redirected_to '/projects/blog/settings'
+ project = Project.find_by_name('blog')
+ end
+
+ should "fail without parent_id" do
+ assert_no_difference 'Project.count' do
+ post :add, :project => { :name => "blog",
+ :description => "weblog",
+ :identifier => "blog",
+ :is_public => 1,
+ :custom_field_values => { '3' => 'Beta' }
+ }
+ end
+ assert_response :success
+ project = assigns(:project)
+ assert_kind_of Project, project
+ assert_not_nil project.errors.on(:parent_id)
+ end
+
+ should "fail with unauthorized parent_id" do
+ assert !User.find(2).member_of?(Project.find(6))
+ assert_no_difference 'Project.count' do
+ post :add, :project => { :name => "blog",
+ :description => "weblog",
+ :identifier => "blog",
+ :is_public => 1,
+ :custom_field_values => { '3' => 'Beta' },
+ :parent_id => 6
+ }
+ end
+ assert_response :success
+ project = assigns(:project)
+ assert_kind_of Project, project
+ assert_not_nil project.errors.on(:parent_id)
+ end
+ end
end
def test_show_routing
diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb
index 0633c95de..e61ab03fc 100644
--- a/test/unit/project_test.rb
+++ b/test/unit/project_test.rb
@@ -282,7 +282,7 @@ class ProjectTest < ActiveSupport::TestCase
user = User.find(9)
assert user.memberships.empty?
User.current = user
- assert Project.new.allowed_parents.empty?
+ assert Project.new.allowed_parents.compact.empty?
end
def test_users_by_role