##// END OF EJS Templates
Add/remove issue watchers via the REST API (#6727)....
Jean-Philippe Lang -
r11060:a0158eff9643
parent child
Show More
@@ -19,6 +19,7 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 accept_api_auth :create, :destroy
22
23
23 def watch
24 def watch
24 if @watched.respond_to?(:visible?) && !@watched.visible?(User.current)
25 if @watched.respond_to?(:visible?) && !@watched.visible?(User.current)
@@ -36,15 +37,19 class WatchersController < ApplicationController
36 end
37 end
37
38
38 def create
39 def create
39 if params[:watcher].is_a?(Hash) && request.post?
40 user_ids = []
40 user_ids = params[:watcher][:user_ids] || [params[:watcher][:user_id]]
41 if params[:watcher].is_a?(Hash)
41 user_ids.each do |user_id|
42 user_ids << (params[:watcher][:user_ids] || params[:watcher][:user_id])
42 Watcher.create(:watchable => @watched, :user_id => user_id)
43 else
44 user_ids << params[:user_id]
43 end
45 end
46 user_ids.flatten.compact.uniq.each do |user_id|
47 Watcher.create(:watchable => @watched, :user_id => user_id)
44 end
48 end
45 respond_to do |format|
49 respond_to do |format|
46 format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}}
50 format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}}
47 format.js
51 format.js
52 format.api { render_api_ok }
48 end
53 end
49 end
54 end
50
55
@@ -56,10 +61,11 class WatchersController < ApplicationController
56 end
61 end
57
62
58 def destroy
63 def destroy
59 @watched.set_watcher(User.find(params[:user_id]), false) if request.post?
64 @watched.set_watcher(User.find(params[:user_id]), false)
60 respond_to do |format|
65 respond_to do |format|
61 format.html { redirect_to :back }
66 format.html { redirect_to :back }
62 format.js
67 format.js
68 format.api { render_api_ok }
63 end
69 end
64 end
70 end
65
71
@@ -64,4 +64,10 api.issue do
64 end
64 end
65 end
65 end
66 end if include_in_api_response?('journals')
66 end if include_in_api_response?('journals')
67
68 api.array :watchers do
69 @issue.watcher_users.each do |user|
70 api.user :id => user.id, :name => user.name
71 end
72 end if include_in_api_response?('watchers') && User.current.allowed_to?(:view_issue_watchers, @issue.project)
67 end
73 end
@@ -84,6 +84,9 RedmineApp::Application.routes.draw do
84 match 'watchers/watch', :controller=> 'watchers', :action => 'watch', :via => :post
84 match 'watchers/watch', :controller=> 'watchers', :action => 'watch', :via => :post
85 match 'watchers/unwatch', :controller=> 'watchers', :action => 'unwatch', :via => :post
85 match 'watchers/unwatch', :controller=> 'watchers', :action => 'unwatch', :via => :post
86 match 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user', :via => :get
86 match 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user', :via => :get
87 # Specific routes for issue watchers API
88 post 'issues/:object_id/watchers', :to => 'watchers#create', :object_type => 'issue'
89 delete 'issues/:object_id/watchers/:user_id' => 'watchers#destroy', :object_type => 'issue'
87
90
88 resources :projects do
91 resources :projects do
89 member do
92 member do
@@ -453,6 +453,21 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
453 end
453 end
454 end
454 end
455
455
456 test "GET /issues/:id.xml?include=watchers should include watchers" do
457 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
458
459 get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
460
461 assert_response :ok
462 assert_equal 'application/xml', response.content_type
463 assert_select 'issue' do
464 assert_select 'watchers', Issue.find(1).watchers.count
465 assert_select 'watchers' do
466 assert_select 'user[id=3]'
467 end
468 end
469 end
470
456 context "POST /issues.xml" do
471 context "POST /issues.xml" do
457 should_allow_api_authentication(
472 should_allow_api_authentication(
458 :post,
473 :post,
@@ -478,6 +493,18 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
478 end
493 end
479 end
494 end
480
495
496 test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
497 assert_difference('Issue.count') do
498 post '/issues.xml',
499 {:issue => {:project_id => 1, :subject => 'Watchers',
500 :tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
501 assert_response :created
502 end
503 issue = Issue.order('id desc').first
504 assert_equal 2, issue.watchers.size
505 assert_equal [1, 3], issue.watcher_user_ids.sort
506 end
507
481 context "POST /issues.xml with failure" do
508 context "POST /issues.xml with failure" do
482 should "have an errors tag" do
509 should "have an errors tag" do
483 assert_no_difference('Issue.count') do
510 assert_no_difference('Issue.count') do
@@ -720,6 +747,30 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
720 end
747 end
721 end
748 end
722
749
750 test "POST /issues/:id/watchers.xml should add watcher" do
751 assert_difference 'Watcher.count' do
752 post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
753
754 assert_response :ok
755 assert_equal '', response.body
756 end
757 watcher = Watcher.order('id desc').first
758 assert_equal Issue.find(1), watcher.watchable
759 assert_equal User.find(3), watcher.user
760 end
761
762 test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
763 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
764
765 assert_difference 'Watcher.count', -1 do
766 delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
767
768 assert_response :ok
769 assert_equal '', response.body
770 end
771 assert_equal false, Issue.find(1).watched_by?(User.find(3))
772 end
773
723 def test_create_issue_with_uploaded_file
774 def test_create_issue_with_uploaded_file
724 set_tmp_attachments_directory
775 set_tmp_attachments_directory
725 # upload the file
776 # upload the file
@@ -47,5 +47,15 class RoutingWatchersTest < ActionController::IntegrationTest
47 { :method => 'post', :path => "/watchers/unwatch" },
47 { :method => 'post', :path => "/watchers/unwatch" },
48 { :controller => 'watchers', :action => 'unwatch' }
48 { :controller => 'watchers', :action => 'unwatch' }
49 )
49 )
50 assert_routing(
51 { :method => 'post', :path => "/issues/12/watchers.xml" },
52 { :controller => 'watchers', :action => 'create',
53 :object_type => 'issue', :object_id => '12', :format => 'xml' }
54 )
55 assert_routing(
56 { :method => 'delete', :path => "/issues/12/watchers/3.xml" },
57 { :controller => 'watchers', :action => 'destroy',
58 :object_type => 'issue', :object_id => '12', :user_id => '3', :format => 'xml'}
59 )
50 end
60 end
51 end
61 end
General Comments 0
You need to be logged in to leave comments. Login now