diff --git a/app/models/issue.rb b/app/models/issue.rb index 02aaff33be..8a61447143 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -284,13 +284,18 @@ class Issue < ActiveRecord::Base # Copies attributes from another issue, arg can be an id or an Issue def copy_from(arg, options={}) issue = arg.is_a?(Issue) ? arg : Issue.visible.find(arg) + # core fields + not_copyable = %w[id root_id parent_id lft rgt created_on updated_on status_id closed_on] + not_copyable += issue.disabled_core_fields + not_copyable += issue.read_only_attribute_names(User.current) + # For a new issue project and tracker should be copied regardless of workflow + if new_record? + not_copyable -= %w[project_id tracker_id] + end self.attributes = - issue.attributes.dup.except( - "id", "root_id", "parent_id", "lft", "rgt", - "created_on", "updated_on", "status_id", "closed_on" - ) + issue.attributes.dup.except(*not_copyable) self.custom_field_values = - issue.custom_field_values.inject({}) do |h, v| + issue.editable_custom_field_values(User.current).inject({}) do |h, v| h[v.custom_field_id] = v.value h end diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index a0d9485c22..f593984b0f 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -3427,4 +3427,67 @@ class IssueTest < ActiveSupport::TestCase r = Issue.like('issue today') assert_include Issue.find(7), r end + + def test_copy_issue_should_copy_only_editable_attributes + User.current = User.find(2) + issue_orig = Issue.find(11) + cf = IssueCustomField.find(6) + cv = CustomValue.create!(:custom_field => cf, :customized => issue_orig, :value => 12.34) + + WorkflowPermission.delete_all + # status new + WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, + :old_status_id => 1, + :author => false, :assignee => false, + :field_name => 'fixed_version_id', :rule => 'readonly') + WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, + :old_status_id => 1, + :author => false, :assignee => false, + :field_name => cf.id, :rule => 'readonly') + # closed + WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, + :old_status_id => 5, + :author => false, :assignee => false, + :field_name => 'fixed_version_id', :rule => 'readonly') + WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, + :old_status_id => 5, + :author => false, :assignee => false, + :field_name => cf.id, :rule => 'readonly') + + # user cannot change field + assert_not issue_orig.safe_attribute?('fixed_version_id') + assert_not_nil issue_orig.fixed_version_id + # cf_6 is read only + assert issue_orig.read_only_attribute_names(User.current).include?(cf.id.to_s) + assert_equal cv.to_s, issue_orig.custom_field_value(cf.id) + + issue_copy = Issue.new.copy_from issue_orig + # field was not copied + assert_nil issue_copy.fixed_version_id + assert_empty issue_copy.custom_field_value(cf.id) + # still can't change field + assert_not issue_copy.safe_attribute?('fixed_version_id') + assert issue_copy.read_only_attribute_names(User.current).include?(cf.id.to_s) + end + + def test_copy_issue_from_should_ignore_disabled_rules_for_project_and_tracker + User.current = User.find(2) + source_issue = Issue.find(1) + icf = IssueCustomField.generate!(:tracker_ids => [1], :visible => true, :role_ids => [1], :is_for_all => false, :project_ids => [1]) + + # Disable changing Project for role Manager + WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, + :old_status_id => 1, + :author => false, :assignee => false, + :field_name => 'project_id', :rule => 'readonly') + + CustomValue.create!(:custom_field => icf, :customized => source_issue, :value => 'test string') + + + new_issue = Issue.new.copy_from(source_issue) + # custom values were copied + assert_not_empty new_issue.custom_field_values + # copied values are equal + assert_equal source_issue.custom_field_value(icf.id), new_issue.custom_field_value(icf.id) + end end