redmine_changeable_author_r21387.patch

Mizuki ISHIKAWA, 2022-01-25 02:39

Download (12.6 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
109 109
  before_validation :clear_disabled_fields
110 110
  before_save :close_duplicates, :update_done_ratio_from_issue_status,
111 111
              :force_updated_on_change, :update_closed_on
112
  before_create :set_author_journal
112 113
  after_save do |issue|
113 114
    if !issue.saved_change_to_id? && issue.saved_change_to_project_id?
114 115
      issue.send :after_project_change
......
517 518
  safe_attributes(
518 519
    'deleted_attachment_ids',
519 520
    :if => lambda {|issue, user| issue.attachments_deletable?(user)})
521
  safe_attributes(
522
    'author_id',
523
    :if => lambda {|issue, user| user.allowed_to?(:change_issue_author, issue.project)})
520 524

  
521 525
  def safe_attribute_names(user=nil)
522 526
    names = super
......
2013 2017
    end
2014 2018
  end
2015 2019

  
2020
  def set_author_journal
2021
    return unless new_record?
2022
    return unless self.author.present? && User.current.present? && self.author != User.current
2023

  
2024
    self.init_journal(User.current)
2025
    self.current_journal.__send__(:add_attribute_detail, 'author_id', User.current.id, self.author.id)
2026
  end
2027

  
2016 2028
  def send_notification
2017 2029
    if notify? && Setting.notified_events.include?('issue_added')
2018 2030
      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
533 533
  permission_view_private_notes: View private notes
534 534
  permission_set_notes_private: Set notes as private
535 535
  permission_delete_issues: Delete issues
536
  permission_change_issue_author: Change issue author
536 537
  permission_manage_public_queries: Manage public queries
537 538
  permission_save_queries: Save queries
538 539
  permission_view_gantt: View gantt chart
lib/redmine/preparation.rb
71 71
          map.permission :view_private_notes, {}, :read => true, :require => :member
72 72
          map.permission :set_notes_private, {}, :require => :member
73 73
          map.permission :delete_issues, {:issues => :destroy}, :require => :member
74
          map.permission :change_issue_author, {:issues => [:edit, :update]}
74 75
          # Watchers
75 76
          map.permission :view_issue_watchers, {}, :read => true
76 77
          map.permission :add_issue_watchers, {:watchers => [:new, :create, :append, :autocomplete_for_user]}
test/functional/issues_controller_test.rb
8250 8250
  end
8251 8251

  
8252 8252
  def test_destroy_child_issue
8253
    User.current = User.find(1)
8253 8254
    parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
8254 8255
    child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
8255 8256
    assert child.is_descendant_of?(parent.reload)
test/functional/versions_controller_test.rb
100 100
  end
101 101

  
102 102
  def test_index_should_show_issue_assignee
103
    User.current = User.find_by_login('jsmith')
103 104
    with_settings :gravatar_enabled => '1' do
104 105
      Issue.generate!(:project_id => 3, :fixed_version_id => 4, :assigned_to => User.find_by_login('jsmith'))
105 106
      Issue.generate!(:project_id => 3, :fixed_version_id => 4)
test/helpers/issues_helper_test.rb
435 435
    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
436 436
    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
437 437
  end
438

  
439
  def test_author_options_for_select_if_new_record_and_users_includes_current_user
440
    User.current = User.find(2)
441
    issue = Issue.new(project_id: 1)
442
    assignable_users = [User.find(3), User.find(2)]
443

  
444
    assert_includes assignable_users, User.current
445
    assert_equal(
446
      principals_options_for_select(assignable_users, nil),
447
      author_options_for_select(issue, issue.project))
448
  end
449

  
450
  def test_author_options_for_select_if_new_record_and_users_not_includes_current_user
451
    User.current = User.find(1)
452
    issue = Issue.new(project_id: 1)
453
    assignable_users = [User.find(3), User.find(2)]
454
    assert_not_includes assignable_users, User.current
455

  
456
    assert_equal(
457
      principals_options_for_select([User.current] + assignable_users, nil),
458
      author_options_for_select(issue, issue.project))
459
  end
460

  
461
  def test_author_options_for_select_if_persisted_record_and_users_includes_author
462
    User.current = User.find(2)
463
    issue = Issue.find(1)
464
    issue.update(author_id: 2)
465
    assignable_users = [User.find(3), User.find(2)]
466

  
467
    assert_includes assignable_users, issue.author
468
    assert_equal(
469
      principals_options_for_select(assignable_users, issue.author),
470
      author_options_for_select(issue, issue.project))
471
  end
472

  
473
  def test_author_options_for_select_if_persisted_record_and_users_not_includes_author
474
    User.current = User.find(2)
475
    issue = Issue.find(1)
476
    issue.update(author_id: 1)
477
    assignable_users = [User.find(3), User.find(2)]
478

  
479
    assert_not_includes assignable_users, issue.author
480
    assert_equal(
481
      principals_options_for_select([User.find(1)] + assignable_users, issue.author),
482
      author_options_for_select(issue, issue.project))
483
  end
484

  
485
  def test_author_options_for_select_if_persisted_record_and_author_is_anonymous
486
    User.current = User.find(2)
487
    issue = Issue.find(1)
488
    issue.update(author_id: User.anonymous.id)
489
    assignable_users = [User.find(3), User.find(2)]
490

  
491
    assert_not_includes assignable_users, issue.author
492
    assert_equal(
493
      principals_options_for_select([User.anonymous] + assignable_users, issue.author),
494
      author_options_for_select(issue, issue.project))
495
  end
438 496
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
2751 2751
  end
2752 2752

  
2753 2753
  def test_journalized_multi_custom_field
2754
    User.current = User.find(1)
2754 2755
    field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
2755 2756
                                     :is_filter => true, :is_for_all => true,
2756 2757
                                     :tracker_ids => [1],
......
3427 3428
    r = Issue.like('issue today')
3428 3429
    assert_include Issue.find(7), r
3429 3430
  end
3431

  
3432
  def test_author_should_be_changed_when_user_with_permission_change_issue_author
3433
    Role.all.each do |r|
3434
      r.add_permission! :change_issue_author
3435
    end
3436
    User.current = User.find(2)
3437

  
3438
    issue = Issue.generate!(:author => User.find(3))
3439
    assert_equal 3, issue.author_id
3440

  
3441
    issue.safe_attributes = { 'author_id' => 4 }
3442
    assert_equal 4, issue.author_id
3443
    assert_not_equal 3, issue.author_id
3444
  end
3445

  
3446
  def test_author_should_not_be_changed_when_user_without_permission_change_issue_author
3447
    Role.all.each do |r|
3448
      r.remove_permission! :change_issue_author
3449
    end
3450
    User.current = User.find(2)
3451

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

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

  
3460
  def test_create_should_create_journal_if_user_other_than_current_user_is_set_as_the_author
3461
    User.current = User.find(1)
3462
    issue = nil
3463
    assert_difference 'Journal.count' do
3464
      issue = Issue.generate!(author: User.find(2))
3465
    end
3466

  
3467
    first_journal_detail = issue.journals.first.details.first
3468
    assert_equal 'author_id', first_journal_detail.prop_key
3469
    assert_equal '1', first_journal_detail.old_value
3470
    assert_equal '2', first_journal_detail.value
3471
  end
3472

  
3473
  def test_create_should_create_journal_if_current_user_is_set_as_the_author
3474
    User.current = User.find(1)
3475
    issue = nil
3476
    assert_no_difference 'Journal.count' do
3477
      issue = Issue.generate!(author: User.current)
3478
    end
3479

  
3480
    assert_not issue.journals.present?
3481
  end
3430 3482
end