##// END OF EJS Templates
Do not propose users that can't view an issue as watchers (#7412)....
Jean-Philippe Lang -
r5756:7e1f04bdfb6f
parent child
Show More
@@ -1,111 +1,122
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_user_ids
50 def test_watcher_user_ids
51 issue = Issue.new
51 issue = Issue.new
52 issue.watcher_user_ids = ['1', '3']
52 issue.watcher_user_ids = ['1', '3']
53 assert issue.watched_by?(User.find(1))
53 assert issue.watched_by?(User.find(1))
54 end
54 end
55
55
56 def test_addable_watcher_users
57 addable_watcher_users = @issue.addable_watcher_users
58 assert_kind_of Array, addable_watcher_users
59 assert_kind_of User, addable_watcher_users.first
60 end
61
62 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)
64 assert_nil issue.addable_watcher_users.detect {|user| !issue.visible?(user)}
65 end
66
56 def test_recipients
67 def test_recipients
57 @issue.watchers.delete_all
68 @issue.watchers.delete_all
58 @issue.reload
69 @issue.reload
59
70
60 assert @issue.watcher_recipients.empty?
71 assert @issue.watcher_recipients.empty?
61 assert @issue.add_watcher(@user)
72 assert @issue.add_watcher(@user)
62
73
63 @user.mail_notification = 'all'
74 @user.mail_notification = 'all'
64 @user.save!
75 @user.save!
65 @issue.reload
76 @issue.reload
66 assert @issue.watcher_recipients.include?(@user.mail)
77 assert @issue.watcher_recipients.include?(@user.mail)
67
78
68 @user.mail_notification = 'none'
79 @user.mail_notification = 'none'
69 @user.save!
80 @user.save!
70 @issue.reload
81 @issue.reload
71 assert !@issue.watcher_recipients.include?(@user.mail)
82 assert !@issue.watcher_recipients.include?(@user.mail)
72 end
83 end
73
84
74 def test_unwatch
85 def test_unwatch
75 assert @issue.add_watcher(@user)
86 assert @issue.add_watcher(@user)
76 @issue.reload
87 @issue.reload
77 assert_equal 1, @issue.remove_watcher(@user)
88 assert_equal 1, @issue.remove_watcher(@user)
78 end
89 end
79
90
80 def test_prune
91 def test_prune
81 Watcher.delete_all("user_id = 9")
92 Watcher.delete_all("user_id = 9")
82 user = User.find(9)
93 user = User.find(9)
83
94
84 # public
95 # public
85 Watcher.create!(:watchable => Issue.find(1), :user => user)
96 Watcher.create!(:watchable => Issue.find(1), :user => user)
86 Watcher.create!(:watchable => Issue.find(2), :user => user)
97 Watcher.create!(:watchable => Issue.find(2), :user => user)
87 Watcher.create!(:watchable => Message.find(1), :user => user)
98 Watcher.create!(:watchable => Message.find(1), :user => user)
88 Watcher.create!(:watchable => Wiki.find(1), :user => user)
99 Watcher.create!(:watchable => Wiki.find(1), :user => user)
89 Watcher.create!(:watchable => WikiPage.find(2), :user => user)
100 Watcher.create!(:watchable => WikiPage.find(2), :user => user)
90
101
91 # private project (id: 2)
102 # private project (id: 2)
92 Member.create!(:project => Project.find(2), :principal => user, :role_ids => [1])
103 Member.create!(:project => Project.find(2), :principal => user, :role_ids => [1])
93 Watcher.create!(:watchable => Issue.find(4), :user => user)
104 Watcher.create!(:watchable => Issue.find(4), :user => user)
94 Watcher.create!(:watchable => Message.find(7), :user => user)
105 Watcher.create!(:watchable => Message.find(7), :user => user)
95 Watcher.create!(:watchable => Wiki.find(2), :user => user)
106 Watcher.create!(:watchable => Wiki.find(2), :user => user)
96 Watcher.create!(:watchable => WikiPage.find(3), :user => user)
107 Watcher.create!(:watchable => WikiPage.find(3), :user => user)
97
108
98 assert_no_difference 'Watcher.count' do
109 assert_no_difference 'Watcher.count' do
99 Watcher.prune(:user => User.find(9))
110 Watcher.prune(:user => User.find(9))
100 end
111 end
101
112
102 Member.delete_all
113 Member.delete_all
103
114
104 assert_difference 'Watcher.count', -4 do
115 assert_difference 'Watcher.count', -4 do
105 Watcher.prune(:user => User.find(9))
116 Watcher.prune(:user => User.find(9))
106 end
117 end
107
118
108 assert Issue.find(1).watched_by?(user)
119 assert Issue.find(1).watched_by?(user)
109 assert !Issue.find(4).watched_by?(user)
120 assert !Issue.find(4).watched_by?(user)
110 end
121 end
111 end
122 end
@@ -1,73 +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
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 self.project.users.sort - self.watcher_users
34 users = self.project.users.sort - self.watcher_users
35 if respond_to?(:visible?)
36 users.reject! {|user| !visible?(user)}
37 end
38 users
35 end
39 end
36
40
37 # Adds user as a watcher
41 # Adds user as a watcher
38 def add_watcher(user)
42 def add_watcher(user)
39 self.watchers << Watcher.new(:user => user)
43 self.watchers << Watcher.new(:user => user)
40 end
44 end
41
45
42 # Removes user from the watchers list
46 # Removes user from the watchers list
43 def remove_watcher(user)
47 def remove_watcher(user)
44 return nil unless user && user.is_a?(User)
48 return nil unless user && user.is_a?(User)
45 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}"
46 end
50 end
47
51
48 # Adds/removes watcher
52 # Adds/removes watcher
49 def set_watcher(user, watching=true)
53 def set_watcher(user, watching=true)
50 watching ? add_watcher(user) : remove_watcher(user)
54 watching ? add_watcher(user) : remove_watcher(user)
51 end
55 end
52
56
53 # Returns true if object is watched by +user+
57 # Returns true if object is watched by +user+
54 def watched_by?(user)
58 def watched_by?(user)
55 !!(user && self.watcher_user_ids.detect {|uid| uid == user.id })
59 !!(user && self.watcher_user_ids.detect {|uid| uid == user.id })
56 end
60 end
57
61
58 # Returns an array of watchers' email addresses
62 # Returns an array of watchers' email addresses
59 def watcher_recipients
63 def watcher_recipients
60 notified = watcher_users.active
64 notified = watcher_users.active
61 notified.reject! {|user| user.mail_notification == 'none'}
65 notified.reject! {|user| user.mail_notification == 'none'}
62
66
63 if respond_to?(:visible?)
67 if respond_to?(:visible?)
64 notified.reject! {|user| !visible?(user)}
68 notified.reject! {|user| !visible?(user)}
65 end
69 end
66 notified.collect(&:mail).compact
70 notified.collect(&:mail).compact
67 end
71 end
68
72
69 module ClassMethods; end
73 module ClassMethods; end
70 end
74 end
71 end
75 end
72 end
76 end
73 end
77 end
General Comments 0
You need to be logged in to leave comments. Login now