Allow non admin users to add subprojects (#2963).
Subprojects can be added to the projects for which the user has add_project permission. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3059 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
ea9a7c20e6
commit
534ce51154
@ -75,7 +75,7 @@ class ProjectsController < ApplicationController
|
|||||||
else
|
else
|
||||||
@project.enabled_module_names = params[:enabled_modules]
|
@project.enabled_module_names = params[:enabled_modules]
|
||||||
if @project.save
|
if @project.save
|
||||||
@project.set_parent!(params[:project]['parent_id']) if User.current.admin? && params[:project].has_key?('parent_id')
|
@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
|
# Add current user as a project member if he is not admin
|
||||||
unless User.current.admin?
|
unless User.current.admin?
|
||||||
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
|
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
|
||||||
@ -106,7 +106,7 @@ class ProjectsController < ApplicationController
|
|||||||
@project = Project.new(params[:project])
|
@project = Project.new(params[:project])
|
||||||
@project.enabled_module_names = params[:enabled_modules]
|
@project.enabled_module_names = params[:enabled_modules]
|
||||||
if @project.copy(@source_project, :only => params[:only])
|
if @project.copy(@source_project, :only => params[:only])
|
||||||
@project.set_parent!(params[:project]['parent_id']) if User.current.admin? && params[:project].has_key?('parent_id')
|
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||||
flash[:notice] = l(:notice_successful_create)
|
flash[:notice] = l(:notice_successful_create)
|
||||||
redirect_to :controller => 'admin', :action => 'projects'
|
redirect_to :controller => 'admin', :action => 'projects'
|
||||||
end
|
end
|
||||||
@ -158,7 +158,7 @@ class ProjectsController < ApplicationController
|
|||||||
if request.post?
|
if request.post?
|
||||||
@project.attributes = params[:project]
|
@project.attributes = params[:project]
|
||||||
if @project.save
|
if @project.save
|
||||||
@project.set_parent!(params[:project]['parent_id']) if User.current.admin? && params[:project].has_key?('parent_id')
|
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||||
flash[:notice] = l(:notice_successful_update)
|
flash[:notice] = l(:notice_successful_update)
|
||||||
redirect_to :action => 'settings', :id => @project
|
redirect_to :action => 'settings', :id => @project
|
||||||
else
|
else
|
||||||
|
@ -36,7 +36,7 @@ module ProjectsHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def parent_project_select_tag(project)
|
def parent_project_select_tag(project)
|
||||||
options = '<option></option>' + project_tree_options_for_select(project.possible_parents, :selected => project.parent)
|
options = '<option></option>' + project_tree_options_for_select(project.allowed_parents, :selected => project.parent)
|
||||||
content_tag('select', options, :name => 'project[parent_id]')
|
content_tag('select', options, :name => 'project[parent_id]')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -148,14 +148,16 @@ class Project < ActiveRecord::Base
|
|||||||
else
|
else
|
||||||
statements << "1=0"
|
statements << "1=0"
|
||||||
if user.logged?
|
if user.logged?
|
||||||
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if Role.non_member.allowed_to?(permission)
|
if Role.non_member.allowed_to?(permission) && !options[:member]
|
||||||
|
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}"
|
||||||
|
end
|
||||||
allowed_project_ids = user.memberships.select {|m| m.roles.detect {|role| role.allowed_to?(permission)}}.collect {|m| m.project_id}
|
allowed_project_ids = user.memberships.select {|m| m.roles.detect {|role| role.allowed_to?(permission)}}.collect {|m| m.project_id}
|
||||||
statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any?
|
statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any?
|
||||||
elsif Role.anonymous.allowed_to?(permission)
|
|
||||||
# anonymous user allowed on public project
|
|
||||||
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}"
|
|
||||||
else
|
else
|
||||||
# anonymous user is not authorized
|
if Role.anonymous.allowed_to?(permission) && !options[:member]
|
||||||
|
# anonymous user allowed on public project
|
||||||
|
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
statements.empty? ? base_statement : "((#{base_statement}) AND (#{statements.join(' OR ')}))"
|
statements.empty? ? base_statement : "((#{base_statement}) AND (#{statements.join(' OR ')}))"
|
||||||
@ -253,8 +255,34 @@ class Project < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Returns an array of projects the project can be moved to
|
# Returns an array of projects the project can be moved to
|
||||||
def possible_parents
|
# by the current user
|
||||||
@possible_parents ||= (Project.active.find(:all) - self_and_descendants)
|
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)
|
||||||
|
unless parent.nil? || @allowed_parents.empty? || @allowed_parents.include?(parent)
|
||||||
|
@allowed_parents << parent
|
||||||
|
end
|
||||||
|
@allowed_parents
|
||||||
|
end
|
||||||
|
|
||||||
|
# Sets the parent of the project with authorization check
|
||||||
|
def set_allowed_parent!(p)
|
||||||
|
unless p.nil? || p.is_a?(Project)
|
||||||
|
if p.to_s.blank?
|
||||||
|
p = nil
|
||||||
|
else
|
||||||
|
p = Project.find_by_id(p)
|
||||||
|
return false unless p
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if p.nil?
|
||||||
|
if !new_record? && allowed_parents.empty?
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
elsif !allowed_parents.include?(p)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
set_parent!(p)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sets the parent of the project
|
# Sets the parent of the project
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<!--[form:project]-->
|
<!--[form:project]-->
|
||||||
<p><%= f.text_field :name, :required => true %><br /><em><%= l(:text_caracters_maximum, 30) %></em></p>
|
<p><%= f.text_field :name, :required => true %><br /><em><%= l(:text_caracters_maximum, 30) %></em></p>
|
||||||
|
|
||||||
<% if User.current.admin? && !@project.possible_parents.empty? %>
|
<% unless @project.allowed_parents.empty? %>
|
||||||
<p><label><%= l(:field_parent) %></label><%= parent_project_select_tag(@project) %></p>
|
<p><label><%= l(:field_parent) %></label><%= parent_project_select_tag(@project) %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
@ -117,6 +117,23 @@ class ProjectsControllerTest < ActionController::TestCase
|
|||||||
assert_kind_of Project, project
|
assert_kind_of Project, project
|
||||||
assert_equal 'weblog', project.description
|
assert_equal 'weblog', project.description
|
||||||
assert_equal true, project.is_public?
|
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'
|
||||||
|
|
||||||
|
project = Project.find_by_name('blog')
|
||||||
|
assert_kind_of Project, project
|
||||||
|
assert_equal Project.find(1), project.parent
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_post_add_by_non_admin
|
def test_post_add_by_non_admin
|
||||||
|
@ -26,6 +26,7 @@ class ProjectTest < ActiveSupport::TestCase
|
|||||||
def setup
|
def setup
|
||||||
@ecookbook = Project.find(1)
|
@ecookbook = Project.find(1)
|
||||||
@ecookbook_sub1 = Project.find(3)
|
@ecookbook_sub1 = Project.find(3)
|
||||||
|
User.current = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
should_validate_presence_of :name
|
should_validate_presence_of :name
|
||||||
@ -236,6 +237,14 @@ class ProjectTest < ActiveSupport::TestCase
|
|||||||
assert_equal [5, 6, 3, 4], d.collect(&:id)
|
assert_equal [5, 6, 3, 4], d.collect(&:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_allowed_parents_should_be_empty_for_non_member_user
|
||||||
|
Role.non_member.add_permission!(:add_project)
|
||||||
|
user = User.find(9)
|
||||||
|
assert user.memberships.empty?
|
||||||
|
User.current = user
|
||||||
|
assert Project.new.allowed_parents.empty?
|
||||||
|
end
|
||||||
|
|
||||||
def test_users_by_role
|
def test_users_by_role
|
||||||
users_by_role = Project.find(1).users_by_role
|
users_by_role = Project.find(1).users_by_role
|
||||||
assert_kind_of Hash, users_by_role
|
assert_kind_of Hash, users_by_role
|
||||||
|
Loading…
x
Reference in New Issue
Block a user