@@ -16,7 +16,9 | |||||
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 IssueRelationsController < ApplicationController |
|
18 | class IssueRelationsController < ApplicationController | |
19 | before_filter :find_issue, :find_project_from_association, :authorize |
|
19 | before_filter :find_issue, :find_project_from_association, :authorize, :only => [:index, :create] | |
|
20 | before_filter :find_relation, :except => [:index, :create] | |||
|
21 | ||||
20 | accept_key_auth :index, :show, :create, :destroy |
|
22 | accept_key_auth :index, :show, :create, :destroy | |
21 |
|
23 | |||
22 | def index |
|
24 | def index | |
@@ -29,7 +31,7 class IssueRelationsController < ApplicationController | |||||
29 | end |
|
31 | end | |
30 |
|
32 | |||
31 | def show |
|
33 | def show | |
32 | @relation = @issue.find_relation(params[:id]) |
|
34 | raise Unauthorized unless @relation.visible? | |
33 |
|
35 | |||
34 | respond_to do |format| |
|
36 | respond_to do |format| | |
35 | format.html { render :nothing => true } |
|
37 | format.html { render :nothing => true } | |
@@ -62,7 +64,7 class IssueRelationsController < ApplicationController | |||||
62 | end |
|
64 | end | |
63 | format.api { |
|
65 | format.api { | |
64 | if saved |
|
66 | if saved | |
65 |
render :action => 'show', :status => :created, :location => |
|
67 | render :action => 'show', :status => :created, :location => relation_url(@relation) | |
66 | else |
|
68 | else | |
67 | render_validation_errors(@relation) |
|
69 | render_validation_errors(@relation) | |
68 | end |
|
70 | end | |
@@ -72,16 +74,13 class IssueRelationsController < ApplicationController | |||||
72 |
|
74 | |||
73 | verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed } |
|
75 | verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed } | |
74 | def destroy |
|
76 | def destroy | |
75 | relation = @issue.find_relation(params[:id]) |
|
77 | raise Unauthorized unless @relation.deletable? | |
76 | relation.destroy |
|
78 | @relation.destroy | |
77 |
|
79 | |||
78 | respond_to do |format| |
|
80 | respond_to do |format| | |
79 | format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue } |
|
81 | format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue } | |
80 | format.js { |
|
82 | format.js { render(:update) {|page| page.remove "relation-#{@relation.id}"} } | |
81 | @relations = @issue.reload.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? } |
|
83 | format.api { head :ok } | |
82 | render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'} |
|
|||
83 | } |
|
|||
84 | format.api { head :ok } |
|
|||
85 | end |
|
84 | end | |
86 | rescue ActiveRecord::RecordNotFound |
|
85 | rescue ActiveRecord::RecordNotFound | |
87 | render_404 |
|
86 | render_404 | |
@@ -93,4 +92,10 private | |||||
93 | rescue ActiveRecord::RecordNotFound |
|
92 | rescue ActiveRecord::RecordNotFound | |
94 | render_404 |
|
93 | render_404 | |
95 | end |
|
94 | end | |
|
95 | ||||
|
96 | def find_relation | |||
|
97 | @relation = IssueRelation.find(params[:id]) | |||
|
98 | rescue ActiveRecord::RecordNotFound | |||
|
99 | render_404 | |||
|
100 | end | |||
96 | end |
|
101 | end |
@@ -43,6 +43,16 class IssueRelation < ActiveRecord::Base | |||||
43 |
|
43 | |||
44 | attr_protected :issue_from_id, :issue_to_id |
|
44 | attr_protected :issue_from_id, :issue_to_id | |
45 |
|
45 | |||
|
46 | def visible?(user=User.current) | |||
|
47 | (issue_from.nil? || issue_from.visible?(user)) && (issue_to.nil? || issue_to.visible?(user)) | |||
|
48 | end | |||
|
49 | ||||
|
50 | def deletable?(user=User.current) | |||
|
51 | visible?(user) && | |||
|
52 | ((issue_from.nil? || user.allowed_to?(:manage_issue_relations, issue_from.project)) || | |||
|
53 | (issue_to.nil? || user.allowed_to?(:manage_issue_relations, issue_to.project))) | |||
|
54 | end | |||
|
55 | ||||
46 | def after_initialize |
|
56 | def after_initialize | |
47 | if new_record? |
|
57 | if new_record? | |
48 | if relation_type.blank? |
|
58 | if relation_type.blank? |
@@ -2,6 +2,6 api.relation do | |||||
2 | api.id @relation.id |
|
2 | api.id @relation.id | |
3 | api.issue_id @relation.issue_from_id |
|
3 | api.issue_id @relation.issue_from_id | |
4 | api.issue_to_id @relation.issue_to_id |
|
4 | api.issue_to_id @relation.issue_to_id | |
5 |
api.relation_type @relation.relation_type |
|
5 | api.relation_type @relation.relation_type | |
6 | api.delay @relation.delay |
|
6 | api.delay @relation.delay | |
7 | end |
|
7 | end |
@@ -10,7 +10,7 | |||||
10 | <form> |
|
10 | <form> | |
11 | <table class="list issues"> |
|
11 | <table class="list issues"> | |
12 | <% @relations.each do |relation| %> |
|
12 | <% @relations.each do |relation| %> | |
13 | <tr class="issue hascontextmenu"> |
|
13 | <tr class="issue hascontextmenu" id="relation-<%= relation.id %>"> | |
14 | <td class="checkbox"><%= check_box_tag("ids[]", relation.other_issue(@issue).id, false, :id => nil) %></td> |
|
14 | <td class="checkbox"><%= check_box_tag("ids[]", relation.other_issue(@issue).id, false, :id => nil) %></td> | |
15 | <td class="subject"><%= l(relation.label_for(@issue)) %> <%= "(#{l('datetime.distance_in_words.x_days', :count => relation.delay)})" if relation.delay && relation.delay != 0 %> |
|
15 | <td class="subject"><%= l(relation.label_for(@issue)) %> <%= "(#{l('datetime.distance_in_words.x_days', :count => relation.delay)})" if relation.delay && relation.delay != 0 %> | |
16 | <%= h(relation.other_issue(@issue).project) + ' - ' if Setting.cross_project_issue_relations? %> |
|
16 | <%= h(relation.other_issue(@issue).project) + ' - ' if Setting.cross_project_issue_relations? %> | |
@@ -19,7 +19,7 | |||||
19 | <td class="status"><%= relation.other_issue(@issue).status.name %></td> |
|
19 | <td class="status"><%= relation.other_issue(@issue).status.name %></td> | |
20 | <td class="start_date"><%= format_date(relation.other_issue(@issue).start_date) %></td> |
|
20 | <td class="start_date"><%= format_date(relation.other_issue(@issue).start_date) %></td> | |
21 | <td class="due_date"><%= format_date(relation.other_issue(@issue).due_date) %></td> |
|
21 | <td class="due_date"><%= format_date(relation.other_issue(@issue).due_date) %></td> | |
22 |
<td class="buttons"><%= link_to_remote(image_tag('link_break.png'), { :url => {:controller => 'issue_relations', :action => 'destroy', |
|
22 | <td class="buttons"><%= link_to_remote(image_tag('link_break.png'), { :url => {:controller => 'issue_relations', :action => 'destroy', :id => relation}, | |
23 | :method => :delete |
|
23 | :method => :delete | |
24 | }, :title => l(:label_relation_delete)) if authorize_for('issue_relations', 'destroy') %></td> |
|
24 | }, :title => l(:label_relation_delete)) if authorize_for('issue_relations', 'destroy') %></td> | |
25 | </tr> |
|
25 | </tr> |
@@ -110,7 +110,7 ActionController::Routing::Routes.draw do |map| | |||||
110 |
|
110 | |||
111 | map.resources :issues, :member => { :edit => :post }, :collection => {} do |issues| |
|
111 | map.resources :issues, :member => { :edit => :post }, :collection => {} do |issues| | |
112 | issues.resources :time_entries, :controller => 'timelog' |
|
112 | issues.resources :time_entries, :controller => 'timelog' | |
113 | issues.resources :relations, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy] |
|
113 | issues.resources :relations, :shallow => true, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy] | |
114 | end |
|
114 | end | |
115 |
|
115 | |||
116 | map.resources :issues, :path_prefix => '/projects/:project_id', :collection => { :create => :post } do |issues| |
|
116 | map.resources :issues, :path_prefix => '/projects/:project_id', :collection => { :create => :post } do |issues| |
@@ -97,7 +97,7 class IssueRelationsControllerTest < ActionController::TestCase | |||||
97 | def test_destroy |
|
97 | def test_destroy | |
98 | assert_difference 'IssueRelation.count', -1 do |
|
98 | assert_difference 'IssueRelation.count', -1 do | |
99 | @request.session[:user_id] = 3 |
|
99 | @request.session[:user_id] = 3 | |
100 |
delete :destroy, :id => '2' |
|
100 | delete :destroy, :id => '2' | |
101 | end |
|
101 | end | |
102 | end |
|
102 | end | |
103 |
|
103 | |||
@@ -109,11 +109,8 class IssueRelationsControllerTest < ActionController::TestCase | |||||
109 |
|
109 | |||
110 | assert_difference 'IssueRelation.count', -1 do |
|
110 | assert_difference 'IssueRelation.count', -1 do | |
111 | @request.session[:user_id] = 3 |
|
111 | @request.session[:user_id] = 3 | |
112 |
xhr :delete, :destroy, :id => '2' |
|
112 | xhr :delete, :destroy, :id => '2' | |
113 |
assert_select_rjs 'relation |
|
113 | assert_select_rjs :remove, 'relation-2' | |
114 | assert_select 'table', 1 |
|
|||
115 | assert_select 'tr', 1 # relation left |
|
|||
116 | end |
|
|||
117 | end |
|
114 | end | |
118 | end |
|
115 | end | |
119 | end |
|
116 | end |
@@ -73,10 +73,10 class ApiTest::IssueRelationsTest < ActionController::IntegrationTest | |||||
73 | end |
|
73 | end | |
74 | end |
|
74 | end | |
75 |
|
75 | |||
76 |
context " |
|
76 | context "/relations/:id" do | |
77 | context "GET" do |
|
77 | context "GET" do | |
78 | should "return the relation" do |
|
78 | should "return the relation" do | |
79 |
get '/ |
|
79 | get '/relations/2.xml', {}, :authorization => credentials('jsmith') | |
80 |
|
80 | |||
81 | assert_response :success |
|
81 | assert_response :success | |
82 | assert_equal 'application/xml', @response.content_type |
|
82 | assert_equal 'application/xml', @response.content_type | |
@@ -87,7 +87,7 class ApiTest::IssueRelationsTest < ActionController::IntegrationTest | |||||
87 | context "DELETE" do |
|
87 | context "DELETE" do | |
88 | should "delete the relation" do |
|
88 | should "delete the relation" do | |
89 | assert_difference('IssueRelation.count', -1) do |
|
89 | assert_difference('IssueRelation.count', -1) do | |
90 |
delete '/ |
|
90 | delete '/relations/2.xml', {}, :authorization => credentials('jsmith') | |
91 | end |
|
91 | end | |
92 |
|
92 | |||
93 | assert_response :ok |
|
93 | assert_response :ok |
@@ -126,13 +126,13 class RoutingTest < ActionController::IntegrationTest | |||||
126 | should_route :post, "/issues/1/relations.xml", :controller => 'issue_relations', :action => 'create', :issue_id => '1', :format => 'xml' |
|
126 | should_route :post, "/issues/1/relations.xml", :controller => 'issue_relations', :action => 'create', :issue_id => '1', :format => 'xml' | |
127 | should_route :post, "/issues/1/relations.json", :controller => 'issue_relations', :action => 'create', :issue_id => '1', :format => 'json' |
|
127 | should_route :post, "/issues/1/relations.json", :controller => 'issue_relations', :action => 'create', :issue_id => '1', :format => 'json' | |
128 |
|
128 | |||
129 |
should_route :get, " |
|
129 | should_route :get, "/relations/23", :controller => 'issue_relations', :action => 'show', :id => '23' | |
130 |
should_route :get, " |
|
130 | should_route :get, "/relations/23.xml", :controller => 'issue_relations', :action => 'show', :id => '23', :format => 'xml' | |
131 |
should_route :get, " |
|
131 | should_route :get, "/relations/23.json", :controller => 'issue_relations', :action => 'show', :id => '23', :format => 'json' | |
132 |
|
132 | |||
133 |
should_route :delete, " |
|
133 | should_route :delete, "/relations/23", :controller => 'issue_relations', :action => 'destroy', :id => '23' | |
134 |
should_route :delete, " |
|
134 | should_route :delete, "/relations/23.xml", :controller => 'issue_relations', :action => 'destroy', :id => '23', :format => 'xml' | |
135 |
should_route :delete, " |
|
135 | should_route :delete, "/relations/23.json", :controller => 'issue_relations', :action => 'destroy', :id => '23', :format => 'json' | |
136 | end |
|
136 | end | |
137 |
|
137 | |||
138 | context "issue reports" do |
|
138 | context "issue reports" do |
General Comments 0
You need to be logged in to leave comments.
Login now