diff --git a/app/controllers/watchers_controller.rb b/app/controllers/watchers_controller.rb
index 2325634a..2f596caf 100644
--- a/app/controllers/watchers_controller.rb
+++ b/app/controllers/watchers_controller.rb
@@ -16,7 +16,8 @@ class WatchersController < ApplicationController
before_filter :find_project
before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch]
before_filter :authorize, :only => [:new, :destroy]
-
+ before_filter :authorize_access_to_object, :only => [:new, :destroy]
+
verify :method => :post,
:only => [ :watch, :unwatch ],
:render => { :nothing => true, :status => :method_not_allowed }
@@ -97,4 +98,28 @@ private
rescue ::ActionController::RedirectBackError
render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true
end
+
+ def authorize_access_to_object
+ allowed = false
+
+ case @watched.class.to_s
+ when "Issue"
+ if params[:action] == 'new'
+ allowed = true if User.current.allowed_to?(:add_issue_watchers, @project)
+ end
+ if params[:action] == 'destroy'
+ allowed = true if User.current.allowed_to?(:delete_issue_watchers, @project)
+ end
+ when "WikiPage"
+ if params[:action] == 'new'
+ allowed = true if User.current.allowed_to?(:add_wiki_page_watchers, @project)
+ end
+ if params[:action] == 'destroy'
+ allowed = true if User.current.allowed_to?(:delete_wiki_page_watchers, @project)
+ end
+ end
+
+ deny_access unless allowed
+ end
+
end
diff --git a/app/views/watchers/_watchers.rhtml b/app/views/watchers/_watchers.rhtml
index 00b4954c..838b49f1 100644
--- a/app/views/watchers/_watchers.rhtml
+++ b/app/views/watchers/_watchers.rhtml
@@ -1,10 +1,10 @@
-<%= link_to_function(l(:button_add), "$('new-watcher-form').toggle();") if User.current.allowed_to?(:add_issue_watchers, @project) %>
+<%= link_to_function(l(:button_add), "$('new-watcher-form').toggle();") if User.current.allowed_to?("add_#{watched.class.name.underscore}_watchers".to_sym, @project) %>
<%= l(:label_issue_watchers) %> (<%= watched.watcher_users.size %>)
-<% if User.current.allowed_to?(:add_issue_watchers, @project) %>
+<% if User.current.allowed_to?("add_#{watched.class.name.underscore}_watchers".to_sym, @project) %>
<% remote_form_for(:watcher, @watcher,
:url => {:controller => 'watchers',
:action => 'new',
diff --git a/app/views/wiki/show.rhtml b/app/views/wiki/show.rhtml
index c144fb1d..b2d7e2d2 100644
--- a/app/views/wiki/show.rhtml
+++ b/app/views/wiki/show.rhtml
@@ -59,6 +59,14 @@
<% content_for :sidebar do %>
<%= render :partial => 'wiki/sidebar' %>
+
+ <% if User.current.allowed_to?(:add_wiki_page_watchers, @project) ||
+ (@page.watchers.present? && User.current.allowed_to?(:view_wiki_page_watchers, @project)) %>
+
+ <%= render :partial => 'watchers/watchers', :locals => {:watched => @page} %>
+
+ <% end %>
+
<% end %>
<% html_title h(@page.pretty_title) %>
diff --git a/lib/redmine.rb b/lib/redmine.rb
index ec5a2618..7ed95c9e 100644
--- a/lib/redmine.rb
+++ b/lib/redmine.rb
@@ -136,6 +136,9 @@ Redmine::AccessControl.map do |map|
map.permission :edit_wiki_pages, :wiki => [:edit, :update, :preview, :add_attachment]
map.permission :delete_wiki_pages_attachments, {}
map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
+ map.permission :view_wiki_page_watchers, {}
+ map.permission :add_wiki_page_watchers, {:watchers => :new}
+ map.permission :delete_wiki_page_watchers, {:watchers => :destroy}
end
map.project_module :repository do |map|
diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml
index 2f287e1b..5fc52b67 100644
--- a/test/fixtures/roles.yml
+++ b/test/fixtures/roles.yml
@@ -45,6 +45,9 @@ roles_001:
- :protect_wiki_pages
- :delete_wiki_pages
- :rename_wiki_pages
+ - :view_wiki_page_watchers
+ - :add_wiki_page_watchers
+ - :delete_wiki_page_watchers
- :add_messages
- :edit_messages
- :delete_messages
diff --git a/test/functional/watchers_controller_test.rb b/test/functional/watchers_controller_test.rb
index ad839bac..3e4f63cf 100644
--- a/test/functional/watchers_controller_test.rb
+++ b/test/functional/watchers_controller_test.rb
@@ -19,7 +19,8 @@ class WatchersController; def rescue_action(e) raise e end; end
class WatchersControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
- :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
+ :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers,
+ :wikis, :wiki_pages
def setup
@controller = WatchersController.new
@@ -145,9 +146,58 @@ class WatchersControllerTest < ActionController::TestCase
end
assert Issue.find(2).watched_by?(@group)
end
+
+ end
+
+ def test_new_multiple_users_watching_wiki_page
+ Role.find(1).add_permission! :add_wiki_page_watchers
+
+ @request.session[:user_id] = 2
+ @page = WikiPage.find(1)
+ assert !@page.watched_by?(User.find(2))
+ assert !@page.watched_by?(User.find(4))
+ assert !@page.watched_by?(User.find(7))
+
+ assert_difference('Watcher.count', 3) do
+ xhr :post, :new, :object_type => 'wiki_page', :object_id => '1', :user_ids => ['2','4','7']
+ assert_response :success
+ assert_select_rjs :replace_html, 'watchers'
+ end
+ @page.reload
+ assert @page.watched_by?(User.find(2))
+ assert @page.watched_by?(User.find(4))
+ assert @page.watched_by?(User.find(7))
+ end
+
+ def test_new_issue_watcher_without_permission
+ Role.find(1).remove_permission! :add_issue_watchers
+
+ @request.session[:user_id] = 2
+ assert_difference('Watcher.count',0) do
+ xhr :post, :new, :object_type => 'issue', :object_id => '2', :user_ids => ['4']
+ assert_response :forbidden
+ end
+ assert !Issue.find(2).watched_by?(User.find(4))
+
+ end
+
+ def test_remove_wiki_page_watcher_without_permission
+ Role.find(1).remove_permission! :delete_wiki_page_watchers
+
+ @request.session[:user_id] = 2
+ @page = WikiPage.find(1)
+
+ assert_difference('Watcher.count',0) do
+ xhr :post, :new, :object_type => 'wiki_page', :object_id => '1', :user_ids => ['2']
+ assert_response :forbidden
+ end
+ assert !WikiPage.find(1).watched_by?(User.find(2))
+
end
def test_remove_watcher
+ Role.find(1).add_permission! :delete_issue_watchers
+
@request.session[:user_id] = 2
assert_difference('Watcher.count', -1) do
xhr :post, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
@@ -175,4 +225,48 @@ class WatchersControllerTest < ActionController::TestCase
end
+ def test_remove_wiki_page_watcher
+ Role.find(1).add_permission! :delete_wiki_page_watchers
+
+ @request.session[:user_id] = 2
+ @page = WikiPage.find(1)
+ Watcher.create!(:user_id => 2, :watchable => @page)
+ assert @page.watched_by?(User.find(2))
+
+ assert_difference('Watcher.count', -1) do
+ xhr :post, :destroy, :object_type => 'wiki_page', :object_id => '1', :user_id => '2'
+ assert_response :success
+ assert_select_rjs :replace_html, 'watchers'
+ end
+ assert !WikiPage.find(1).watched_by?(User.find(2))
+ end
+
+ def test_remove_issue_watcher_without_permission
+ Role.find(1).remove_permission! :delete_issue_watchers
+
+ @request.session[:user_id] = 2
+ assert_difference('Watcher.count',0) do
+ xhr :post, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
+ assert_response :forbidden
+ end
+ assert Issue.find(2).watched_by?(User.find(3))
+
+ end
+
+ def test_remove_wiki_page_watcher_without_permission
+ Role.find(1).remove_permission! :delete_wiki_page_watchers
+
+ @request.session[:user_id] = 2
+ @page = WikiPage.find(1)
+ Watcher.create!(:user_id => 2, :watchable => @page)
+ assert @page.watched_by?(User.find(2))
+
+ assert_difference('Watcher.count',0) do
+ xhr :post, :destroy, :object_type => 'wiki_page', :object_id => '1', :user_id => '2'
+ assert_response :forbidden
+ end
+ assert WikiPage.find(1).watched_by?(User.find(2))
+
+ end
+
end