##// END OF EJS Templates
Enforce issue assignee validation (#23921)....
Jean-Philippe Lang -
r15673:3a2b6c7c9653
parent child
Show More
@@ -377,6 +377,11 class Issue < ActiveRecord::Base
377 377 if category
378 378 self.category = project.issue_categories.find_by_name(category.name)
379 379 end
380 # Clear the assignee if not available in the new project for new issues (eg. copy)
381 # For existing issue, the previous assignee is still valid, so we keep it
382 if new_record? && assigned_to && !assignable_users.include?(assigned_to)
383 self.assigned_to_id = nil
384 end
380 385 # Keep the fixed_version if it's still valid in the new_project
381 386 if fixed_version && fixed_version.project != project && !project.shared_versions.include?(fixed_version)
382 387 self.fixed_version = nil
@@ -538,14 +543,7 class Issue < ActiveRecord::Base
538 543 self.status = statuses_allowed.first || default_status
539 544 end
540 545 if (u = attrs.delete('assigned_to_id')) && safe_attribute?('assigned_to_id')
541 if u.blank?
542 self.assigned_to_id = nil
543 else
544 u = u.to_i
545 if assignable_users.any?{|assignable_user| assignable_user.id == u}
546 self.assigned_to_id = u
547 end
548 end
546 self.assigned_to_id = u
549 547 end
550 548
551 549
@@ -708,6 +706,12 class Issue < ActiveRecord::Base
708 706 end
709 707 end
710 708
709 if assigned_to_id_changed? && assigned_to_id.present?
710 unless assignable_users.include?(assigned_to)
711 errors.add :assigned_to_id, :invalid
712 end
713 end
714
711 715 # Checks parent issue assignment
712 716 if @invalid_parent_issue_id.present?
713 717 errors.add :parent_issue_id, :invalid
@@ -868,7 +872,9 class Issue < ActiveRecord::Base
868 872 def assignable_users
869 873 users = project.assignable_users(tracker).to_a
870 874 users << author if author && author.active?
871 users << assigned_to if assigned_to
875 if assigned_to_id_was.present? && assignee = Principal.find_by_id(assigned_to_id_was)
876 users << assignee
877 end
872 878 users.uniq.sort
873 879 end
874 880
@@ -780,7 +780,7 class Project < ActiveRecord::Base
780 780 def copy(project, options={})
781 781 project = project.is_a?(Project) ? project : Project.find(project)
782 782
783 to_be_copied = %w(wiki versions issue_categories issues members queries boards)
783 to_be_copied = %w(members wiki versions issue_categories issues queries boards)
784 784 to_be_copied = to_be_copied & Array.wrap(options[:only]) unless options[:only].nil?
785 785
786 786 Project.transaction do
@@ -4440,7 +4440,7 class IssuesControllerTest < Redmine::ControllerTest
4440 4440 :assigned_to_id => nil),
4441 4441 Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2,
4442 4442 :priority_id => 1, :subject => 'issue 2', :author_id => 2,
4443 :assigned_to_id => 3)
4443 :assigned_to_id => 2)
4444 4444 ]
4445 4445 assert_difference 'Issue.count', issues.size do
4446 4446 post :bulk_update, :ids => issues.map(&:id), :copy => '1',
@@ -4496,7 +4496,7 class IssuesControllerTest < Redmine::ControllerTest
4496 4496 post :bulk_update, :ids => [1], :copy => '1',
4497 4497 :notes => 'Copying one issue',
4498 4498 :issue => {
4499 :project_id => '', :tracker_id => '', :assigned_to_id => '4',
4499 :project_id => '', :tracker_id => '',
4500 4500 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
4501 4501 }
4502 4502 end
@@ -689,6 +689,14 JSON
689 689 assert_select 'errors error', :text => "Subject cannot be blank"
690 690 end
691 691
692 test "PUT /issues/:id.xml with invalid assignee should return error" do
693 user = User.generate!
694 put '/issues/6.xml', {:issue => {:assigned_to_id => user.id}}, credentials('jsmith')
695
696 assert_response :unprocessable_entity
697 assert_select 'errors error', :text => "Assignee is invalid"
698 end
699
692 700 test "PUT /issues/:id.json" do
693 701 assert_difference('Journal.count') do
694 702 put '/issues/6.json',
@@ -243,14 +243,14 class IssueTest < ActiveSupport::TestCase
243 243
244 244 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
245 245 Role.anonymous.update!(:issues_visibility => 'default')
246 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
246 issue = Issue.generate!(:author => User.anonymous, :is_private => true)
247 247 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
248 248 assert !issue.visible?(User.anonymous)
249 249 end
250 250
251 251 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
252 252 assert Role.anonymous.update!(:issues_visibility => 'own')
253 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
253 issue = Issue.generate!(:author => User.anonymous, :is_private => true)
254 254 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
255 255 assert !issue.visible?(User.anonymous)
256 256 end
@@ -344,24 +344,27 class IssueTest < ActiveSupport::TestCase
344 344 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
345 345 user = User.find(8)
346 346 assert user.groups.any?
347 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
347 group = user.groups.first
348 Member.create!(:principal => group, :project_id => 1, :role_ids => [2])
348 349 Role.non_member.remove_permission!(:view_issues)
349 350
350 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 3,
351 :status_id => 1, :priority => IssuePriority.all.first,
352 :subject => 'Assignment test',
353 :assigned_to => user.groups.first,
354 :is_private => true)
355
356 Role.find(2).update! :issues_visibility => 'default'
357 issues = Issue.visible(User.find(8)).to_a
358 assert issues.any?
359 assert issues.include?(issue)
360
361 Role.find(2).update! :issues_visibility => 'own'
362 issues = Issue.visible(User.find(8)).to_a
363 assert issues.any?
364 assert_include issue, issues
351 with_settings :issue_group_assignment => '1' do
352 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 3,
353 :status_id => 1, :priority => IssuePriority.all.first,
354 :subject => 'Assignment test',
355 :assigned_to => group,
356 :is_private => true)
357
358 Role.find(2).update! :issues_visibility => 'default'
359 issues = Issue.visible(User.find(8)).to_a
360 assert issues.any?
361 assert issues.include?(issue)
362
363 Role.find(2).update! :issues_visibility => 'own'
364 issues = Issue.visible(User.find(8)).to_a
365 assert issues.any?
366 assert_include issue, issues
367 end
365 368 end
366 369
367 370 def test_visible_scope_for_member_with_limited_tracker_ids
@@ -458,6 +461,7 class IssueTest < ActiveSupport::TestCase
458 461
459 462 def test_visible_and_nested_set_scopes
460 463 user = User.generate!
464 Member.create!(:project_id => 1, :principal => user, :role_ids => [1])
461 465 parent = Issue.generate!(:assigned_to => user)
462 466 assert parent.visible?(user)
463 467 child1 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
@@ -761,13 +765,6 class IssueTest < ActiveSupport::TestCase
761 765 :project_id => 1, :author => user,
762 766 :assigned_to => user)
763 767 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
764
765 group = Group.generate!
766 group.users << user
767 issue = Issue.generate!(:tracker => tracker, :status => status,
768 :project_id => 1, :author => user,
769 :assigned_to => group)
770 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
771 768 end
772 769
773 770 def test_new_statuses_allowed_to_should_consider_group_assignment
@@ -775,12 +772,16 class IssueTest < ActiveSupport::TestCase
775 772 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
776 773 :old_status_id => 1, :new_status_id => 4,
777 774 :author => false, :assignee => true)
778 user = User.find(2)
779 775 group = Group.generate!
776 Member.create!(:project_id => 1, :principal => group, :role_ids => [1])
777
778 user = User.find(2)
780 779 group.users << user
781 780
782 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
783 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
781 with_settings :issue_group_assignment => '1' do
782 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
783 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
784 end
784 785 end
785 786
786 787 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
@@ -895,40 +896,6 class IssueTest < ActiveSupport::TestCase
895 896 assert_nil issue.custom_field_value(cf2)
896 897 end
897 898
898 def test_safe_attributes_should_ignore_unassignable_assignee
899 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
900 :status_id => 1, :priority => IssuePriority.all.first,
901 :subject => 'test_create')
902 assert issue.valid?
903
904 # locked user, not allowed
905 issue.safe_attributes=({'assigned_to_id' => '5'})
906 assert_nil issue.assigned_to_id
907 # no member
908 issue.safe_attributes=({'assigned_to_id' => '1'})
909 assert_nil issue.assigned_to_id
910 # user 2 is ok
911 issue.safe_attributes=({'assigned_to_id' => '2'})
912 assert_equal 2, issue.assigned_to_id
913 assert issue.save
914
915 issue.reload
916 assert_equal 2, issue.assigned_to_id
917 issue.safe_attributes=({'assigned_to_id' => '5'})
918 assert_equal 2, issue.assigned_to_id
919 issue.safe_attributes=({'assigned_to_id' => '1'})
920 assert_equal 2, issue.assigned_to_id
921 # user 3 is also ok
922 issue.safe_attributes=({'assigned_to_id' => '3'})
923 assert_equal 3, issue.assigned_to_id
924 assert issue.save
925
926 # removal of assignee
927 issue.safe_attributes=({'assigned_to_id' => ''})
928 assert_nil issue.assigned_to_id
929 assert issue.save
930 end
931
932 899 def test_editable_custom_field_values_should_return_non_readonly_custom_values
933 900 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
934 901 :is_for_all => true, :tracker_ids => [1, 2])
@@ -1250,6 +1217,15 class IssueTest < ActiveSupport::TestCase
1250 1217 assert_equal "125", issue.custom_value_for(2).value
1251 1218 end
1252 1219
1220 def test_copy_to_another_project_should_clear_assignee_if_not_valid
1221 issue = Issue.generate!(:project_id => 1, :assigned_to_id => 2)
1222 project = Project.generate!
1223
1224 issue = Issue.new.copy_from(1)
1225 issue.project = project
1226 assert_nil issue.assigned_to
1227 end
1228
1253 1229 def test_copy_should_copy_status
1254 1230 orig = Issue.find(8)
1255 1231 assert orig.status != orig.default_status
@@ -1759,14 +1735,16 class IssueTest < ActiveSupport::TestCase
1759 1735 end
1760 1736
1761 1737 test "#copy should not create a journal" do
1762 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false)
1738 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2}, :link => false)
1763 1739 copy.save!
1764 1740 assert_equal 0, copy.reload.journals.size
1765 1741 end
1766 1742
1767 1743 test "#copy should allow assigned_to changes" do
1768 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1769 assert_equal 3, copy.assigned_to_id
1744 user = User.generate!
1745 Member.create!(:project_id => 3, :principal => user, :role_ids => [1])
1746 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => user.id)
1747 assert_equal user.id, copy.assigned_to_id
1770 1748 end
1771 1749
1772 1750 test "#copy should allow status changes" do
@@ -2297,8 +2275,9 class IssueTest < ActiveSupport::TestCase
2297 2275 assert !issue.assignable_users.include?(user)
2298 2276 end
2299 2277
2300 test "#assignable_users should include the current assignee" do
2278 def test_assignable_users_should_include_the_current_assignee
2301 2279 user = User.generate!
2280 Member.create!(:project_id => 1, :principal => user, :role_ids => [1])
2302 2281 issue = Issue.generate!(:assigned_to => user)
2303 2282 user.lock!
2304 2283
@@ -2674,7 +2653,9 class IssueTest < ActiveSupport::TestCase
2674 2653 end
2675 2654
2676 2655 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2677 issue = Issue.generate!(:assigned_to => User.generate!)
2656 user = User.generate!
2657 Member.create!(:project_id => 1, :principal => user, :role_ids => [1])
2658 issue = Issue.generate!(:assigned_to => user)
2678 2659 assert issue.assigned_to, "No assigned_to set for Issue"
2679 2660 assert issue.recipients.include?(issue.assigned_to.mail)
2680 2661 end
@@ -2692,7 +2673,9 class IssueTest < ActiveSupport::TestCase
2692 2673 end
2693 2674
2694 2675 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2695 issue = Issue.generate!(:assigned_to => User.generate!)
2676 user = User.generate!
2677 Member.create!(:project_id => 1, :principal => user, :role_ids => [1])
2678 issue = Issue.generate!(:assigned_to => user)
2696 2679 issue.assigned_to.update!(:mail_notification => :only_owner)
2697 2680 assert !issue.recipients.include?(issue.assigned_to.mail)
2698 2681 end
@@ -2980,10 +2963,13 class IssueTest < ActiveSupport::TestCase
2980 2963
2981 2964 def test_assigned_to_was_with_a_group
2982 2965 group = Group.find(10)
2966 Member.create!(:project_id => 1, :principal => group, :role_ids => [1])
2983 2967
2984 issue = Issue.generate!(:assigned_to => group)
2985 issue.reload.assigned_to = nil
2986 assert_equal group, issue.assigned_to_was
2968 with_settings :issue_group_assignment => '1' do
2969 issue = Issue.generate!(:assigned_to => group)
2970 issue.reload.assigned_to = nil
2971 assert_equal group, issue.assigned_to_was
2972 end
2987 2973 end
2988 2974
2989 2975 def test_issue_overdue_should_respect_user_timezone
@@ -627,8 +627,9 class MailerTest < ActiveSupport::TestCase
627 627 end
628 628
629 629 def test_reminder_should_include_issues_assigned_to_groups
630 with_settings :default_language => 'en' do
630 with_settings :default_language => 'en', :issue_group_assignment => '1' do
631 631 group = Group.generate!
632 Member.create!(:project_id => 1, :principal => group, :role_ids => [1])
632 633 group.users << User.find(2)
633 634 group.users << User.find(3)
634 635
@@ -676,19 +676,25 class QueryTest < ActiveSupport::TestCase
676 676 def test_filter_assigned_to_me
677 677 user = User.find(2)
678 678 group = Group.find(10)
679 User.current = user
680 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
681 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
682 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11))
683 679 group.users << user
680 other_group = Group.find(11)
681 Member.create!(:project_id => 1, :principal => group, :role_ids => [1])
682 Member.create!(:project_id => 1, :principal => other_group, :role_ids => [1])
683 User.current = user
684 684
685 query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
686 result = query.issues
687 assert_equal Issue.visible.where(:assigned_to_id => ([2] + user.reload.group_ids)).sort_by(&:id), result.sort_by(&:id)
688
689 assert result.include?(i1)
690 assert result.include?(i2)
691 assert !result.include?(i3)
685 with_settings :issue_group_assignment => '1' do
686 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
687 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
688 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => other_group)
689
690 query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
691 result = query.issues
692 assert_equal Issue.visible.where(:assigned_to_id => ([2] + user.reload.group_ids)).sort_by(&:id), result.sort_by(&:id)
693
694 assert result.include?(i1)
695 assert result.include?(i2)
696 assert !result.include?(i3)
697 end
692 698 end
693 699
694 700 def test_user_custom_field_filtered_on_me
@@ -1689,7 +1695,7 class QueryTest < ActiveSupport::TestCase
1689 1695 @issue1 = Issue.generate!(:project => @project, :assigned_to_id => @manager.id)
1690 1696 @issue2 = Issue.generate!(:project => @project, :assigned_to_id => @developer.id)
1691 1697 @issue3 = Issue.generate!(:project => @project, :assigned_to_id => @boss.id)
1692 @issue4 = Issue.generate!(:project => @project, :assigned_to_id => @guest.id)
1698 @issue4 = Issue.generate!(:project => @project, :author_id => @guest.id, :assigned_to_id => @guest.id)
1693 1699 @issue5 = Issue.generate!(:project => @project)
1694 1700
1695 1701 @query = IssueQuery.new(:name => '_', :project => @project)
@@ -1140,6 +1140,7 class UserTest < ActiveSupport::TestCase
1140 1140 project = Project.find(1)
1141 1141 author = User.generate!
1142 1142 assignee = User.generate!
1143 Member.create!(:user => assignee, :project => project, :role_ids => [1])
1143 1144 member = User.generate!
1144 1145 Member.create!(:user => member, :project => project, :role_ids => [1])
1145 1146 issue = Issue.generate!(:project => project, :assigned_to => assignee, :author => author)
@@ -1160,7 +1161,9 class UserTest < ActiveSupport::TestCase
1160 1161
1161 1162 def test_notify_about_issue_for_previous_assignee
1162 1163 assignee = User.generate!(:mail_notification => 'only_assigned')
1164 Member.create!(:user => assignee, :project_id => 1, :role_ids => [1])
1163 1165 new_assignee = User.generate!(:mail_notification => 'only_assigned')
1166 Member.create!(:user => new_assignee, :project_id => 1, :role_ids => [1])
1164 1167 issue = Issue.generate!(:assigned_to => assignee)
1165 1168
1166 1169 assert assignee.notify_about?(issue)
General Comments 0
You need to be logged in to leave comments. Login now