##// END OF EJS Templates
Make sure user can not watch what he is not allowed to view....
Jean-Philippe Lang -
r3056:9a452a5c351f
parent child
Show More
@@ -1,97 +1,101
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 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 class WatchersController < ApplicationController
18 class WatchersController < ApplicationController
19 before_filter :find_project
19 before_filter :find_project
20 before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch]
20 before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch]
21 before_filter :authorize, :only => [:new, :destroy]
21 before_filter :authorize, :only => [:new, :destroy]
22
22
23 verify :method => :post,
23 verify :method => :post,
24 :only => [ :watch, :unwatch ],
24 :only => [ :watch, :unwatch ],
25 :render => { :nothing => true, :status => :method_not_allowed }
25 :render => { :nothing => true, :status => :method_not_allowed }
26
26
27 def watch
27 def watch
28 set_watcher(User.current, true)
28 if @watched.respond_to?(:visible?) && !@watched.visible?(User.current)
29 render_403
30 else
31 set_watcher(User.current, true)
32 end
29 end
33 end
30
34
31 def unwatch
35 def unwatch
32 set_watcher(User.current, false)
36 set_watcher(User.current, false)
33 end
37 end
34
38
35 def new
39 def new
36 @watcher = Watcher.new(params[:watcher])
40 @watcher = Watcher.new(params[:watcher])
37 @watcher.watchable = @watched
41 @watcher.watchable = @watched
38 @watcher.save if request.post?
42 @watcher.save if request.post?
39 respond_to do |format|
43 respond_to do |format|
40 format.html { redirect_to :back }
44 format.html { redirect_to :back }
41 format.js do
45 format.js do
42 render :update do |page|
46 render :update do |page|
43 page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
47 page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
44 end
48 end
45 end
49 end
46 end
50 end
47 rescue ::ActionController::RedirectBackError
51 rescue ::ActionController::RedirectBackError
48 render :text => 'Watcher added.', :layout => true
52 render :text => 'Watcher added.', :layout => true
49 end
53 end
50
54
51 def destroy
55 def destroy
52 @watched.set_watcher(User.find(params[:user_id]), false) if request.post?
56 @watched.set_watcher(User.find(params[:user_id]), false) if request.post?
53 respond_to do |format|
57 respond_to do |format|
54 format.html { redirect_to :back }
58 format.html { redirect_to :back }
55 format.js do
59 format.js do
56 render :update do |page|
60 render :update do |page|
57 page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
61 page.replace_html 'watchers', :partial => 'watchers/watchers', :locals => {:watched => @watched}
58 end
62 end
59 end
63 end
60 end
64 end
61 end
65 end
62
66
63 private
67 private
64 def find_project
68 def find_project
65 klass = Object.const_get(params[:object_type].camelcase)
69 klass = Object.const_get(params[:object_type].camelcase)
66 return false unless klass.respond_to?('watched_by')
70 return false unless klass.respond_to?('watched_by')
67 @watched = klass.find(params[:object_id])
71 @watched = klass.find(params[:object_id])
68 @project = @watched.project
72 @project = @watched.project
69 rescue
73 rescue
70 render_404
74 render_404
71 end
75 end
72
76
73 def set_watcher(user, watching)
77 def set_watcher(user, watching)
74 @watched.set_watcher(user, watching)
78 @watched.set_watcher(user, watching)
75 if params[:replace].present?
79 if params[:replace].present?
76 if params[:replace].is_a? Array
80 if params[:replace].is_a? Array
77 replace_ids = params[:replace]
81 replace_ids = params[:replace]
78 else
82 else
79 replace_ids = [params[:replace]]
83 replace_ids = [params[:replace]]
80 end
84 end
81 else
85 else
82 replace_ids = 'watcher'
86 replace_ids = 'watcher'
83 end
87 end
84 respond_to do |format|
88 respond_to do |format|
85 format.html { redirect_to :back }
89 format.html { redirect_to :back }
86 format.js do
90 format.js do
87 render(:update) do |page|
91 render(:update) do |page|
88 replace_ids.each do |replace_id|
92 replace_ids.each do |replace_id|
89 page.replace_html replace_id, watcher_link(@watched, user, :replace => replace_ids)
93 page.replace_html replace_id, watcher_link(@watched, user, :replace => replace_ids)
90 end
94 end
91 end
95 end
92 end
96 end
93 end
97 end
94 rescue ::ActionController::RedirectBackError
98 rescue ::ActionController::RedirectBackError
95 render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true
99 render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true
96 end
100 end
97 end
101 end
@@ -1,101 +1,110
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 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.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'watchers_controller'
19 require 'watchers_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class WatchersController; def rescue_action(e) raise e end; end
22 class WatchersController; def rescue_action(e) raise e end; end
23
23
24 class WatchersControllerTest < ActionController::TestCase
24 class WatchersControllerTest < ActionController::TestCase
25 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
25 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
26 :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
26 :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
27
27
28 def setup
28 def setup
29 @controller = WatchersController.new
29 @controller = WatchersController.new
30 @request = ActionController::TestRequest.new
30 @request = ActionController::TestRequest.new
31 @response = ActionController::TestResponse.new
31 @response = ActionController::TestResponse.new
32 User.current = nil
32 User.current = nil
33 end
33 end
34
34
35 def test_get_watch_should_be_invalid
35 def test_get_watch_should_be_invalid
36 @request.session[:user_id] = 3
36 @request.session[:user_id] = 3
37 get :watch, :object_type => 'issue', :object_id => '1'
37 get :watch, :object_type => 'issue', :object_id => '1'
38 assert_response 405
38 assert_response 405
39 end
39 end
40
40
41 def test_watch
41 def test_watch
42 @request.session[:user_id] = 3
42 @request.session[:user_id] = 3
43 assert_difference('Watcher.count') do
43 assert_difference('Watcher.count') do
44 xhr :post, :watch, :object_type => 'issue', :object_id => '1'
44 xhr :post, :watch, :object_type => 'issue', :object_id => '1'
45 assert_response :success
45 assert_response :success
46 assert_select_rjs :replace_html, 'watcher'
46 assert_select_rjs :replace_html, 'watcher'
47 end
47 end
48 assert Issue.find(1).watched_by?(User.find(3))
48 assert Issue.find(1).watched_by?(User.find(3))
49 end
49 end
50
51 def test_watch_should_be_denied_without_permission
52 Role.find(2).remove_permission! :view_issues
53 @request.session[:user_id] = 3
54 assert_no_difference('Watcher.count') do
55 xhr :post, :watch, :object_type => 'issue', :object_id => '1'
56 assert_response 403
57 end
58 end
50
59
51 def test_watch_with_multiple_replacements
60 def test_watch_with_multiple_replacements
52 @request.session[:user_id] = 3
61 @request.session[:user_id] = 3
53 assert_difference('Watcher.count') do
62 assert_difference('Watcher.count') do
54 xhr :post, :watch, :object_type => 'issue', :object_id => '1', :replace => ['watch_item_1','watch_item_2']
63 xhr :post, :watch, :object_type => 'issue', :object_id => '1', :replace => ['watch_item_1','watch_item_2']
55 assert_response :success
64 assert_response :success
56 assert_select_rjs :replace_html, 'watch_item_1'
65 assert_select_rjs :replace_html, 'watch_item_1'
57 assert_select_rjs :replace_html, 'watch_item_2'
66 assert_select_rjs :replace_html, 'watch_item_2'
58 end
67 end
59 end
68 end
60
69
61 def test_unwatch
70 def test_unwatch
62 @request.session[:user_id] = 3
71 @request.session[:user_id] = 3
63 assert_difference('Watcher.count', -1) do
72 assert_difference('Watcher.count', -1) do
64 xhr :post, :unwatch, :object_type => 'issue', :object_id => '2'
73 xhr :post, :unwatch, :object_type => 'issue', :object_id => '2'
65 assert_response :success
74 assert_response :success
66 assert_select_rjs :replace_html, 'watcher'
75 assert_select_rjs :replace_html, 'watcher'
67 end
76 end
68 assert !Issue.find(1).watched_by?(User.find(3))
77 assert !Issue.find(1).watched_by?(User.find(3))
69 end
78 end
70
79
71 def test_unwatch_with_multiple_replacements
80 def test_unwatch_with_multiple_replacements
72 @request.session[:user_id] = 3
81 @request.session[:user_id] = 3
73 assert_difference('Watcher.count', -1) do
82 assert_difference('Watcher.count', -1) do
74 xhr :post, :unwatch, :object_type => 'issue', :object_id => '2', :replace => ['watch_item_1', 'watch_item_2']
83 xhr :post, :unwatch, :object_type => 'issue', :object_id => '2', :replace => ['watch_item_1', 'watch_item_2']
75 assert_response :success
84 assert_response :success
76 assert_select_rjs :replace_html, 'watch_item_1'
85 assert_select_rjs :replace_html, 'watch_item_1'
77 assert_select_rjs :replace_html, 'watch_item_2'
86 assert_select_rjs :replace_html, 'watch_item_2'
78 end
87 end
79 assert !Issue.find(1).watched_by?(User.find(3))
88 assert !Issue.find(1).watched_by?(User.find(3))
80 end
89 end
81
90
82 def test_new_watcher
91 def test_new_watcher
83 @request.session[:user_id] = 2
92 @request.session[:user_id] = 2
84 assert_difference('Watcher.count') do
93 assert_difference('Watcher.count') do
85 xhr :post, :new, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'}
94 xhr :post, :new, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'}
86 assert_response :success
95 assert_response :success
87 assert_select_rjs :replace_html, 'watchers'
96 assert_select_rjs :replace_html, 'watchers'
88 end
97 end
89 assert Issue.find(2).watched_by?(User.find(4))
98 assert Issue.find(2).watched_by?(User.find(4))
90 end
99 end
91
100
92 def test_remove_watcher
101 def test_remove_watcher
93 @request.session[:user_id] = 2
102 @request.session[:user_id] = 2
94 assert_difference('Watcher.count', -1) do
103 assert_difference('Watcher.count', -1) do
95 xhr :post, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
104 xhr :post, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
96 assert_response :success
105 assert_response :success
97 assert_select_rjs :replace_html, 'watchers'
106 assert_select_rjs :replace_html, 'watchers'
98 end
107 end
99 assert !Issue.find(2).watched_by?(User.find(3))
108 assert !Issue.find(2).watched_by?(User.find(3))
100 end
109 end
101 end
110 end
General Comments 0
You need to be logged in to leave comments. Login now