From 62c83bdd2e1b06fcd873ba6d638c0bf59e390958 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Thu, 24 Dec 2009 16:18:15 +0000 Subject: [PATCH] Adds a 'Add subprojects' permission. * 'Add project' permission will let user create a root project * 'Add subprojects' permission will let project members create subprojects git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3238 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/projects_controller.rb | 21 +- app/helpers/projects_helper.rb | 11 +- app/models/project.rb | 6 +- app/views/projects/_form.rhtml | 2 +- app/views/projects/show.rhtml | 6 + config/locales/bg.yml | 2 + config/locales/bs.yml | 2 + config/locales/ca.yml | 2 + config/locales/cs.yml | 2 + config/locales/da.yml | 2 + config/locales/de.yml | 2 + config/locales/el.yml | 2 + config/locales/en.yml | 2 + config/locales/es.yml | 2 + config/locales/fi.yml | 2 + config/locales/fr.yml | 2 + config/locales/gl.yml | 2 + config/locales/he.yml | 2 + config/locales/hu.yml | 2 + config/locales/id.yml | 2 + config/locales/it.yml | 2 + config/locales/ja.yml | 2 + config/locales/ko.yml | 2 + config/locales/lt.yml | 2 + config/locales/nl.yml | 2 + config/locales/no.yml | 2 + config/locales/pl.yml | 2 + config/locales/pt-BR.yml | 2 + config/locales/pt.yml | 2 + config/locales/ro.yml | 2 + config/locales/ru.yml | 2 + config/locales/sk.yml | 2 + config/locales/sl.yml | 2 + config/locales/sr.yml | 2 + config/locales/sv.yml | 2 + config/locales/th.yml | 2 + config/locales/tr.yml | 2 + config/locales/uk.yml | 2 + config/locales/vi.yml | 2 + config/locales/zh-TW.yml | 2 + config/locales/zh.yml | 2 + lib/redmine.rb | 1 + test/functional/projects_controller_test.rb | 218 ++++++++++++++------ test/unit/project_test.rb | 2 +- 44 files changed, 269 insertions(+), 70 deletions(-) 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