diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2009-12-13 12:39:22 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2009-12-13 12:39:22 +0000 |
commit | f33231181f9591ee67577e229a8bf6de24516ba0 (patch) | |
tree | 57bbc4338b9cf35cecf323565fefbf549ecfd14f /app | |
parent | c31a6719735114c371e5da68eb3787b8713c5360 (diff) | |
download | redmine-f33231181f9591ee67577e229a8bf6de24516ba0.tar.gz redmine-f33231181f9591ee67577e229a8bf6de24516ba0.zip |
Makes user unwatch what he can no longer view after its permissions have changed (#3589).
A rake task (redmine:watchers:prune) is also added to prune existing watchers.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3167 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r-- | app/models/board.rb | 4 | ||||
-rw-r--r-- | app/models/member.rb | 17 | ||||
-rw-r--r-- | app/models/member_role.rb | 7 | ||||
-rw-r--r-- | app/models/message.rb | 4 | ||||
-rw-r--r-- | app/models/watcher.rb | 35 | ||||
-rw-r--r-- | app/models/wiki.rb | 4 | ||||
-rw-r--r-- | app/models/wiki_page.rb | 4 |
7 files changed, 73 insertions, 2 deletions
diff --git a/app/models/board.rb b/app/models/board.rb index ada138375..e7310da65 100644 --- a/app/models/board.rb +++ b/app/models/board.rb @@ -27,6 +27,10 @@ class Board < ActiveRecord::Base validates_length_of :name, :maximum => 30 validates_length_of :description, :maximum => 255 + def visible?(user=User.current) + !user.nil? && user.allowed_to?(:view_messages, project) + end + def to_s name end diff --git a/app/models/member.rb b/app/models/member.rb index 6fffb2161..44a421745 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -24,6 +24,8 @@ class Member < ActiveRecord::Base validates_presence_of :principal, :project validates_uniqueness_of :user_id, :scope => :project_id + + after_destroy :unwatch_from_permission_change def name self.user.name @@ -39,7 +41,11 @@ class Member < ActiveRecord::Base # Add new roles new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id) } # Remove roles (Rails' #role_ids= will not trigger MemberRole#on_destroy) - member_roles.select {|mr| !ids.include?(mr.role_id)}.each(&:destroy) + member_roles_to_destroy = member_roles.select {|mr| !ids.include?(mr.role_id)} + if member_roles_to_destroy.any? + member_roles_to_destroy.each(&:destroy) + unwatch_from_permission_change + end end def <=>(member) @@ -63,4 +69,13 @@ class Member < ActiveRecord::Base def validate errors.add_to_base "Role can't be blank" if member_roles.empty? && roles.empty? end + + private + + # Unwatch things that the user is no longer allowed to view inside project + def unwatch_from_permission_change + if user + Watcher.prune(:user => user, :project => project) + end + end end diff --git a/app/models/member_role.rb b/app/models/member_role.rb index 5a31c17c5..286659fc3 100644 --- a/app/models/member_role.rb +++ b/app/models/member_role.rb @@ -49,6 +49,11 @@ class MemberRole < ActiveRecord::Base end def remove_role_from_group_users - MemberRole.find(:all, :conditions => { :inherited_from => id }).each(&:destroy) + MemberRole.find(:all, :conditions => { :inherited_from => id }).group_by(&:member).each do |member, member_roles| + member_roles.each(&:destroy) + if member && member.user + Watcher.prune(:user => member.user, :project => member.project) + end + end end end diff --git a/app/models/message.rb b/app/models/message.rb index f37413286..1e59719dd 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -42,6 +42,10 @@ class Message < ActiveRecord::Base after_create :add_author_as_watcher + def visible?(user=User.current) + !user.nil? && user.allowed_to?(:view_messages, project) + end + def validate_on_create # Can not reply to a locked topic errors.add_to_base 'Topic is locked' if root.locked? && self != root diff --git a/app/models/watcher.rb b/app/models/watcher.rb index b13039f84..a6c0c331c 100644 --- a/app/models/watcher.rb +++ b/app/models/watcher.rb @@ -21,10 +21,45 @@ class Watcher < ActiveRecord::Base validates_presence_of :user validates_uniqueness_of :user_id, :scope => [:watchable_type, :watchable_id] + + # Unwatch things that users are no longer allowed to view + def self.prune(options={}) + if options.has_key?(:user) + prune_single_user(options[:user], options) + else + pruned = 0 + User.find(:all, :conditions => "id IN (SELECT DISTINCT user_id FROM #{table_name})").each do |user| + pruned += prune_single_user(user, options) + end + pruned + end + end protected def validate errors.add :user_id, :invalid unless user.nil? || user.active? end + + private + + def self.prune_single_user(user, options={}) + return unless user.is_a?(User) + pruned = 0 + find(:all, :conditions => {:user_id => user.id}).each do |watcher| + next if watcher.watchable.nil? + + if options.has_key?(:project) + next unless watcher.watchable.respond_to?(:project) && watcher.watchable.project == options[:project] + end + + if watcher.watchable.respond_to?(:visible?) + unless watcher.watchable.visible?(user) + watcher.destroy + pruned += 1 + end + end + end + pruned + end end diff --git a/app/models/wiki.rb b/app/models/wiki.rb index b31b03482..b9a76fb32 100644 --- a/app/models/wiki.rb +++ b/app/models/wiki.rb @@ -25,6 +25,10 @@ class Wiki < ActiveRecord::Base validates_presence_of :start_page validates_format_of :start_page, :with => /^[^,\.\/\?\;\|\:]*$/ + def visible?(user=User.current) + !user.nil? && user.allowed_to?(:view_wiki_pages, project) + end + # find the page with the given title # if page doesn't exist, return a new page def find_or_new_page(title) diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index d6009c2e3..1b0bf4d49 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -40,6 +40,10 @@ class WikiPage < ActiveRecord::Base validates_format_of :title, :with => /^[^,\.\/\?\;\|\s]*$/ validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false validates_associated :content + + def visible?(user=User.current) + !user.nil? && user.allowed_to?(:view_wiki_pages, project) + end def title=(value) value = Wiki.titleize(value) |