redmine_changeable_author_r21799.patch

Go MAEDA, 2022-09-05 03:52

Download (12.5 KB)

View differences:

app/helpers/issues_helper.rb
534 534
        old_value = format_date(detail.old_value.to_date) if detail.old_value
535 535

  
536 536
      when 'project_id', 'status_id', 'tracker_id', 'assigned_to_id',
537
            'priority_id', 'category_id', 'fixed_version_id'
537
            'priority_id', 'category_id', 'fixed_version_id', 'author_id'
538 538
        value = find_name_by_reflection(field, detail.value)
539 539
        old_value = find_name_by_reflection(field, detail.old_value)
540 540

  
......
772 772
      issue.allowed_target_projects(User.current)
773 773
    end
774 774
  end
775

  
776
  def author_options_for_select(issue, project)
777
    users = issue.assignable_users.select {|m| m.is_a?(User) && m.allowed_to?(:add_issues, project) }
778

  
779
    if issue.new_record?
780
      if users.include?(User.current)
781
        principals_options_for_select(users, issue.author)
782
      else
783
        principals_options_for_select([User.current] + users)
784
      end
785
    elsif issue.persisted?
786
      if users.include?(issue.author)
787
        principals_options_for_select(users, issue.author)
788
      else
789
        author_principal = Principal.find(issue.author_id)
790
        principals_options_for_select([author_principal] + users, author_principal)
791
      end
792
    end
793
  end
775 794
end
app/models/issue.rb
111 111
  before_validation :clear_disabled_fields
112 112
  before_save :close_duplicates, :update_done_ratio_from_issue_status,
113 113
              :force_updated_on_change, :update_closed_on
114
  before_create :set_author_journal
114 115
  after_save do |issue|
115 116
    if !issue.saved_change_to_id? && issue.saved_change_to_project_id?
116 117
      issue.send :after_project_change
......
519 520
  safe_attributes(
520 521
    'deleted_attachment_ids',
521 522
    :if => lambda {|issue, user| issue.attachments_deletable?(user)})
523
  safe_attributes(
524
    'author_id',
525
    :if => lambda {|issue, user| user.allowed_to?(:change_issue_author, issue.project)})
522 526

  
523 527
  def safe_attribute_names(user=nil)
524 528
    names = super
......
2022 2026
    end
2023 2027
  end
2024 2028

  
2029
  def set_author_journal
2030
    return unless new_record?
2031
    return unless self.author.present? && User.current.present? && self.author != User.current
2032

  
2033
    self.init_journal(User.current)
2034
    self.current_journal.__send__(:add_attribute_detail, 'author_id', User.current.id, self.author.id)
2035
  end
2036

  
2025 2037
  def send_notification
2026 2038
    if notify? && Setting.notified_events.include?('issue_added')
2027 2039
      Mailer.deliver_issue_add(self)
app/views/issues/_attributes.html.erb
3 3
<div class="splitcontent">
4 4
<div class="splitcontentleft">
5 5
<% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %>
6
<% if User.current.allowed_to?(:change_issue_author, @project) %>
7
  <p><%= f.select :author_id, author_options_for_select(@issue, @project), :include_blank => false, :required => true %></p>
8
<% end %>
6 9
<p>
7 10
  <%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), {:required => true},
8 11
                :onchange => "updateIssueFrom('#{escape_javascript(update_issue_form_path(@project, @issue))}', this)" %>
config/locales/en.yml
540 540
  permission_view_private_notes: View private notes
541 541
  permission_set_notes_private: Set notes as private
542 542
  permission_delete_issues: Delete issues
543
  permission_change_issue_author: Change issue author
543 544
  permission_manage_public_queries: Manage public queries
544 545
  permission_save_queries: Save queries
545 546
  permission_view_gantt: View gantt chart
lib/redmine/preparation.rb
72 72
          map.permission :view_private_notes, {}, :read => true, :require => :member
73 73
          map.permission :set_notes_private, {}, :require => :member
74 74
          map.permission :delete_issues, {:issues => :destroy}, :require => :member
75
          map.permission :change_issue_author, {:issues => [:edit, :update]}
75 76
          map.permission :mention_users, {}
76 77
          # Watchers
77 78
          map.permission :view_issue_watchers, {}, :read => true
test/functional/issues_controller_test.rb
8286 8286
  end
8287 8287

  
8288 8288
  def test_destroy_child_issue
8289
    User.current = User.find(1)
8289 8290
    parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
8290 8291
    child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
8291 8292
    assert child.is_descendant_of?(parent.reload)
test/functional/versions_controller_test.rb
103 103
  end
104 104

  
105 105
  def test_index_should_show_issue_assignee
106
    User.current = User.find_by_login('jsmith')
106 107
    with_settings :gravatar_enabled => '1' do
107 108
      Issue.generate!(:project_id => 3, :fixed_version_id => 4, :assigned_to => User.find_by_login('jsmith'))
108 109
      Issue.generate!(:project_id => 3, :fixed_version_id => 4)
test/helpers/issues_helper_test.rb
465 465
    assert_include "<a href=\"/issues?issue_id=#{open_issue.id}%2C#{closed_issue.id}&amp;set_filter=true&amp;status_id=o\">1 open</a>", html
466 466
    assert_include "<a href=\"/issues?issue_id=#{open_issue.id}%2C#{closed_issue.id}&amp;set_filter=true&amp;status_id=c\">1 closed</a>", html
467 467
  end
468

  
469
  def test_author_options_for_select_if_new_record_and_users_includes_current_user
470
    User.current = User.find(2)
471
    issue = Issue.new(project_id: 1)
472
    assignable_users = [User.find(3), User.find(2)]
473

  
474
    assert_includes assignable_users, User.current
475
    assert_equal(
476
      principals_options_for_select(assignable_users, nil),
477
      author_options_for_select(issue, issue.project))
478
  end
479

  
480
  def test_author_options_for_select_if_new_record_and_users_not_includes_current_user
481
    User.current = User.find(1)
482
    issue = Issue.new(project_id: 1)
483
    assignable_users = [User.find(3), User.find(2)]
484
    assert_not_includes assignable_users, User.current
485

  
486
    assert_equal(
487
      principals_options_for_select([User.current] + assignable_users, nil),
488
      author_options_for_select(issue, issue.project))
489
  end
490

  
491
  def test_author_options_for_select_if_persisted_record_and_users_includes_author
492
    User.current = User.find(2)
493
    issue = Issue.find(1)
494
    issue.update(author_id: 2)
495
    assignable_users = [User.find(3), User.find(2)]
496

  
497
    assert_includes assignable_users, issue.author
498
    assert_equal(
499
      principals_options_for_select(assignable_users, issue.author),
500
      author_options_for_select(issue, issue.project))
501
  end
502

  
503
  def test_author_options_for_select_if_persisted_record_and_users_not_includes_author
504
    User.current = User.find(2)
505
    issue = Issue.find(1)
506
    issue.update(author_id: 1)
507
    assignable_users = [User.find(3), User.find(2)]
508

  
509
    assert_not_includes assignable_users, issue.author
510
    assert_equal(
511
      principals_options_for_select([User.find(1)] + assignable_users, issue.author),
512
      author_options_for_select(issue, issue.project))
513
  end
514

  
515
  def test_author_options_for_select_if_persisted_record_and_author_is_anonymous
516
    User.current = User.find(2)
517
    issue = Issue.find(1)
518
    issue.update(author_id: User.anonymous.id)
519
    assignable_users = [User.find(3), User.find(2)]
520

  
521
    assert_not_includes assignable_users, issue.author
522
    assert_equal(
523
      principals_options_for_select([User.anonymous] + assignable_users, issue.author),
524
      author_options_for_select(issue, issue.project))
525
  end
468 526
end
test/helpers/journals_helper_test.rb
22 22
class JournalsHelperTest < Redmine::HelperTest
23 23
  include JournalsHelper
24 24

  
25
  fixtures :projects, :trackers, :issue_statuses, :issues, :journals,
25
  fixtures :projects, :trackers, :issue_statuses, :issues, :journals, :journal_details,
26 26
           :enumerations, :issue_categories,
27 27
           :projects_trackers,
28 28
           :users, :roles, :member_roles, :members,
test/object_helpers.rb
95 95
    issue.project ||= Project.find(1)
96 96
    issue.tracker ||= issue.project.trackers.first
97 97
    issue.subject = 'Generated' if issue.subject.blank?
98
    issue.author ||= User.find(2)
98
    issue.author ||= (User.current || User.find(2))
99 99
    yield issue if block_given?
100 100
    issue
101 101
  end
test/unit/issue_nested_set_test.rb
60 60
  end
61 61

  
62 62
  def test_creating_a_child_in_a_subproject_should_validate
63
    User.current = User.find(1)
63 64
    issue = Issue.generate!
64 65
    child = nil
65 66
    assert_difference 'Journal.count', 1 do
test/unit/issue_test.rb
2767 2767
  end
2768 2768

  
2769 2769
  def test_journalized_multi_custom_field
2770
    User.current = User.find(1)
2770 2771
    field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
2771 2772
                                     :is_filter => true, :is_for_all => true,
2772 2773
                                     :tracker_ids => [1],
......
3443 3444
    r = Issue.like('issue today')
3444 3445
    assert_include Issue.find(7), r
3445 3446
  end
3447

  
3448
  def test_author_should_be_changed_when_user_with_permission_change_issue_author
3449
    Role.all.each do |r|
3450
      r.add_permission! :change_issue_author
3451
    end
3452
    User.current = User.find(2)
3453

  
3454
    issue = Issue.generate!(:author => User.find(3))
3455
    assert_equal 3, issue.author_id
3456

  
3457
    issue.safe_attributes = { 'author_id' => 4 }
3458
    assert_equal 4, issue.author_id
3459
    assert_not_equal 3, issue.author_id
3460
  end
3461

  
3462
  def test_author_should_not_be_changed_when_user_without_permission_change_issue_author
3463
    Role.all.each do |r|
3464
      r.remove_permission! :change_issue_author
3465
    end
3466
    User.current = User.find(2)
3467

  
3468
    issue = Issue.generate!(:author => User.find(3))
3469
    assert_equal 3, issue.author_id
3470

  
3471
    issue.safe_attributes = { 'author_id' => 4 }
3472
    assert_not_equal 4, issue.author_id
3473
    assert_equal 3, issue.author_id
3474
  end
3475

  
3476
  def test_create_should_create_journal_if_user_other_than_current_user_is_set_as_the_author
3477
    User.current = User.find(1)
3478
    issue = nil
3479
    assert_difference 'Journal.count' do
3480
      issue = Issue.generate!(author: User.find(2))
3481
    end
3482

  
3483
    first_journal_detail = issue.journals.first.details.first
3484
    assert_equal 'author_id', first_journal_detail.prop_key
3485
    assert_equal '1', first_journal_detail.old_value
3486
    assert_equal '2', first_journal_detail.value
3487
  end
3488

  
3489
  def test_create_should_create_journal_if_current_user_is_set_as_the_author
3490
    User.current = User.find(1)
3491
    issue = nil
3492
    assert_no_difference 'Journal.count' do
3493
      issue = Issue.generate!(author: User.current)
3494
    end
3495

  
3496
    assert_not issue.journals.present?
3497
  end
3446 3498
end