##// END OF EJS Templates
Makes user unwatch what he can no longer view after its permissions have changed (#3589)....
Jean-Philippe Lang -
r3053:f33231181f95
parent child
Show More
@@ -0,0 +1,9
1 desc 'Removes watchers from what they can no longer view.'
2
3 namespace :redmine do
4 namespace :watchers do
5 task :prune => :environment do
6 Watcher.prune
7 end
8 end
9 end
@@ -27,6 +27,10 class Board < ActiveRecord::Base
27 27 validates_length_of :name, :maximum => 30
28 28 validates_length_of :description, :maximum => 255
29 29
30 def visible?(user=User.current)
31 !user.nil? && user.allowed_to?(:view_messages, project)
32 end
33
30 34 def to_s
31 35 name
32 36 end
@@ -25,6 +25,8 class Member < ActiveRecord::Base
25 25 validates_presence_of :principal, :project
26 26 validates_uniqueness_of :user_id, :scope => :project_id
27 27
28 after_destroy :unwatch_from_permission_change
29
28 30 def name
29 31 self.user.name
30 32 end
@@ -39,7 +41,11 class Member < ActiveRecord::Base
39 41 # Add new roles
40 42 new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id) }
41 43 # Remove roles (Rails' #role_ids= will not trigger MemberRole#on_destroy)
42 member_roles.select {|mr| !ids.include?(mr.role_id)}.each(&:destroy)
44 member_roles_to_destroy = member_roles.select {|mr| !ids.include?(mr.role_id)}
45 if member_roles_to_destroy.any?
46 member_roles_to_destroy.each(&:destroy)
47 unwatch_from_permission_change
48 end
43 49 end
44 50
45 51 def <=>(member)
@@ -63,4 +69,13 class Member < ActiveRecord::Base
63 69 def validate
64 70 errors.add_to_base "Role can't be blank" if member_roles.empty? && roles.empty?
65 71 end
72
73 private
74
75 # Unwatch things that the user is no longer allowed to view inside project
76 def unwatch_from_permission_change
77 if user
78 Watcher.prune(:user => user, :project => project)
79 end
80 end
66 81 end
@@ -49,6 +49,11 class MemberRole < ActiveRecord::Base
49 49 end
50 50
51 51 def remove_role_from_group_users
52 MemberRole.find(:all, :conditions => { :inherited_from => id }).each(&:destroy)
52 MemberRole.find(:all, :conditions => { :inherited_from => id }).group_by(&:member).each do |member, member_roles|
53 member_roles.each(&:destroy)
54 if member && member.user
55 Watcher.prune(:user => member.user, :project => member.project)
56 end
57 end
53 58 end
54 59 end
@@ -42,6 +42,10 class Message < ActiveRecord::Base
42 42
43 43 after_create :add_author_as_watcher
44 44
45 def visible?(user=User.current)
46 !user.nil? && user.allowed_to?(:view_messages, project)
47 end
48
45 49 def validate_on_create
46 50 # Can not reply to a locked topic
47 51 errors.add_to_base 'Topic is locked' if root.locked? && self != root
@@ -22,9 +22,44 class Watcher < ActiveRecord::Base
22 22 validates_presence_of :user
23 23 validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id]
24 24
25 # Unwatch things that users are no longer allowed to view
26 def self.prune(options={})
27 if options.has_key?(:user)
28 prune_single_user(options[:user], options)
29 else
30 pruned = 0
31 User.find(:all, :conditions => "id IN (SELECT DISTINCT user_id FROM #{table_name})").each do |user|
32 pruned += prune_single_user(user, options)
33 end
34 pruned
35 end
36 end
37
25 38 protected
26 39
27 40 def validate
28 41 errors.add :user_id, :invalid unless user.nil? || user.active?
29 42 end
43
44 private
45
46 def self.prune_single_user(user, options={})
47 return unless user.is_a?(User)
48 pruned = 0
49 find(:all, :conditions => {:user_id => user.id}).each do |watcher|
50 next if watcher.watchable.nil?
51
52 if options.has_key?(:project)
53 next unless watcher.watchable.respond_to?(:project) && watcher.watchable.project == options[:project]
54 end
55
56 if watcher.watchable.respond_to?(:visible?)
57 unless watcher.watchable.visible?(user)
58 watcher.destroy
59 pruned += 1
60 end
61 end
62 end
63 pruned
64 end
30 65 end
@@ -25,6 +25,10 class Wiki < ActiveRecord::Base
25 25 validates_presence_of :start_page
26 26 validates_format_of :start_page, :with => /^[^,\.\/\?\;\|\:]*$/
27 27
28 def visible?(user=User.current)
29 !user.nil? && user.allowed_to?(:view_wiki_pages, project)
30 end
31
28 32 # find the page with the given title
29 33 # if page doesn't exist, return a new page
30 34 def find_or_new_page(title)
@@ -41,6 +41,10 class WikiPage < ActiveRecord::Base
41 41 validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
42 42 validates_associated :content
43 43
44 def visible?(user=User.current)
45 !user.nil? && user.allowed_to?(:view_wiki_pages, project)
46 end
47
44 48 def title=(value)
45 49 value = Wiki.titleize(value)
46 50 @previous_title = read_attribute(:title) if @previous_title.blank?
@@ -59,3 +59,7 enabled_modules_015:
59 59 name: wiki
60 60 project_id: 2
61 61 id: 15
62 enabled_modules_016:
63 name: boards
64 project_id: 2
65 id: 16
@@ -66,3 +66,14 messages_006:
66 66 author_id: 3
67 67 parent_id: 4
68 68 board_id: 1
69 messages_007:
70 created_on: <%= 2.days.ago.to_date.to_s(:db) %>
71 updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
72 subject: 'Message on a private project'
73 id: 7
74 replies_count: 0
75 last_reply_id:
76 content: "This is a private message"
77 author_id: 1
78 parent_id:
79 board_id: 3
@@ -18,7 +18,7
18 18 require File.dirname(__FILE__) + '/../test_helper'
19 19
20 20 class MemberTest < ActiveSupport::TestCase
21 fixtures :users, :projects, :roles, :members, :member_roles
21 fixtures :all
22 22
23 23 def setup
24 24 @jsmith = Member.find(1)
@@ -68,4 +68,70 class MemberTest < ActiveSupport::TestCase
68 68
69 69 assert_raise(ActiveRecord::RecordNotFound) { Member.find(@jsmith.id) }
70 70 end
71
72 context "removing permissions" do
73 setup do
74 Watcher.delete_all("user_id = 9")
75 user = User.find(9)
76 # public
77 Watcher.create!(:watchable => Issue.find(1), :user_id => user)
78 # private
79 Watcher.create!(:watchable => Issue.find(4), :user => user)
80 Watcher.create!(:watchable => Message.find(7), :user => user)
81 Watcher.create!(:watchable => Wiki.find(2), :user => user)
82 Watcher.create!(:watchable => WikiPage.find(3), :user => user)
83 end
84
85 context "of user" do
86 setup do
87 @member = Member.create!(:project => Project.find(2), :principal => User.find(9), :role_ids => [1, 2])
88 end
89
90 context "by deleting membership" do
91 should "prune watchers" do
92 assert_difference 'Watcher.count', -4 do
93 @member.destroy
94 end
95 end
96 end
97
98 context "by updating roles" do
99 should "prune watchers" do
100 Role.find(2).remove_permission! :view_wiki_pages
101 member = Member.first(:order => 'id desc')
102 assert_difference 'Watcher.count', -2 do
103 member.role_ids = [2]
104 member.save
105 end
106 assert !Message.find(7).watched_by?(@user)
107 end
108 end
109 end
110
111 context "of group" do
112 setup do
113 group = Group.find(10)
114 @member = Member.create!(:project => Project.find(2), :principal => group, :role_ids => [1, 2])
115 group.users << User.find(9)
116 end
117
118 context "by deleting membership" do
119 should "prune watchers" do
120 assert_difference 'Watcher.count', -4 do
121 @member.destroy
122 end
123 end
124 end
125
126 context "by updating roles" do
127 should "prune watchers" do
128 Role.find(2).remove_permission! :view_wiki_pages
129 assert_difference 'Watcher.count', -2 do
130 @member.role_ids = [2]
131 @member.save
132 end
133 end
134 end
135 end
136 end
71 137 end
@@ -1,5 +1,5
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
@@ -18,7 +18,11
18 18 require File.dirname(__FILE__) + '/../test_helper'
19 19
20 20 class WatcherTest < ActiveSupport::TestCase
21 fixtures :issues, :users
21 fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules,
22 :issues,
23 :boards, :messages,
24 :wikis, :wiki_pages,
25 :watchers
22 26
23 27 def setup
24 28 @user = User.find(1)
@@ -66,4 +70,36 class WatcherTest < ActiveSupport::TestCase
66 70 @issue.reload
67 71 assert_equal 1, @issue.remove_watcher(@user)
68 72 end
73
74 def test_prune
75 Watcher.delete_all("user_id = 9")
76 user = User.find(9)
77
78 # public
79 Watcher.create!(:watchable => Issue.find(1), :user => user)
80 Watcher.create!(:watchable => Issue.find(2), :user => user)
81 Watcher.create!(:watchable => Message.find(1), :user => user)
82 Watcher.create!(:watchable => Wiki.find(1), :user => user)
83 Watcher.create!(:watchable => WikiPage.find(2), :user => user)
84
85 # private project (id: 2)
86 Member.create!(:project => Project.find(2), :principal => user, :role_ids => [1])
87 Watcher.create!(:watchable => Issue.find(4), :user => user)
88 Watcher.create!(:watchable => Message.find(7), :user => user)
89 Watcher.create!(:watchable => Wiki.find(2), :user => user)
90 Watcher.create!(:watchable => WikiPage.find(3), :user => user)
91
92 assert_no_difference 'Watcher.count' do
93 Watcher.prune(:user => User.find(9))
94 end
95
96 Member.delete_all
97
98 assert_difference 'Watcher.count', -4 do
99 Watcher.prune(:user => User.find(9))
100 end
101
102 assert Issue.find(1).watched_by?(user)
103 assert !Issue.find(4).watched_by?(user)
104 end
69 105 end
General Comments 0
You need to be logged in to leave comments. Login now