@@ -0,0 +1,5 | |||||
|
1 | class AddRolesSettings < ActiveRecord::Migration | |||
|
2 | def change | |||
|
3 | add_column :roles, :settings, :text | |||
|
4 | end | |||
|
5 | end No newline at end of file |
@@ -467,7 +467,13 class IssuesController < ApplicationController | |||||
467 | if @issue.project |
|
467 | if @issue.project | |
468 | @issue.tracker ||= @issue.allowed_target_trackers.first |
|
468 | @issue.tracker ||= @issue.allowed_target_trackers.first | |
469 | if @issue.tracker.nil? |
|
469 | if @issue.tracker.nil? | |
470 | render_error l(:error_no_tracker_in_project) |
|
470 | if @issue.project.trackers.any? | |
|
471 | # None of the project trackers is allowed to the user | |||
|
472 | render_error :message => l(:error_no_tracker_allowed_for_new_issue_in_project), :status => 403 | |||
|
473 | else | |||
|
474 | # Project has no trackers | |||
|
475 | render_error l(:error_no_tracker_in_project) | |||
|
476 | end | |||
471 | return false |
|
477 | return false | |
472 | end |
|
478 | end | |
473 | if @issue.status.nil? |
|
479 | if @issue.status.nil? |
@@ -1368,16 +1368,27 class Issue < ActiveRecord::Base | |||||
1368 |
|
1368 | |||
1369 | # Returns a scope of trackers that user can assign the issue to |
|
1369 | # Returns a scope of trackers that user can assign the issue to | |
1370 | def allowed_target_trackers(user=User.current) |
|
1370 | def allowed_target_trackers(user=User.current) | |
1371 | if project |
|
1371 | self.class.allowed_target_trackers(project, user, tracker_id_was) | |
1372 | self.class.allowed_target_trackers(project, user, tracker_id_was) |
|
|||
1373 | else |
|
|||
1374 | Tracker.none |
|
|||
1375 | end |
|
|||
1376 | end |
|
1372 | end | |
1377 |
|
1373 | |||
1378 | # Returns a scope of trackers that user can assign project issues to |
|
1374 | # Returns a scope of trackers that user can assign project issues to | |
1379 | def self.allowed_target_trackers(project, user=User.current, current_tracker=nil) |
|
1375 | def self.allowed_target_trackers(project, user=User.current, current_tracker=nil) | |
1380 | project.trackers.sorted |
|
1376 | if project | |
|
1377 | scope = project.trackers.sorted | |||
|
1378 | unless user.admin? | |||
|
1379 | roles = user.roles_for_project(project).select {|r| r.has_permission?(:add_issues)} | |||
|
1380 | unless roles.any? {|r| r.permissions_all_trackers?(:add_issues)} | |||
|
1381 | tracker_ids = roles.map {|r| r.permissions_tracker_ids(:add_issues)}.flatten.uniq | |||
|
1382 | if current_tracker | |||
|
1383 | tracker_ids << current_tracker | |||
|
1384 | end | |||
|
1385 | scope = scope.where(:id => tracker_ids) | |||
|
1386 | end | |||
|
1387 | end | |||
|
1388 | scope | |||
|
1389 | else | |||
|
1390 | Tracker.none | |||
|
1391 | end | |||
1381 | end |
|
1392 | end | |
1382 |
|
1393 | |||
1383 | private |
|
1394 | private |
@@ -37,7 +37,7 class IssueImport < Import | |||||
37 | # Returns a scope of trackers that user is allowed to |
|
37 | # Returns a scope of trackers that user is allowed to | |
38 | # import issue to |
|
38 | # import issue to | |
39 | def allowed_target_trackers |
|
39 | def allowed_target_trackers | |
40 | project.trackers |
|
40 | Issue.allowed_target_trackers(project, user) | |
41 | end |
|
41 | end | |
42 |
|
42 | |||
43 | def tracker |
|
43 | def tracker |
@@ -73,6 +73,7 class Role < ActiveRecord::Base | |||||
73 | acts_as_positioned :scope => :builtin |
|
73 | acts_as_positioned :scope => :builtin | |
74 |
|
74 | |||
75 | serialize :permissions, ::Role::PermissionsAttributeCoder |
|
75 | serialize :permissions, ::Role::PermissionsAttributeCoder | |
|
76 | store :settings, :accessors => [:permissions_all_trackers, :permissions_tracker_ids] | |||
76 | attr_protected :builtin |
|
77 | attr_protected :builtin | |
77 |
|
78 | |||
78 | validates_presence_of :name |
|
79 | validates_presence_of :name | |
@@ -188,6 +189,56 class Role < ActiveRecord::Base | |||||
188 | setable_permissions |
|
189 | setable_permissions | |
189 | end |
|
190 | end | |
190 |
|
191 | |||
|
192 | def permissions_tracker_ids(*args) | |||
|
193 | if args.any? | |||
|
194 | Array(permissions_tracker_ids[args.first.to_s]).map(&:to_i) | |||
|
195 | else | |||
|
196 | super || {} | |||
|
197 | end | |||
|
198 | end | |||
|
199 | ||||
|
200 | def permissions_tracker_ids=(arg) | |||
|
201 | h = arg.to_hash | |||
|
202 | h.values.each {|v| v.reject!(&:blank?)} | |||
|
203 | super(h) | |||
|
204 | end | |||
|
205 | ||||
|
206 | # Returns true if tracker_id belongs to the list of | |||
|
207 | # trackers for which permission is given | |||
|
208 | def permissions_tracker_ids?(permission, tracker_id) | |||
|
209 | permissions_tracker_ids(permission).include?(tracker_id) | |||
|
210 | end | |||
|
211 | ||||
|
212 | def permissions_all_trackers | |||
|
213 | super || {} | |||
|
214 | end | |||
|
215 | ||||
|
216 | def permissions_all_trackers=(arg) | |||
|
217 | super(arg.to_hash) | |||
|
218 | end | |||
|
219 | ||||
|
220 | # Returns true if permission is given for all trackers | |||
|
221 | def permissions_all_trackers?(permission) | |||
|
222 | permissions_all_trackers[permission.to_s].to_s != '0' | |||
|
223 | end | |||
|
224 | ||||
|
225 | # Sets the trackers that are allowed for a permission. | |||
|
226 | # tracker_ids can be an array of tracker ids or :all for | |||
|
227 | # no restrictions. | |||
|
228 | # | |||
|
229 | # Examples: | |||
|
230 | # role.set_permission_trackers :add_issues, [1, 3] | |||
|
231 | # role.set_permission_trackers :add_issues, :all | |||
|
232 | def set_permission_trackers(permission, tracker_ids) | |||
|
233 | h = {permission.to_s => (tracker_ids == :all ? '1' : '0')} | |||
|
234 | self.permissions_all_trackers = permissions_all_trackers.merge(h) | |||
|
235 | ||||
|
236 | h = {permission.to_s => (tracker_ids == :all ? [] : tracker_ids)} | |||
|
237 | self.permissions_tracker_ids = permissions_tracker_ids.merge(h) | |||
|
238 | ||||
|
239 | self | |||
|
240 | end | |||
|
241 | ||||
191 | # Find all the roles that can be given to a project member |
|
242 | # Find all the roles that can be given to a project member | |
192 | def self.find_all_givable |
|
243 | def self.find_all_givable | |
193 | Role.givable.to_a |
|
244 | Role.givable.to_a |
@@ -62,6 +62,50 | |||||
62 | <%= hidden_field_tag 'role[permissions][]', '' %> |
|
62 | <%= hidden_field_tag 'role[permissions][]', '' %> | |
63 | </div> |
|
63 | </div> | |
64 |
|
64 | |||
|
65 | <div id="role-permissions-trackers"> | |||
|
66 | <h3><%= l(:label_issue_tracking) %></h3> | |||
|
67 | <% permissions = %w(add_issues) %> | |||
|
68 | <table class="list"> | |||
|
69 | <thead> | |||
|
70 | <tr> | |||
|
71 | <th><%= l(:label_tracker) %></th> | |||
|
72 | <% permissions.each do |permission| %> | |||
|
73 | <th><%= l("permission_#{permission}") %></th> | |||
|
74 | <% end %> | |||
|
75 | </thead> | |||
|
76 | <tbody> | |||
|
77 | <tr> | |||
|
78 | <td class="name"><b><%= l(:label_tracker_all) %></b></td> | |||
|
79 | <% permissions.each do |permission| %> | |||
|
80 | <td> | |||
|
81 | <%= hidden_field_tag "role[permissions_all_trackers][#{permission}]", '0', :id => nil %> | |||
|
82 | <%= check_box_tag "role[permissions_all_trackers][#{permission}]", | |||
|
83 | '1', | |||
|
84 | @role.permissions_all_trackers?(permission), | |||
|
85 | :data => {:disables => ".#{permission}_tracker"} %> | |||
|
86 | </td> | |||
|
87 | <% end %> | |||
|
88 | </tr> | |||
|
89 | <% Tracker.sorted.all.each do |tracker| %> | |||
|
90 | <tr> | |||
|
91 | <td class="name"><%= tracker.name %></td> | |||
|
92 | <% permissions.each do |permission| %> | |||
|
93 | <td><%= check_box_tag "role[permissions_tracker_ids][#{permission}][]", | |||
|
94 | tracker.id, | |||
|
95 | @role.permissions_tracker_ids?(permission, tracker.id), | |||
|
96 | :class => "#{permission}_tracker", | |||
|
97 | :id => "role_permissions_tracker_ids_add_issues_#{tracker.id}" %></td> | |||
|
98 | <% end %> | |||
|
99 | </tr> | |||
|
100 | <% end %> | |||
|
101 | </tbody> | |||
|
102 | </table> | |||
|
103 | ||||
|
104 | <% permissions.each do |permission| %> | |||
|
105 | <%= hidden_field_tag "role[permissions_tracker_ids][#{permission}][]", '' %> | |||
|
106 | <% end %> | |||
|
107 | </div> | |||
|
108 | ||||
65 | <%= javascript_tag do %> |
|
109 | <%= javascript_tag do %> | |
66 | $(document).ready(function(){ |
|
110 | $(document).ready(function(){ | |
67 | $("#role_permissions_manage_members").change(function(){ |
|
111 | $("#role_permissions_manage_members").change(function(){ |
@@ -213,6 +213,7 en: | |||||
213 | error_can_not_read_import_file: "An error occurred while reading the file to import" |
|
213 | error_can_not_read_import_file: "An error occurred while reading the file to import" | |
214 | error_attachment_extension_not_allowed: "Attachment extension %{extension} is not allowed" |
|
214 | error_attachment_extension_not_allowed: "Attachment extension %{extension} is not allowed" | |
215 | error_ldap_bind_credentials: "Invalid LDAP Account/Password" |
|
215 | error_ldap_bind_credentials: "Invalid LDAP Account/Password" | |
|
216 | error_no_tracker_allowed_for_new_issue_in_project: "The project doesn't have any trackers for which you can create an issue" | |||
216 |
|
217 | |||
217 | mail_subject_lost_password: "Your %{value} password" |
|
218 | mail_subject_lost_password: "Your %{value} password" | |
218 | mail_body_lost_password: 'To change your password, click on the following link:' |
|
219 | mail_body_lost_password: 'To change your password, click on the following link:' | |
@@ -561,6 +562,7 en: | |||||
561 | label_member_plural: Members |
|
562 | label_member_plural: Members | |
562 | label_tracker: Tracker |
|
563 | label_tracker: Tracker | |
563 | label_tracker_plural: Trackers |
|
564 | label_tracker_plural: Trackers | |
|
565 | label_tracker_all: All trackers | |||
564 | label_tracker_new: New tracker |
|
566 | label_tracker_new: New tracker | |
565 | label_workflow: Workflow |
|
567 | label_workflow: Workflow | |
566 | label_issue_status: Issue status |
|
568 | label_issue_status: Issue status |
@@ -233,6 +233,7 fr: | |||||
233 | error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier Γ importer" |
|
233 | error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier Γ importer" | |
234 | error_attachment_extension_not_allowed: "L'extension %{extension} n'est pas autorisΓ©e" |
|
234 | error_attachment_extension_not_allowed: "L'extension %{extension} n'est pas autorisΓ©e" | |
235 | error_ldap_bind_credentials: "Identifiant ou mot de passe LDAP incorrect" |
|
235 | error_ldap_bind_credentials: "Identifiant ou mot de passe LDAP incorrect" | |
|
236 | error_no_tracker_allowed_for_new_issue_in_project: "Le projet ne dispose d'aucun tracker sur lequel vous pouvez crΓ©er une demande" | |||
236 |
|
237 | |||
237 | mail_subject_lost_password: "Votre mot de passe %{value}" |
|
238 | mail_subject_lost_password: "Votre mot de passe %{value}" | |
238 | mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :' |
|
239 | mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :' | |
@@ -573,6 +574,7 fr: | |||||
573 | label_member_plural: Membres |
|
574 | label_member_plural: Membres | |
574 | label_tracker: Tracker |
|
575 | label_tracker: Tracker | |
575 | label_tracker_plural: Trackers |
|
576 | label_tracker_plural: Trackers | |
|
577 | label_tracker_all: Tous les trackers | |||
576 | label_tracker_new: Nouveau tracker |
|
578 | label_tracker_new: Nouveau tracker | |
577 | label_workflow: Workflow |
|
579 | label_workflow: Workflow | |
578 | label_issue_status: Statut de demandes |
|
580 | label_issue_status: Statut de demandes |
@@ -1864,6 +1864,31 class IssuesControllerTest < ActionController::TestCase | |||||
1864 | end |
|
1864 | end | |
1865 | end |
|
1865 | end | |
1866 |
|
1866 | |||
|
1867 | def test_new_should_propose_allowed_trackers | |||
|
1868 | role = Role.find(1) | |||
|
1869 | role.set_permission_trackers 'add_issues', [1, 3] | |||
|
1870 | role.save! | |||
|
1871 | @request.session[:user_id] = 2 | |||
|
1872 | ||||
|
1873 | get :new, :project_id => 1 | |||
|
1874 | assert_response :success | |||
|
1875 | assert_select 'select[name=?]', 'issue[tracker_id]' do | |||
|
1876 | assert_select 'option', 2 | |||
|
1877 | assert_select 'option[value="1"]' | |||
|
1878 | assert_select 'option[value="3"]' | |||
|
1879 | end | |||
|
1880 | end | |||
|
1881 | ||||
|
1882 | def test_new_without_allowed_trackers_should_respond_with_403 | |||
|
1883 | role = Role.find(1) | |||
|
1884 | role.set_permission_trackers 'add_issues', [] | |||
|
1885 | role.save! | |||
|
1886 | @request.session[:user_id] = 2 | |||
|
1887 | ||||
|
1888 | get :new, :project_id => 1 | |||
|
1889 | assert_response 403 | |||
|
1890 | end | |||
|
1891 | ||||
1867 | def test_new_should_preselect_default_version |
|
1892 | def test_new_should_preselect_default_version | |
1868 | version = Version.generate!(:project_id => 1) |
|
1893 | version = Version.generate!(:project_id => 1) | |
1869 | Project.find(1).update_attribute :default_version_id, version.id |
|
1894 | Project.find(1).update_attribute :default_version_id, version.id | |
@@ -2432,6 +2457,23 class IssuesControllerTest < ActionController::TestCase | |||||
2432 | assert_nil issue.custom_field_value(cf2) |
|
2457 | assert_nil issue.custom_field_value(cf2) | |
2433 | end |
|
2458 | end | |
2434 |
|
2459 | |||
|
2460 | def test_create_should_ignore_unallowed_trackers | |||
|
2461 | role = Role.find(1) | |||
|
2462 | role.set_permission_trackers :add_issues, [3] | |||
|
2463 | role.save! | |||
|
2464 | @request.session[:user_id] = 2 | |||
|
2465 | ||||
|
2466 | issue = new_record(Issue) do | |||
|
2467 | post :create, :project_id => 1, :issue => { | |||
|
2468 | :tracker_id => 1, | |||
|
2469 | :status_id => 1, | |||
|
2470 | :subject => 'Test' | |||
|
2471 | } | |||
|
2472 | assert_response 302 | |||
|
2473 | end | |||
|
2474 | assert_equal 3, issue.tracker_id | |||
|
2475 | end | |||
|
2476 | ||||
2435 | def test_post_create_with_watchers |
|
2477 | def test_post_create_with_watchers | |
2436 | @request.session[:user_id] = 2 |
|
2478 | @request.session[:user_id] = 2 | |
2437 | ActionMailer::Base.deliveries.clear |
|
2479 | ActionMailer::Base.deliveries.clear |
@@ -132,6 +132,22 class RolesControllerTest < ActionController::TestCase | |||||
132 | assert_equal [:edit_project], role.permissions |
|
132 | assert_equal [:edit_project], role.permissions | |
133 | end |
|
133 | end | |
134 |
|
134 | |||
|
135 | def test_update_trackers_permissions | |||
|
136 | put :update, :id => 1, :role => { | |||
|
137 | :permissions_all_trackers => {'add_issues' => '0'}, | |||
|
138 | :permissions_tracker_ids => {'add_issues' => ['1', '3', '']} | |||
|
139 | } | |||
|
140 | ||||
|
141 | assert_redirected_to '/roles' | |||
|
142 | role = Role.find(1) | |||
|
143 | ||||
|
144 | assert_equal({'add_issues' => '0'}, role.permissions_all_trackers) | |||
|
145 | assert_equal({'add_issues' => ['1', '3']}, role.permissions_tracker_ids) | |||
|
146 | ||||
|
147 | assert_equal false, role.permissions_all_trackers?(:add_issues) | |||
|
148 | assert_equal [1, 3], role.permissions_tracker_ids(:add_issues).sort | |||
|
149 | end | |||
|
150 | ||||
135 | def test_update_with_failure |
|
151 | def test_update_with_failure | |
136 | put :update, :id => 1, :role => {:name => ''} |
|
152 | put :update, :id => 1, :role => {:name => ''} | |
137 | assert_response :success |
|
153 | assert_response :success |
@@ -1438,6 +1438,91 class IssueTest < ActiveSupport::TestCase | |||||
1438 | assert_not_include project, Issue.allowed_target_projects(User.find(1)) |
|
1438 | assert_not_include project, Issue.allowed_target_projects(User.find(1)) | |
1439 | end |
|
1439 | end | |
1440 |
|
1440 | |||
|
1441 | def test_allowed_target_trackers_with_one_role_allowed_on_all_trackers | |||
|
1442 | user = User.generate! | |||
|
1443 | role = Role.generate! | |||
|
1444 | role.add_permission! :add_issues | |||
|
1445 | role.set_permission_trackers :add_issues, :all | |||
|
1446 | role.save! | |||
|
1447 | User.add_to_project(user, Project.find(1), role) | |||
|
1448 | ||||
|
1449 | assert_equal [1, 2, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
|
1450 | end | |||
|
1451 | ||||
|
1452 | def test_allowed_target_trackers_with_one_role_allowed_on_some_trackers | |||
|
1453 | user = User.generate! | |||
|
1454 | role = Role.generate! | |||
|
1455 | role.add_permission! :add_issues | |||
|
1456 | role.set_permission_trackers :add_issues, [1, 3] | |||
|
1457 | role.save! | |||
|
1458 | User.add_to_project(user, Project.find(1), role) | |||
|
1459 | ||||
|
1460 | assert_equal [1, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
|
1461 | end | |||
|
1462 | ||||
|
1463 | def test_allowed_target_trackers_with_two_roles_allowed_on_some_trackers | |||
|
1464 | user = User.generate! | |||
|
1465 | role1 = Role.generate! | |||
|
1466 | role1.add_permission! :add_issues | |||
|
1467 | role1.set_permission_trackers :add_issues, [1] | |||
|
1468 | role1.save! | |||
|
1469 | role2 = Role.generate! | |||
|
1470 | role2.add_permission! :add_issues | |||
|
1471 | role2.set_permission_trackers :add_issues, [3] | |||
|
1472 | role2.save! | |||
|
1473 | User.add_to_project(user, Project.find(1), [role1, role2]) | |||
|
1474 | ||||
|
1475 | assert_equal [1, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
|
1476 | end | |||
|
1477 | ||||
|
1478 | def test_allowed_target_trackers_with_two_roles_allowed_on_all_trackers_and_some_trackers | |||
|
1479 | user = User.generate! | |||
|
1480 | role1 = Role.generate! | |||
|
1481 | role1.add_permission! :add_issues | |||
|
1482 | role1.set_permission_trackers :add_issues, :all | |||
|
1483 | role1.save! | |||
|
1484 | role2 = Role.generate! | |||
|
1485 | role2.add_permission! :add_issues | |||
|
1486 | role2.set_permission_trackers :add_issues, [1, 3] | |||
|
1487 | role2.save! | |||
|
1488 | User.add_to_project(user, Project.find(1), [role1, role2]) | |||
|
1489 | ||||
|
1490 | assert_equal [1, 2, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
|
1491 | end | |||
|
1492 | ||||
|
1493 | def test_allowed_target_trackers_should_not_consider_roles_without_add_issues_permission | |||
|
1494 | user = User.generate! | |||
|
1495 | role1 = Role.generate! | |||
|
1496 | role1.remove_permission! :add_issues | |||
|
1497 | role1.set_permission_trackers :add_issues, :all | |||
|
1498 | role1.save! | |||
|
1499 | role2 = Role.generate! | |||
|
1500 | role2.add_permission! :add_issues | |||
|
1501 | role2.set_permission_trackers :add_issues, [1, 3] | |||
|
1502 | role2.save! | |||
|
1503 | User.add_to_project(user, Project.find(1), [role1, role2]) | |||
|
1504 | ||||
|
1505 | assert_equal [1, 3], Issue.new(:project => Project.find(1)).allowed_target_trackers(user).ids.sort | |||
|
1506 | end | |||
|
1507 | ||||
|
1508 | def test_allowed_target_trackers_without_project_should_be_empty | |||
|
1509 | issue = Issue.new | |||
|
1510 | assert_nil issue.project | |||
|
1511 | assert_equal [], issue.allowed_target_trackers(User.find(2)).ids | |||
|
1512 | end | |||
|
1513 | ||||
|
1514 | def test_allowed_target_trackers_should_include_current_tracker | |||
|
1515 | user = User.generate! | |||
|
1516 | role = Role.generate! | |||
|
1517 | role.add_permission! :add_issues | |||
|
1518 | role.set_permission_trackers :add_issues, [3] | |||
|
1519 | role.save! | |||
|
1520 | User.add_to_project(user, Project.find(1), role) | |||
|
1521 | ||||
|
1522 | issue = Issue.generate!(:project => Project.find(1), :tracker => Tracker.find(1)) | |||
|
1523 | assert_equal [1, 3], issue.allowed_target_trackers(user).ids.sort | |||
|
1524 | end | |||
|
1525 | ||||
1441 | def test_move_to_another_project_with_same_category |
|
1526 | def test_move_to_another_project_with_same_category | |
1442 | issue = Issue.find(1) |
|
1527 | issue = Issue.find(1) | |
1443 | issue.project = Project.find(2) |
|
1528 | issue.project = Project.find(2) |
General Comments 0
You need to be logged in to leave comments.
Login now