##// END OF EJS Templates
Adds permission to edit and delete issues by role/tracker (#285)....
Jean-Philippe Lang -
r15084:c4fd1750f703
parent child
Show More
@@ -29,11 +29,11 class ContextMenusController < ApplicationController
29 29
30 30 @allowed_statuses = @issues.map(&:new_statuses_allowed_to).reduce(:&)
31 31
32 @can = {:edit => User.current.allowed_to?(:edit_issues, @projects),
32 @can = {:edit => @issues.all?(&:attributes_editable?),
33 33 :log_time => (@project && User.current.allowed_to?(:log_time, @project)),
34 34 :copy => User.current.allowed_to?(:copy_issues, @projects) && Issue.allowed_target_projects.any?,
35 35 :add_watchers => User.current.allowed_to?(:add_issue_watchers, @projects),
36 :delete => User.current.allowed_to?(:delete_issues, @projects)
36 :delete => @issues.all?(&:deletable?)
37 37 }
38 38 if @project
39 39 if @issue
@@ -211,6 +211,10 class IssuesController < ApplicationController
211 211 unless User.current.allowed_to?(:copy_issues, @projects)
212 212 raise ::Unauthorized
213 213 end
214 else
215 unless @issues.all?(&:attributes_editable?)
216 raise ::Unauthorized
217 end
214 218 end
215 219
216 220 @allowed_projects = Issue.allowed_target_projects
@@ -263,6 +267,10 class IssuesController < ApplicationController
263 267 unless User.current.allowed_to?(:add_issues, target_projects)
264 268 raise ::Unauthorized
265 269 end
270 else
271 unless @issues.all?(&:attributes_editable?)
272 raise ::Unauthorized
273 end
266 274 end
267 275
268 276 unsaved_issues = []
@@ -316,6 +324,7 class IssuesController < ApplicationController
316 324 end
317 325
318 326 def destroy
327 raise Unauthorized unless @issues.all?(&:deletable?)
319 328 @hours = TimeEntry.where(:issue_id => @issues.map(&:id)).sum(:hours).to_f
320 329 if @hours > 0
321 330 case params[:todo]
@@ -172,14 +172,24 class Issue < ActiveRecord::Base
172 172 end
173 173 end
174 174
175 # Returns true if user or current user is allowed to edit or add a note to the issue
175 # Returns true if user or current user is allowed to edit or add notes to the issue
176 176 def editable?(user=User.current)
177 attributes_editable?(user) || user.allowed_to?(:add_issue_notes, project)
177 attributes_editable?(user) || notes_addable?(user)
178 178 end
179 179
180 180 # Returns true if user or current user is allowed to edit the issue
181 181 def attributes_editable?(user=User.current)
182 user.allowed_to?(:edit_issues, project)
182 user_tracker_permission?(user, :edit_issues)
183 end
184
185 # Returns true if user or current user is allowed to add notes to the issue
186 def notes_addable?(user=User.current)
187 user_tracker_permission?(user, :add_issue_notes)
188 end
189
190 # Returns true if user or current user is allowed to delete the issue
191 def deletable?(user=User.current)
192 user_tracker_permission?(user, :delete_issues)
183 193 end
184 194
185 195 def initialize(attributes=nil, *args)
@@ -429,10 +439,10 class Issue < ActiveRecord::Base
429 439 'custom_fields',
430 440 'lock_version',
431 441 'notes',
432 :if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) }
442 :if => lambda {|issue, user| issue.new_record? || issue.attributes_editable?(user) }
433 443
434 444 safe_attributes 'notes',
435 :if => lambda {|issue, user| user.allowed_to?(:add_issue_notes, issue.project)}
445 :if => lambda {|issue, user| issue.notes_addable?(user)}
436 446
437 447 safe_attributes 'private_notes',
438 448 :if => lambda {|issue, user| !issue.new_record? && user.allowed_to?(:set_notes_private, issue.project)}
@@ -447,7 +457,7 class Issue < ActiveRecord::Base
447 457 }
448 458
449 459 safe_attributes 'parent_issue_id',
450 :if => lambda {|issue, user| (issue.new_record? || user.allowed_to?(:edit_issues, issue.project)) &&
460 :if => lambda {|issue, user| (issue.new_record? || issue.attributes_editable?(user)) &&
451 461 user.allowed_to?(:manage_subtasks, issue.project)}
452 462
453 463 def safe_attribute_names(user=nil)
@@ -1406,6 +1416,11 class Issue < ActiveRecord::Base
1406 1416
1407 1417 private
1408 1418
1419 def user_tracker_permission?(user, permission)
1420 roles = user.roles_for_project(project).select {|r| r.has_permission?(permission)}
1421 roles.any? {|r| r.permissions_all_trackers?(permission) || r.permissions_tracker_ids?(permission, tracker_id)}
1422 end
1423
1409 1424 def after_project_change
1410 1425 # Update project_id on related time entries
1411 1426 TimeEntry.where({:issue_id => id}).update_all(["project_id = ?", project_id])
@@ -3,5 +3,5
3 3 <%= link_to l(:button_log_time), new_issue_time_entry_path(@issue), :class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project) %>
4 4 <%= watcher_link(@issue, User.current) %>
5 5 <%= link_to l(:button_copy), project_copy_issue_path(@project, @issue), :class => 'icon icon-copy' if User.current.allowed_to?(:copy_issues, @project) && Issue.allowed_target_projects.any? %>
6 <%= link_to l(:button_delete), issue_path(@issue), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'icon icon-del' if User.current.allowed_to?(:delete_issues, @project) %>
6 <%= link_to l(:button_delete), issue_path(@issue), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'icon icon-del' if @issue.deletable? %>
7 7 </div>
@@ -27,21 +27,22
27 27 <% end %>
28 28 </fieldset>
29 29 <% end %>
30
31 <fieldset><legend><%= l(:field_notes) %></legend>
32 <%= f.text_area :notes, :cols => 60, :rows => 10, :class => 'wiki-edit', :no_label => true %>
33 <%= wikitoolbar_for 'issue_notes' %>
34
35 <% if @issue.safe_attribute? 'private_notes' %>
36 <%= f.check_box :private_notes, :no_label => true %> <label for="issue_private_notes"><%= l(:field_private_notes) %></label>
30 <% if @issue.notes_addable? %>
31 <fieldset><legend><%= l(:field_notes) %></legend>
32 <%= f.text_area :notes, :cols => 60, :rows => 10, :class => 'wiki-edit', :no_label => true %>
33 <%= wikitoolbar_for 'issue_notes' %>
34
35 <% if @issue.safe_attribute? 'private_notes' %>
36 <%= f.check_box :private_notes, :no_label => true %> <label for="issue_private_notes"><%= l(:field_private_notes) %></label>
37 <% end %>
38
39 <%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %>
40 </fieldset>
41
42 <fieldset><legend><%= l(:label_attachment_plural) %></legend>
43 <p><%= render :partial => 'attachments/form', :locals => {:container => @issue} %></p>
44 </fieldset>
37 45 <% end %>
38
39 <%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %>
40 </fieldset>
41
42 <fieldset><legend><%= l(:label_attachment_plural) %></legend>
43 <p><%= render :partial => 'attachments/form', :locals => {:container => @issue} %></p>
44 </fieldset>
45 46 </div>
46 47
47 48 <%= f.hidden_field :lock_version %>
@@ -1,4 +1,4
1 <% reply_links = authorize_for('issues', 'edit') -%>
1 <% reply_links = issue.notes_addable? -%>
2 2 <% for journal in journals %>
3 3 <div id="change-<%= journal.id %>" class="<%= journal.css_classes %>">
4 4 <div id="note-<%= journal.indice %>">
@@ -77,7 +77,7 end %>
77 77 <% if @issue.description? %>
78 78 <div class="description">
79 79 <div class="contextual">
80 <%= link_to l(:button_quote), quoted_issue_path(@issue), :remote => true, :method => 'post', :class => 'icon icon-comment' if authorize_for('issues', 'edit') %>
80 <%= link_to l(:button_quote), quoted_issue_path(@issue), :remote => true, :method => 'post', :class => 'icon icon-comment' if @issue.notes_addable? %>
81 81 </div>
82 82
83 83 <p><strong><%=l(:field_description)%></strong></p>
@@ -64,7 +64,9
64 64
65 65 <div id="role-permissions-trackers">
66 66 <h3><%= l(:label_issue_tracking) %></h3>
67 <% permissions = %w(view_issues add_issues) %>
67 <% permissions = %w(view_issues add_issues edit_issues add_issue_notes delete_issues) %>
68
69 <div class="autoscroll">
68 70 <table class="list">
69 71 <thead>
70 72 <tr>
@@ -87,7 +89,7
87 89 <% end %>
88 90 </tr>
89 91 <% Tracker.sorted.all.each do |tracker| %>
90 <tr>
92 <tr class="<%= cycle("odd", "even") %>">
91 93 <td class="name"><%= tracker.name %></td>
92 94 <% permissions.each do |permission| %>
93 95 <td><%= check_box_tag "role[permissions_tracker_ids][#{permission}][]",
@@ -100,6 +102,7
100 102 <% end %>
101 103 </tbody>
102 104 </table>
105 </div>
103 106
104 107 <% permissions.each do |permission| %>
105 108 <%= hidden_field_tag "role[permissions_tracker_ids][#{permission}][]", '' %>
@@ -152,6 +152,7 table.list td.buttons img, div.buttons img {vertical-align:middle;}
152 152 table.list td.reorder {width:15%; white-space:nowrap; text-align:center; }
153 153 table.list table.progress td {padding-right:0px;}
154 154 table.list caption { text-align: left; padding: 0.5em 0.5em 0.5em 0; }
155 #role-permissions-trackers table.list th {white-space:normal;}
155 156
156 157 .table-list-cell {display: table-cell; vertical-align: top; padding:2px; }
157 158
@@ -3872,6 +3872,30 class IssuesControllerTest < ActionController::TestCase
3872 3872 assert_redirected_to '/issues/11?issue_count=3&issue_position=2&next_issue_id=12&prev_issue_id=8'
3873 3873 end
3874 3874
3875 def test_update_with_permission_on_tracker_should_be_allowed
3876 role = Role.find(1)
3877 role.set_permission_trackers :edit_issues, [1]
3878 role.save!
3879 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Original subject')
3880
3881 @request.session[:user_id] = 2
3882 put :update, :id => issue.id, :issue => {:subject => 'Changed subject'}
3883 assert_response 302
3884 assert_equal 'Changed subject', issue.reload.subject
3885 end
3886
3887 def test_update_without_permission_on_tracker_should_be_denied
3888 role = Role.find(1)
3889 role.set_permission_trackers :edit_issues, [1]
3890 role.save!
3891 issue = Issue.generate!(:project_id => 1, :tracker_id => 2, :subject => 'Original subject')
3892
3893 @request.session[:user_id] = 2
3894 put :update, :id => issue.id, :issue => {:subject => 'Changed subject'}
3895 assert_response 302
3896 assert_equal 'Original subject', issue.reload.subject
3897 end
3898
3875 3899 def test_get_bulk_edit
3876 3900 @request.session[:user_id] = 2
3877 3901 get :bulk_edit, :ids => [1, 3]
@@ -4702,6 +4726,32 class IssuesControllerTest < ActionController::TestCase
4702 4726 assert_response 404
4703 4727 end
4704 4728
4729 def test_destroy_with_permission_on_tracker_should_be_allowed
4730 role = Role.find(1)
4731 role.set_permission_trackers :delete_issues, [1]
4732 role.save!
4733 issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
4734
4735 @request.session[:user_id] = 2
4736 assert_difference 'Issue.count', -1 do
4737 delete :destroy, :id => issue.id
4738 end
4739 assert_response 302
4740 end
4741
4742 def test_destroy_without_permission_on_tracker_should_be_denied
4743 role = Role.find(1)
4744 role.set_permission_trackers :delete_issues, [2]
4745 role.save!
4746 issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
4747
4748 @request.session[:user_id] = 2
4749 assert_no_difference 'Issue.count' do
4750 delete :destroy, :id => issue.id
4751 end
4752 assert_response 403
4753 end
4754
4705 4755 def test_default_search_scope
4706 4756 get :index
4707 4757
General Comments 0
You need to be logged in to leave comments. Login now