git-svn-id: http://svn.redmine.org/redmine/trunk@15464 e93f8b46-1217-0410-a6f0-8f06a7374b81tags/3.4.0
@@ -467,7 +467,13 @@ class IssuesController < ApplicationController | |||
if @issue.project | |||
@issue.tracker ||= @issue.allowed_target_trackers.first | |||
if @issue.tracker.nil? | |||
render_error l(:error_no_tracker_in_project) | |||
if @issue.project.trackers.any? | |||
# None of the project trackers is allowed to the user | |||
render_error :message => l(:error_no_tracker_allowed_for_new_issue_in_project), :status => 403 | |||
else | |||
# Project has no trackers | |||
render_error l(:error_no_tracker_in_project) | |||
end | |||
return false | |||
end | |||
if @issue.status.nil? |
@@ -1368,16 +1368,27 @@ class Issue < ActiveRecord::Base | |||
# Returns a scope of trackers that user can assign the issue to | |||
def allowed_target_trackers(user=User.current) | |||
if project | |||
self.class.allowed_target_trackers(project, user, tracker_id_was) | |||
else | |||
Tracker.none | |||
end | |||
self.class.allowed_target_trackers(project, user, tracker_id_was) | |||
end | |||
# Returns a scope of trackers that user can assign project issues to | |||
def self.allowed_target_trackers(project, user=User.current, current_tracker=nil) | |||
project.trackers.sorted | |||
if project | |||
scope = project.trackers.sorted | |||
unless user.admin? | |||
roles = user.roles_for_project(project).select {|r| r.has_permission?(:add_issues)} | |||
unless roles.any? {|r| r.permissions_all_trackers?(:add_issues)} | |||
tracker_ids = roles.map {|r| r.permissions_tracker_ids(:add_issues)}.flatten.uniq | |||
if current_tracker | |||
tracker_ids << current_tracker | |||
end | |||
scope = scope.where(:id => tracker_ids) | |||
end | |||
end | |||
scope | |||
else | |||
Tracker.none | |||
end | |||
end | |||
private |
@@ -37,7 +37,7 @@ class IssueImport < Import | |||
# Returns a scope of trackers that user is allowed to | |||
# import issue to | |||
def allowed_target_trackers | |||
project.trackers | |||
Issue.allowed_target_trackers(project, user) | |||
end | |||
def tracker |
@@ -73,6 +73,7 @@ class Role < ActiveRecord::Base | |||
acts_as_positioned :scope => :builtin | |||
serialize :permissions, ::Role::PermissionsAttributeCoder | |||
store :settings, :accessors => [:permissions_all_trackers, :permissions_tracker_ids] | |||
attr_protected :builtin | |||
validates_presence_of :name | |||
@@ -188,6 +189,56 @@ class Role < ActiveRecord::Base | |||
setable_permissions | |||
end | |||
def permissions_tracker_ids(*args) | |||
if args.any? | |||
Array(permissions_tracker_ids[args.first.to_s]).map(&:to_i) | |||
else | |||
super || {} | |||
end | |||
end | |||
def permissions_tracker_ids=(arg) | |||
h = arg.to_hash | |||
h.values.each {|v| v.reject!(&:blank?)} | |||
super(h) | |||
end | |||
# Returns true if tracker_id belongs to the list of | |||
# trackers for which permission is given | |||
def permissions_tracker_ids?(permission, tracker_id) | |||
permissions_tracker_ids(permission).include?(tracker_id) | |||
end | |||
def permissions_all_trackers | |||
super || {} | |||
end | |||
def permissions_all_trackers=(arg) | |||
super(arg.to_hash) | |||
end | |||
# Returns true if permission is given for all trackers | |||
def permissions_all_trackers?(permission) | |||
permissions_all_trackers[permission.to_s].to_s != '0' | |||
end | |||
# Sets the trackers that are allowed for a permission. | |||
# tracker_ids can be an array of tracker ids or :all for | |||
# no restrictions. | |||
# | |||
# Examples: | |||
# role.set_permission_trackers :add_issues, [1, 3] | |||
# role.set_permission_trackers :add_issues, :all | |||
def set_permission_trackers(permission, tracker_ids) | |||
h = {permission.to_s => (tracker_ids == :all ? '1' : '0')} | |||
self.permissions_all_trackers = permissions_all_trackers.merge(h) | |||
h = {permission.to_s => (tracker_ids == :all ? [] : tracker_ids)} | |||
self.permissions_tracker_ids = permissions_tracker_ids.merge(h) | |||
self | |||
end | |||
# Find all the roles that can be given to a project member | |||
def self.find_all_givable | |||
Role.givable.to_a |
@@ -62,6 +62,50 @@ | |||
<%= hidden_field_tag 'role[permissions][]', '' %> | |||
</div> | |||
<div id="role-permissions-trackers"> | |||
<h3><%= l(:label_issue_tracking) %></h3> | |||
<% permissions = %w(add_issues) %> | |||
<table class="list"> | |||
<thead> | |||
<tr> | |||
<th><%= l(:label_tracker) %></th> | |||
<% permissions.each do |permission| %> | |||
<th><%= l("permission_#{permission}") %></th> | |||
<% end %> | |||
</thead> | |||
<tbody> | |||
<tr> | |||
<td class="name"><b><%= l(:label_tracker_all) %></b></td> | |||
<% permissions.each do |permission| %> | |||
<td> | |||
<%= hidden_field_tag "role[permissions_all_trackers][#{permission}]", '0', :id => nil %> | |||
<%= check_box_tag "role[permissions_all_trackers][#{permission}]", | |||
'1', | |||
@role.permissions_all_trackers?(permission), | |||
:data => {:disables => ".#{permission}_tracker"} %> | |||
</td> | |||
<% end %> | |||
</tr> | |||
<% Tracker.sorted.all.each do |tracker| %> | |||
<tr> | |||
<td class="name"><%= tracker.name %></td> | |||
<% permissions.each do |permission| %> | |||
<td><%= check_box_tag "role[permissions_tracker_ids][#{permission}][]", | |||
tracker.id, | |||
@role.permissions_tracker_ids?(permission, tracker.id), | |||
:class => "#{permission}_tracker", | |||
:id => "role_permissions_tracker_ids_add_issues_#{tracker.id}" %></td> | |||
<% end %> | |||
</tr> | |||
<% end %> | |||
</tbody> | |||
</table> | |||
<% permissions.each do |permission| %> | |||
<%= hidden_field_tag "role[permissions_tracker_ids][#{permission}][]", '' %> | |||
<% end %> | |||
</div> | |||
<%= javascript_tag do %> | |||
$(document).ready(function(){ | |||
$("#role_permissions_manage_members").change(function(){ |
@@ -213,6 +213,7 @@ en: | |||
error_can_not_read_import_file: "An error occurred while reading the file to import" | |||
error_attachment_extension_not_allowed: "Attachment extension %{extension} is not allowed" | |||
error_ldap_bind_credentials: "Invalid LDAP Account/Password" | |||
error_no_tracker_allowed_for_new_issue_in_project: "The project doesn't have any trackers for which you can create an issue" | |||
mail_subject_lost_password: "Your %{value} password" | |||
mail_body_lost_password: 'To change your password, click on the following link:' | |||
@@ -561,6 +562,7 @@ en: | |||
label_member_plural: Members | |||
label_tracker: Tracker | |||
label_tracker_plural: Trackers | |||
label_tracker_all: All trackers | |||
label_tracker_new: New tracker | |||
label_workflow: Workflow | |||
label_issue_status: Issue status |
@@ -233,6 +233,7 @@ fr: | |||
error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier à importer" | |||
error_attachment_extension_not_allowed: "L'extension %{extension} n'est pas autorisée" | |||
error_ldap_bind_credentials: "Identifiant ou mot de passe LDAP incorrect" | |||
error_no_tracker_allowed_for_new_issue_in_project: "Le projet ne dispose d'aucun tracker sur lequel vous pouvez créer une demande" | |||
mail_subject_lost_password: "Votre mot de passe %{value}" | |||
mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :' | |||
@@ -573,6 +574,7 @@ fr: | |||
label_member_plural: Membres | |||
label_tracker: Tracker | |||
label_tracker_plural: Trackers | |||
label_tracker_all: Tous les trackers | |||
label_tracker_new: Nouveau tracker | |||
label_workflow: Workflow | |||
label_issue_status: Statut de demandes |
@@ -0,0 +1,5 @@ | |||
class AddRolesSettings < ActiveRecord::Migration | |||
def change | |||
add_column :roles, :settings, :text | |||
end | |||
end |
@@ -1864,6 +1864,31 @@ class IssuesControllerTest < ActionController::TestCase | |||
end | |||
end | |||
def test_new_should_propose_allowed_trackers | |||
role = Role.find(1) | |||
role.set_permission_trackers 'add_issues', [1, 3] | |||
role.save! | |||
@request.session[:user_id] = 2 | |||
get :new, :project_id => 1 | |||
assert_response :success | |||
assert_select 'select[name=?]', 'issue[tracker_id]' do | |||
assert_select 'option', 2 | |||
assert_select 'option[value="1"]' | |||
assert_select 'option[value="3"]' | |||
end | |||
end | |||
def test_new_without_allowed_trackers_should_respond_with_403 | |||
role = Role.find(1) | |||
role.set_permission_trackers 'add_issues', [] | |||
role.save! | |||
@request.session[:user_id] = 2 | |||
get :new, :project_id => 1 | |||
assert_response 403 | |||
end | |||
def test_new_should_preselect_default_version | |||
version = Version.generate!(:project_id => 1) | |||
Project.find(1).update_attribute :default_version_id, version.id | |||
@@ -2432,6 +2457,23 @@ class IssuesControllerTest < ActionController::TestCase | |||
assert_nil issue.custom_field_value(cf2) | |||
end | |||
def test_create_should_ignore_unallowed_trackers | |||
role = Role.find(1) | |||
role.set_permission_trackers :add_issues, [3] | |||
role.save! | |||
@request.session[:user_id] = 2 | |||
issue = new_record(Issue) do | |||
post :create, :project_id => 1, :issue => { | |||
:tracker_id => 1, | |||
:status_id => 1, | |||
:subject => 'Test' | |||
} | |||
assert_response 302 | |||
end | |||
assert_equal 3, issue.tracker_id | |||
end | |||
def test_post_create_with_watchers | |||
@request.session[:user_id] = 2 | |||
ActionMailer::Base.deliveries.clear |
@@ -132,6 +132,22 @@ class RolesControllerTest < ActionController::TestCase | |||
assert_equal [:edit_project], role.permissions | |||
end | |||
def test_update_trackers_permissions | |||
put :update, :id => 1, :role => { | |||
:permissions_all_trackers => {'add_issues' => '0'}, | |||
:permissions_tracker_ids => {'add_issues' => ['1', '3', '']} | |||
} | |||
assert_redirected_to '/roles' | |||
role = Role.find(1) | |||
assert_equal({'add_issues' => '0'}, role.permissions_all_trackers) | |||
assert_equal({'add_issues' => ['1', '3']}, role.permissions_tracker_ids) | |||
assert_equal false, role.permissions_all_trackers?(:add_issues) | |||
assert_equal [1, 3], role.permissions_tracker_ids(:add_issues).sort | |||
end | |||
def test_update_with_failure | |||
put :update, :id => 1, :role => {:name => ''} | |||
assert_response :success |
@@ -1438,6 +1438,91 @@ class IssueTest < ActiveSupport::TestCase | |||
assert_not_include project, Issue.allowed_target_projects(User.find(1)) | |||
end | |||
def test_allowed_target_trackers_with_one_role_allowed_on_all_trackers | |||
user = User.generate! | |||
role = Role.generate! | |||
role.add_permission! :add_issues | |||
role.set_permission_trackers :add_issues, :all | |||
role.save! | |||
User.add_to_project(user, Project.find(1), role) | |||
assert_equal [1, 2, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
end | |||
def test_allowed_target_trackers_with_one_role_allowed_on_some_trackers | |||
user = User.generate! | |||
role = Role.generate! | |||
role.add_permission! :add_issues | |||
role.set_permission_trackers :add_issues, [1, 3] | |||
role.save! | |||
User.add_to_project(user, Project.find(1), role) | |||
assert_equal [1, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
end | |||
def test_allowed_target_trackers_with_two_roles_allowed_on_some_trackers | |||
user = User.generate! | |||
role1 = Role.generate! | |||
role1.add_permission! :add_issues | |||
role1.set_permission_trackers :add_issues, [1] | |||
role1.save! | |||
role2 = Role.generate! | |||
role2.add_permission! :add_issues | |||
role2.set_permission_trackers :add_issues, [3] | |||
role2.save! | |||
User.add_to_project(user, Project.find(1), [role1, role2]) | |||
assert_equal [1, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
end | |||
def test_allowed_target_trackers_with_two_roles_allowed_on_all_trackers_and_some_trackers | |||
user = User.generate! | |||
role1 = Role.generate! | |||
role1.add_permission! :add_issues | |||
role1.set_permission_trackers :add_issues, :all | |||
role1.save! | |||
role2 = Role.generate! | |||
role2.add_permission! :add_issues | |||
role2.set_permission_trackers :add_issues, [1, 3] | |||
role2.save! | |||
User.add_to_project(user, Project.find(1), [role1, role2]) | |||
assert_equal [1, 2, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
end | |||
def test_allowed_target_trackers_should_not_consider_roles_without_add_issues_permission | |||
user = User.generate! | |||
role1 = Role.generate! | |||
role1.remove_permission! :add_issues | |||
role1.set_permission_trackers :add_issues, :all | |||
role1.save! | |||
role2 = Role.generate! | |||
role2.add_permission! :add_issues | |||
role2.set_permission_trackers :add_issues, [1, 3] | |||
role2.save! | |||
User.add_to_project(user, Project.find(1), [role1, role2]) | |||
assert_equal [1, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
end | |||
def test_allowed_target_trackers_without_project_should_be_empty | |||
issue = Issue.new | |||
assert_nil issue.project | |||
assert_equal [], issue.allowed_target_trackers(User.find(2)).ids | |||
end | |||
def test_allowed_target_trackers_should_include_current_tracker | |||
user = User.generate! | |||
role = Role.generate! | |||
role.add_permission! :add_issues | |||
role.set_permission_trackers :add_issues, [3] | |||
role.save! | |||
User.add_to_project(user, Project.find(1), role) | |||
issue = Issue.generate!(:project => Project.find(1), :tracker => Tracker.find(1)) | |||
assert_equal [1, 3], issue.allowed_target_trackers(user).ids.sort | |||
end | |||
def test_move_to_another_project_with_same_category | |||
issue = Issue.find(1) | |||
issue.project = Project.find(2) |