##// END OF EJS Templates
Fixed: validation error on issue creation when trying to add an invalid user as a watcher (#5373)....
Jean-Philippe Lang -
r5760:ef00501c3699
parent child
Show More
@@ -1,122 +1,143
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class WatcherTest < ActiveSupport::TestCase
20 class WatcherTest < ActiveSupport::TestCase
21 fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules,
21 fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules,
22 :issues,
22 :issues,
23 :boards, :messages,
23 :boards, :messages,
24 :wikis, :wiki_pages,
24 :wikis, :wiki_pages,
25 :watchers
25 :watchers
26
26
27 def setup
27 def setup
28 @user = User.find(1)
28 @user = User.find(1)
29 @issue = Issue.find(1)
29 @issue = Issue.find(1)
30 end
30 end
31
31
32 def test_watch
32 def test_watch
33 assert @issue.add_watcher(@user)
33 assert @issue.add_watcher(@user)
34 @issue.reload
34 @issue.reload
35 assert @issue.watchers.detect { |w| w.user == @user }
35 assert @issue.watchers.detect { |w| w.user == @user }
36 end
36 end
37
37
38 def test_cant_watch_twice
38 def test_cant_watch_twice
39 assert @issue.add_watcher(@user)
39 assert @issue.add_watcher(@user)
40 assert !@issue.add_watcher(@user)
40 assert !@issue.add_watcher(@user)
41 end
41 end
42
42
43 def test_watched_by
43 def test_watched_by
44 assert @issue.add_watcher(@user)
44 assert @issue.add_watcher(@user)
45 @issue.reload
45 @issue.reload
46 assert @issue.watched_by?(@user)
46 assert @issue.watched_by?(@user)
47 assert Issue.watched_by(@user).include?(@issue)
47 assert Issue.watched_by(@user).include?(@issue)
48 end
48 end
49
49
50 def test_watcher_users
51 watcher_users = Issue.find(2).watcher_users
52 assert_kind_of Array, watcher_users
53 assert_kind_of User, watcher_users.first
54 end
55
56 def test_watcher_users_should_not_validate_user
57 User.update_all("firstname = ''", "id=1")
58 @user.reload
59 assert !@user.valid?
60
61 issue = Issue.new(:project => Project.find(1), :tracker_id => 1, :subject => "test", :author => User.find(2))
62 issue.watcher_users << @user
63 issue.save!
64 assert issue.watched_by?(@user)
65 end
66
50 def test_watcher_user_ids
67 def test_watcher_user_ids
68 assert_equal [1, 3], Issue.find(2).watcher_user_ids.sort
69 end
70
71 def test_watcher_user_ids=
51 issue = Issue.new
72 issue = Issue.new
52 issue.watcher_user_ids = ['1', '3']
73 issue.watcher_user_ids = ['1', '3']
53 assert issue.watched_by?(User.find(1))
74 assert issue.watched_by?(User.find(1))
54 end
75 end
55
76
56 def test_addable_watcher_users
77 def test_addable_watcher_users
57 addable_watcher_users = @issue.addable_watcher_users
78 addable_watcher_users = @issue.addable_watcher_users
58 assert_kind_of Array, addable_watcher_users
79 assert_kind_of Array, addable_watcher_users
59 assert_kind_of User, addable_watcher_users.first
80 assert_kind_of User, addable_watcher_users.first
60 end
81 end
61
82
62 def test_addable_watcher_users_should_not_include_user_that_cannot_view_the_object
83 def test_addable_watcher_users_should_not_include_user_that_cannot_view_the_object
63 issue = Issue.new(:project => Project.find(1), :is_private => true)
84 issue = Issue.new(:project => Project.find(1), :is_private => true)
64 assert_nil issue.addable_watcher_users.detect {|user| !issue.visible?(user)}
85 assert_nil issue.addable_watcher_users.detect {|user| !issue.visible?(user)}
65 end
86 end
66
87
67 def test_recipients
88 def test_recipients
68 @issue.watchers.delete_all
89 @issue.watchers.delete_all
69 @issue.reload
90 @issue.reload
70
91
71 assert @issue.watcher_recipients.empty?
92 assert @issue.watcher_recipients.empty?
72 assert @issue.add_watcher(@user)
93 assert @issue.add_watcher(@user)
73
94
74 @user.mail_notification = 'all'
95 @user.mail_notification = 'all'
75 @user.save!
96 @user.save!
76 @issue.reload
97 @issue.reload
77 assert @issue.watcher_recipients.include?(@user.mail)
98 assert @issue.watcher_recipients.include?(@user.mail)
78
99
79 @user.mail_notification = 'none'
100 @user.mail_notification = 'none'
80 @user.save!
101 @user.save!
81 @issue.reload
102 @issue.reload
82 assert !@issue.watcher_recipients.include?(@user.mail)
103 assert !@issue.watcher_recipients.include?(@user.mail)
83 end
104 end
84
105
85 def test_unwatch
106 def test_unwatch
86 assert @issue.add_watcher(@user)
107 assert @issue.add_watcher(@user)
87 @issue.reload
108 @issue.reload
88 assert_equal 1, @issue.remove_watcher(@user)
109 assert_equal 1, @issue.remove_watcher(@user)
89 end
110 end
90
111
91 def test_prune
112 def test_prune
92 Watcher.delete_all("user_id = 9")
113 Watcher.delete_all("user_id = 9")
93 user = User.find(9)
114 user = User.find(9)
94
115
95 # public
116 # public
96 Watcher.create!(:watchable => Issue.find(1), :user => user)
117 Watcher.create!(:watchable => Issue.find(1), :user => user)
97 Watcher.create!(:watchable => Issue.find(2), :user => user)
118 Watcher.create!(:watchable => Issue.find(2), :user => user)
98 Watcher.create!(:watchable => Message.find(1), :user => user)
119 Watcher.create!(:watchable => Message.find(1), :user => user)
99 Watcher.create!(:watchable => Wiki.find(1), :user => user)
120 Watcher.create!(:watchable => Wiki.find(1), :user => user)
100 Watcher.create!(:watchable => WikiPage.find(2), :user => user)
121 Watcher.create!(:watchable => WikiPage.find(2), :user => user)
101
122
102 # private project (id: 2)
123 # private project (id: 2)
103 Member.create!(:project => Project.find(2), :principal => user, :role_ids => [1])
124 Member.create!(:project => Project.find(2), :principal => user, :role_ids => [1])
104 Watcher.create!(:watchable => Issue.find(4), :user => user)
125 Watcher.create!(:watchable => Issue.find(4), :user => user)
105 Watcher.create!(:watchable => Message.find(7), :user => user)
126 Watcher.create!(:watchable => Message.find(7), :user => user)
106 Watcher.create!(:watchable => Wiki.find(2), :user => user)
127 Watcher.create!(:watchable => Wiki.find(2), :user => user)
107 Watcher.create!(:watchable => WikiPage.find(3), :user => user)
128 Watcher.create!(:watchable => WikiPage.find(3), :user => user)
108
129
109 assert_no_difference 'Watcher.count' do
130 assert_no_difference 'Watcher.count' do
110 Watcher.prune(:user => User.find(9))
131 Watcher.prune(:user => User.find(9))
111 end
132 end
112
133
113 Member.delete_all
134 Member.delete_all
114
135
115 assert_difference 'Watcher.count', -4 do
136 assert_difference 'Watcher.count', -4 do
116 Watcher.prune(:user => User.find(9))
137 Watcher.prune(:user => User.find(9))
117 end
138 end
118
139
119 assert Issue.find(1).watched_by?(user)
140 assert Issue.find(1).watched_by?(user)
120 assert !Issue.find(4).watched_by?(user)
141 assert !Issue.find(4).watched_by?(user)
121 end
142 end
122 end
143 end
@@ -1,77 +1,77
1 # ActsAsWatchable
1 # ActsAsWatchable
2 module Redmine
2 module Redmine
3 module Acts
3 module Acts
4 module Watchable
4 module Watchable
5 def self.included(base)
5 def self.included(base)
6 base.extend ClassMethods
6 base.extend ClassMethods
7 end
7 end
8
8
9 module ClassMethods
9 module ClassMethods
10 def acts_as_watchable(options = {})
10 def acts_as_watchable(options = {})
11 return if self.included_modules.include?(Redmine::Acts::Watchable::InstanceMethods)
11 return if self.included_modules.include?(Redmine::Acts::Watchable::InstanceMethods)
12 send :include, Redmine::Acts::Watchable::InstanceMethods
12 send :include, Redmine::Acts::Watchable::InstanceMethods
13
13
14 class_eval do
14 class_eval do
15 has_many :watchers, :as => :watchable, :dependent => :delete_all
15 has_many :watchers, :as => :watchable, :dependent => :delete_all
16 has_many :watcher_users, :through => :watchers, :source => :user
16 has_many :watcher_users, :through => :watchers, :source => :user, :validate => false
17
17
18 named_scope :watched_by, lambda { |user_id|
18 named_scope :watched_by, lambda { |user_id|
19 { :include => :watchers,
19 { :include => :watchers,
20 :conditions => ["#{Watcher.table_name}.user_id = ?", user_id] }
20 :conditions => ["#{Watcher.table_name}.user_id = ?", user_id] }
21 }
21 }
22 attr_protected :watcher_ids, :watcher_user_ids
22 attr_protected :watcher_ids, :watcher_user_ids
23 end
23 end
24 end
24 end
25 end
25 end
26
26
27 module InstanceMethods
27 module InstanceMethods
28 def self.included(base)
28 def self.included(base)
29 base.extend ClassMethods
29 base.extend ClassMethods
30 end
30 end
31
31
32 # Returns an array of users that are proposed as watchers
32 # Returns an array of users that are proposed as watchers
33 def addable_watcher_users
33 def addable_watcher_users
34 users = self.project.users.sort - self.watcher_users
34 users = self.project.users.sort - self.watcher_users
35 if respond_to?(:visible?)
35 if respond_to?(:visible?)
36 users.reject! {|user| !visible?(user)}
36 users.reject! {|user| !visible?(user)}
37 end
37 end
38 users
38 users
39 end
39 end
40
40
41 # Adds user as a watcher
41 # Adds user as a watcher
42 def add_watcher(user)
42 def add_watcher(user)
43 self.watchers << Watcher.new(:user => user)
43 self.watchers << Watcher.new(:user => user)
44 end
44 end
45
45
46 # Removes user from the watchers list
46 # Removes user from the watchers list
47 def remove_watcher(user)
47 def remove_watcher(user)
48 return nil unless user && user.is_a?(User)
48 return nil unless user && user.is_a?(User)
49 Watcher.delete_all "watchable_type = '#{self.class}' AND watchable_id = #{self.id} AND user_id = #{user.id}"
49 Watcher.delete_all "watchable_type = '#{self.class}' AND watchable_id = #{self.id} AND user_id = #{user.id}"
50 end
50 end
51
51
52 # Adds/removes watcher
52 # Adds/removes watcher
53 def set_watcher(user, watching=true)
53 def set_watcher(user, watching=true)
54 watching ? add_watcher(user) : remove_watcher(user)
54 watching ? add_watcher(user) : remove_watcher(user)
55 end
55 end
56
56
57 # Returns true if object is watched by +user+
57 # Returns true if object is watched by +user+
58 def watched_by?(user)
58 def watched_by?(user)
59 !!(user && self.watcher_user_ids.detect {|uid| uid == user.id })
59 !!(user && self.watcher_user_ids.detect {|uid| uid == user.id })
60 end
60 end
61
61
62 # Returns an array of watchers' email addresses
62 # Returns an array of watchers' email addresses
63 def watcher_recipients
63 def watcher_recipients
64 notified = watcher_users.active
64 notified = watcher_users.active
65 notified.reject! {|user| user.mail_notification == 'none'}
65 notified.reject! {|user| user.mail_notification == 'none'}
66
66
67 if respond_to?(:visible?)
67 if respond_to?(:visible?)
68 notified.reject! {|user| !visible?(user)}
68 notified.reject! {|user| !visible?(user)}
69 end
69 end
70 notified.collect(&:mail).compact
70 notified.collect(&:mail).compact
71 end
71 end
72
72
73 module ClassMethods; end
73 module ClassMethods; end
74 end
74 end
75 end
75 end
76 end
76 end
77 end
77 end
General Comments 0
You need to be logged in to leave comments. Login now