summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2016-06-06 09:41:50 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2016-06-06 09:41:50 +0000
commit6e68d008c4dc50f46585e30aabaa5bc9859bee0f (patch)
treedddbcaecd80051789282556982fad7270c2e5b9d /app
parent7a974437e6414682d6b318a3b1130d728f51907a (diff)
downloadredmine-6e68d008c4dc50f46585e30aabaa5bc9859bee0f.tar.gz
redmine-6e68d008c4dc50f46585e30aabaa5bc9859bee0f.zip
Merged 15430, 15464 to 15469, 15475, 15476 (#285, #7839).
git-svn-id: http://svn.redmine.org/redmine/branches/3.3-stable@15478 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r--app/controllers/context_menus_controller.rb7
-rw-r--r--app/controllers/issues_controller.rb21
-rw-r--r--app/helpers/issues_helper.rb10
-rw-r--r--app/models/issue.rb98
-rw-r--r--app/models/issue_import.rb2
-rw-r--r--app/models/mail_handler.rb13
-rw-r--r--app/models/role.rb51
-rw-r--r--app/views/issues/_action_menu.html.erb2
-rw-r--r--app/views/issues/_edit.html.erb29
-rw-r--r--app/views/issues/_form.html.erb2
-rw-r--r--app/views/issues/_history.html.erb2
-rw-r--r--app/views/issues/index.html.erb2
-rw-r--r--app/views/issues/show.html.erb2
-rw-r--r--app/views/roles/_form.html.erb61
14 files changed, 238 insertions, 64 deletions
diff --git a/app/controllers/context_menus_controller.rb b/app/controllers/context_menus_controller.rb
index 1e5652d09..66ec35085 100644
--- a/app/controllers/context_menus_controller.rb
+++ b/app/controllers/context_menus_controller.rb
@@ -29,11 +29,11 @@ class ContextMenusController < ApplicationController
@allowed_statuses = @issues.map(&:new_statuses_allowed_to).reduce(:&)
- @can = {:edit => User.current.allowed_to?(:edit_issues, @projects),
+ @can = {:edit => @issues.all?(&:attributes_editable?),
:log_time => (@project && User.current.allowed_to?(:log_time, @project)),
:copy => User.current.allowed_to?(:copy_issues, @projects) && Issue.allowed_target_projects.any?,
:add_watchers => User.current.allowed_to?(:add_issue_watchers, @projects),
- :delete => User.current.allowed_to?(:delete_issues, @projects)
+ :delete => @issues.all?(&:deletable?)
}
if @project
if @issue
@@ -41,12 +41,11 @@ class ContextMenusController < ApplicationController
else
@assignables = @project.assignable_users
end
- @trackers = @project.trackers
else
#when multiple projects, we only keep the intersection of each set
@assignables = @projects.map(&:assignable_users).reduce(:&)
- @trackers = @projects.map(&:trackers).reduce(:&)
end
+ @trackers = @projects.map {|p| Issue.allowed_target_trackers(p) }.reduce(:&)
@versions = @projects.map {|p| p.shared_versions.open}.reduce(:&)
@priorities = IssuePriority.active.reverse
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index cf402de22..67956667a 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -211,6 +211,10 @@ class IssuesController < ApplicationController
unless User.current.allowed_to?(:copy_issues, @projects)
raise ::Unauthorized
end
+ else
+ unless @issues.all?(&:attributes_editable?)
+ raise ::Unauthorized
+ end
end
@allowed_projects = Issue.allowed_target_projects
@@ -230,7 +234,7 @@ class IssuesController < ApplicationController
end
@custom_fields = @issues.map{|i|i.editable_custom_fields}.reduce(:&)
@assignables = target_projects.map(&:assignable_users).reduce(:&)
- @trackers = target_projects.map(&:trackers).reduce(:&)
+ @trackers = target_projects.map {|p| Issue.allowed_target_trackers(p) }.reduce(:&)
@versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&)
@categories = target_projects.map {|p| p.issue_categories}.reduce(:&)
if @copy
@@ -263,6 +267,10 @@ class IssuesController < ApplicationController
unless User.current.allowed_to?(:add_issues, target_projects)
raise ::Unauthorized
end
+ else
+ unless @issues.all?(&:attributes_editable?)
+ raise ::Unauthorized
+ end
end
unsaved_issues = []
@@ -316,6 +324,7 @@ class IssuesController < ApplicationController
end
def destroy
+ raise Unauthorized unless @issues.all?(&:deletable?)
@hours = TimeEntry.where(:issue_id => @issues.map(&:id)).sum(:hours).to_f
if @hours > 0
case params[:todo]
@@ -465,9 +474,15 @@ class IssuesController < ApplicationController
@issue.safe_attributes = attrs
if @issue.project
- @issue.tracker ||= @issue.project.trackers.first
+ @issue.tracker ||= @issue.allowed_target_trackers.first
if @issue.tracker.nil?
- render_error l(:error_no_tracker_in_project)
+ if @issue.project.trackers.any?
+ # None of the project trackers is allowed to the user
+ render_error :message => l(:error_no_tracker_allowed_for_new_issue_in_project), :status => 403
+ else
+ # Project has no trackers
+ render_error l(:error_no_tracker_in_project)
+ end
return false
end
if @issue.status.nil?
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index b505765d8..ce6d9f8f2 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -168,6 +168,16 @@ module IssuesHelper
link_to(l(:button_add), new_project_issue_path(issue.project, :issue => attrs))
end
+ def trackers_options_for_select(issue)
+ trackers = issue.allowed_target_trackers
+ if issue.new_record? && issue.parent_issue_id.present?
+ trackers = trackers.reject do |tracker|
+ issue.tracker_id != tracker.id && tracker.disabled_core_fields.include?('parent_issue_id')
+ end
+ end
+ trackers.collect {|t| [t.name, t.id]}
+ end
+
class IssueFieldsRows
include ActionView::Helpers::TagHelper
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 0ee8ff3d3..e0b99e4e6 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -120,10 +120,10 @@ class Issue < ActiveRecord::Base
# Returns a SQL conditions string used to find all issues visible by the specified user
def self.visible_condition(user, options={})
Project.allowed_to_condition(user, :view_issues, options) do |role, user|
- if user.id && user.logged?
+ sql = if user.id && user.logged?
case role.issues_visibility
when 'all'
- nil
+ '1=1'
when 'default'
user_ids = [user.id] + user.groups.map(&:id).compact
"(#{table_name}.is_private = #{connection.quoted_false} OR #{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
@@ -136,13 +136,22 @@ class Issue < ActiveRecord::Base
else
"(#{table_name}.is_private = #{connection.quoted_false})"
end
+ unless role.permissions_all_trackers?(:view_issues)
+ tracker_ids = role.permissions_tracker_ids(:view_issues)
+ if tracker_ids.any?
+ sql = "(#{sql} AND #{table_name}.tracker_id IN (#{tracker_ids.join(',')}))"
+ else
+ sql = '1=0'
+ end
+ end
+ sql
end
end
# Returns true if usr or current user is allowed to view the issue
def visible?(usr=nil)
(usr || User.current).allowed_to?(:view_issues, self.project) do |role, user|
- if user.logged?
+ visible = if user.logged?
case role.issues_visibility
when 'all'
true
@@ -156,17 +165,36 @@ class Issue < ActiveRecord::Base
else
!self.is_private?
end
+ unless role.permissions_all_trackers?(:view_issues)
+ visible &&= role.permissions_tracker_ids?(:view_issues, tracker_id)
+ end
+ visible
end
end
- # Returns true if user or current user is allowed to edit or add a note to the issue
+ # Returns true if user or current user is allowed to edit or add notes to the issue
def editable?(user=User.current)
- attributes_editable?(user) || user.allowed_to?(:add_issue_notes, project)
+ attributes_editable?(user) || notes_addable?(user)
end
# Returns true if user or current user is allowed to edit the issue
def attributes_editable?(user=User.current)
- user.allowed_to?(:edit_issues, project)
+ user_tracker_permission?(user, :edit_issues)
+ end
+
+ # Overrides Redmine::Acts::Attachable::InstanceMethods#attachments_editable?
+ def attachments_editable?(user=User.current)
+ attributes_editable?(user)
+ end
+
+ # Returns true if user or current user is allowed to add notes to the issue
+ def notes_addable?(user=User.current)
+ user_tracker_permission?(user, :add_issue_notes)
+ end
+
+ # Returns true if user or current user is allowed to delete the issue
+ def deletable?(user=User.current)
+ user_tracker_permission?(user, :delete_issues)
end
def initialize(attributes=nil, *args)
@@ -416,10 +444,10 @@ class Issue < ActiveRecord::Base
'custom_fields',
'lock_version',
'notes',
- :if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) }
+ :if => lambda {|issue, user| issue.new_record? || issue.attributes_editable?(user) }
safe_attributes 'notes',
- :if => lambda {|issue, user| user.allowed_to?(:add_issue_notes, issue.project)}
+ :if => lambda {|issue, user| issue.notes_addable?(user)}
safe_attributes 'private_notes',
:if => lambda {|issue, user| !issue.new_record? && user.allowed_to?(:set_notes_private, issue.project)}
@@ -434,7 +462,7 @@ class Issue < ActiveRecord::Base
}
safe_attributes 'parent_issue_id',
- :if => lambda {|issue, user| (issue.new_record? || user.allowed_to?(:edit_issues, issue.project)) &&
+ :if => lambda {|issue, user| (issue.new_record? || issue.attributes_editable?(user)) &&
user.allowed_to?(:manage_subtasks, issue.project)}
def safe_attribute_names(user=nil)
@@ -479,12 +507,14 @@ class Issue < ActiveRecord::Base
end
if (t = attrs.delete('tracker_id')) && safe_attribute?('tracker_id')
- self.tracker_id = t
+ if allowed_target_trackers(user).where(:id => t.to_i).exists?
+ self.tracker_id = t
+ end
end
if project
- # Set the default tracker to accept custom field values
+ # Set a default tracker to accept custom field values
# even if tracker is not specified
- self.tracker ||= project.trackers.first
+ self.tracker ||= allowed_target_trackers(user).first
end
statuses_allowed = new_statuses_allowed_to(user)
@@ -822,16 +852,6 @@ class Issue < ActiveRecord::Base
!leaf?
end
- def assignable_trackers
- trackers = project.trackers
- if new_record? && parent_issue_id.present?
- trackers = trackers.reject do |tracker|
- tracker_id != tracker.id && tracker.disabled_core_fields.include?('parent_issue_id')
- end
- end
- trackers
- end
-
# Users the issue can be assigned to
def assignable_users
users = project.assignable_users.to_a
@@ -1373,9 +1393,43 @@ class Issue < ActiveRecord::Base
end
Project.where(condition).having_trackers
end
+
+ # Returns a scope of trackers that user can assign the issue to
+ def allowed_target_trackers(user=User.current)
+ self.class.allowed_target_trackers(project, user, tracker_id_was)
+ end
+
+ # Returns a scope of trackers that user can assign project issues to
+ def self.allowed_target_trackers(project, user=User.current, current_tracker=nil)
+ if project
+ scope = project.trackers.sorted
+ unless user.admin?
+ roles = user.roles_for_project(project).select {|r| r.has_permission?(:add_issues)}
+ unless roles.any? {|r| r.permissions_all_trackers?(:add_issues)}
+ tracker_ids = roles.map {|r| r.permissions_tracker_ids(:add_issues)}.flatten.uniq
+ if current_tracker
+ tracker_ids << current_tracker
+ end
+ scope = scope.where(:id => tracker_ids)
+ end
+ end
+ scope
+ else
+ Tracker.none
+ end
+ end
private
+ def user_tracker_permission?(user, permission)
+ if user.admin?
+ true
+ else
+ roles = user.roles_for_project(project).select {|r| r.has_permission?(permission)}
+ roles.any? {|r| r.permissions_all_trackers?(permission) || r.permissions_tracker_ids?(permission, tracker_id)}
+ end
+ end
+
def after_project_change
# Update project_id on related time entries
TimeEntry.where({:issue_id => id}).update_all(["project_id = ?", project_id])
diff --git a/app/models/issue_import.rb b/app/models/issue_import.rb
index b6b20a1b1..5b19ac966 100644
--- a/app/models/issue_import.rb
+++ b/app/models/issue_import.rb
@@ -37,7 +37,7 @@ class IssueImport < Import
# Returns a scope of trackers that user is allowed to
# import issue to
def allowed_target_trackers
- project.trackers
+ Issue.allowed_target_trackers(project, user)
end
def tracker
diff --git a/app/models/mail_handler.rb b/app/models/mail_handler.rb
index 40bd02a07..a619f115d 100644
--- a/app/models/mail_handler.rb
+++ b/app/models/mail_handler.rb
@@ -199,7 +199,14 @@ class MailHandler < ActionMailer::Base
end
issue = Issue.new(:author => user, :project => project)
- issue.safe_attributes = issue_attributes_from_keywords(issue)
+ attributes = issue_attributes_from_keywords(issue)
+ if handler_options[:no_permission_check]
+ issue.tracker_id = attributes['tracker_id']
+ if project
+ issue.tracker_id ||= project.trackers.first.try(:id)
+ end
+ end
+ issue.safe_attributes = attributes
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
issue.subject = cleaned_up_subject
if issue.subject.blank?
@@ -420,10 +427,6 @@ class MailHandler < ActionMailer::Base
'done_ratio' => get_keyword(:done_ratio, :format => '(\d|10)?0')
}.delete_if {|k, v| v.blank? }
- if issue.new_record? && attrs['tracker_id'].nil?
- attrs['tracker_id'] = issue.project.trackers.first.try(:id)
- end
-
attrs
end
diff --git a/app/models/role.rb b/app/models/role.rb
index defbc311d..89538aa4d 100644
--- a/app/models/role.rb
+++ b/app/models/role.rb
@@ -73,6 +73,7 @@ class Role < ActiveRecord::Base
acts_as_positioned :scope => :builtin
serialize :permissions, ::Role::PermissionsAttributeCoder
+ store :settings, :accessors => [:permissions_all_trackers, :permissions_tracker_ids]
attr_protected :builtin
validates_presence_of :name
@@ -188,6 +189,56 @@ class Role < ActiveRecord::Base
setable_permissions
end
+ def permissions_tracker_ids(*args)
+ if args.any?
+ Array(permissions_tracker_ids[args.first.to_s]).map(&:to_i)
+ else
+ super || {}
+ end
+ end
+
+ def permissions_tracker_ids=(arg)
+ h = arg.to_hash
+ h.values.each {|v| v.reject!(&:blank?)}
+ super(h)
+ end
+
+ # Returns true if tracker_id belongs to the list of
+ # trackers for which permission is given
+ def permissions_tracker_ids?(permission, tracker_id)
+ permissions_tracker_ids(permission).include?(tracker_id)
+ end
+
+ def permissions_all_trackers
+ super || {}
+ end
+
+ def permissions_all_trackers=(arg)
+ super(arg.to_hash)
+ end
+
+ # Returns true if permission is given for all trackers
+ def permissions_all_trackers?(permission)
+ permissions_all_trackers[permission.to_s].to_s != '0'
+ end
+
+ # Sets the trackers that are allowed for a permission.
+ # tracker_ids can be an array of tracker ids or :all for
+ # no restrictions.
+ #
+ # Examples:
+ # role.set_permission_trackers :add_issues, [1, 3]
+ # role.set_permission_trackers :add_issues, :all
+ def set_permission_trackers(permission, tracker_ids)
+ h = {permission.to_s => (tracker_ids == :all ? '1' : '0')}
+ self.permissions_all_trackers = permissions_all_trackers.merge(h)
+
+ h = {permission.to_s => (tracker_ids == :all ? [] : tracker_ids)}
+ self.permissions_tracker_ids = permissions_tracker_ids.merge(h)
+
+ self
+ end
+
# Find all the roles that can be given to a project member
def self.find_all_givable
Role.givable.to_a
diff --git a/app/views/issues/_action_menu.html.erb b/app/views/issues/_action_menu.html.erb
index c3304626d..b535faec9 100644
--- a/app/views/issues/_action_menu.html.erb
+++ b/app/views/issues/_action_menu.html.erb
@@ -3,5 +3,5 @@
<%= 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) %>
<%= watcher_link(@issue, User.current) %>
<%= 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? %>
-<%= 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) %>
+<%= link_to l(:button_delete), issue_path(@issue), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'icon icon-del' if @issue.deletable? %>
</div>
diff --git a/app/views/issues/_edit.html.erb b/app/views/issues/_edit.html.erb
index 24a01cad0..67e33246d 100644
--- a/app/views/issues/_edit.html.erb
+++ b/app/views/issues/_edit.html.erb
@@ -27,21 +27,22 @@
<% end %>
</fieldset>
<% end %>
-
- <fieldset><legend><%= l(:field_notes) %></legend>
- <%= f.text_area :notes, :cols => 60, :rows => 10, :class => 'wiki-edit', :no_label => true %>
- <%= wikitoolbar_for 'issue_notes' %>
-
- <% if @issue.safe_attribute? 'private_notes' %>
- <%= f.check_box :private_notes, :no_label => true %> <label for="issue_private_notes"><%= l(:field_private_notes) %></label>
+ <% if @issue.notes_addable? %>
+ <fieldset><legend><%= l(:field_notes) %></legend>
+ <%= f.text_area :notes, :cols => 60, :rows => 10, :class => 'wiki-edit', :no_label => true %>
+ <%= wikitoolbar_for 'issue_notes' %>
+
+ <% if @issue.safe_attribute? 'private_notes' %>
+ <%= f.check_box :private_notes, :no_label => true %> <label for="issue_private_notes"><%= l(:field_private_notes) %></label>
+ <% end %>
+
+ <%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %>
+ </fieldset>
+
+ <fieldset><legend><%= l(:label_attachment_plural) %></legend>
+ <p><%= render :partial => 'attachments/form', :locals => {:container => @issue} %></p>
+ </fieldset>
<% end %>
-
- <%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %>
- </fieldset>
-
- <fieldset><legend><%= l(:label_attachment_plural) %></legend>
- <p><%= render :partial => 'attachments/form', :locals => {:container => @issue} %></p>
- </fieldset>
</div>
<%= f.hidden_field :lock_version %>
diff --git a/app/views/issues/_form.html.erb b/app/views/issues/_form.html.erb
index 788a2f38e..1e82b6f84 100644
--- a/app/views/issues/_form.html.erb
+++ b/app/views/issues/_form.html.erb
@@ -14,7 +14,7 @@
<% end %>
<% if @issue.safe_attribute? 'tracker_id' %>
-<p><%= f.select :tracker_id, @issue.assignable_trackers.collect {|t| [t.name, t.id]}, {:required => true},
+<p><%= f.select :tracker_id, trackers_options_for_select(@issue), {:required => true},
:onchange => "updateIssueFrom('#{escape_javascript update_issue_form_path(@project, @issue)}', this)" %></p>
<% end %>
diff --git a/app/views/issues/_history.html.erb b/app/views/issues/_history.html.erb
index 993dfee3c..307ac909b 100644
--- a/app/views/issues/_history.html.erb
+++ b/app/views/issues/_history.html.erb
@@ -1,4 +1,4 @@
-<% reply_links = authorize_for('issues', 'edit') -%>
+<% reply_links = issue.notes_addable? -%>
<% for journal in journals %>
<div id="change-<%= journal.id %>" class="<%= journal.css_classes %>">
<div id="note-<%= journal.indice %>">
diff --git a/app/views/issues/index.html.erb b/app/views/issues/index.html.erb
index 7dcba2629..fd762023f 100644
--- a/app/views/issues/index.html.erb
+++ b/app/views/issues/index.html.erb
@@ -1,5 +1,5 @@
<div class="contextual">
- <% if User.current.allowed_to?(:add_issues, @project, :global => true) && (@project.nil? || @project.trackers.any?) %>
+ <% if User.current.allowed_to?(:add_issues, @project, :global => true) && (@project.nil? || Issue.allowed_target_trackers(@project).any?) %>
<%= link_to l(:label_issue_new), _new_project_issue_path(@project), :class => 'icon icon-add new-issue' %>
<% end %>
</div>
diff --git a/app/views/issues/show.html.erb b/app/views/issues/show.html.erb
index 70a7fe165..2cbff32e5 100644
--- a/app/views/issues/show.html.erb
+++ b/app/views/issues/show.html.erb
@@ -77,7 +77,7 @@ end %>
<% if @issue.description? %>
<div class="description">
<div class="contextual">
- <%= link_to l(:button_quote), quoted_issue_path(@issue), :remote => true, :method => 'post', :class => 'icon icon-comment' if authorize_for('issues', 'edit') %>
+ <%= link_to l(:button_quote), quoted_issue_path(@issue), :remote => true, :method => 'post', :class => 'icon icon-comment' if @issue.notes_addable? %>
</div>
<p><strong><%=l(:field_description)%></strong></p>
diff --git a/app/views/roles/_form.html.erb b/app/views/roles/_form.html.erb
index 84d5de185..39acc34a4 100644
--- a/app/views/roles/_form.html.erb
+++ b/app/views/roles/_form.html.erb
@@ -7,17 +7,17 @@
<% end %>
<% unless @role.anonymous? %>
- <p><%= f.select :issues_visibility, Role::ISSUES_VISIBILITY_OPTIONS.collect {|v| [l(v.last), v.first]} %></p>
+ <p class="view_issues_shown"><%= f.select :issues_visibility, Role::ISSUES_VISIBILITY_OPTIONS.collect {|v| [l(v.last), v.first]} %></p>
<% end %>
<% unless @role.anonymous? %>
- <p><%= f.select :time_entries_visibility, Role::TIME_ENTRIES_VISIBILITY_OPTIONS.collect {|v| [l(v.last), v.first]} %></p>
+ <p class="view_time_entries_shown"><%= f.select :time_entries_visibility, Role::TIME_ENTRIES_VISIBILITY_OPTIONS.collect {|v| [l(v.last), v.first]} %></p>
<% end %>
<p><%= f.select :users_visibility, Role::USERS_VISIBILITY_OPTIONS.collect {|v| [l(v.last), v.first]} %></p>
<% unless @role.builtin? %>
- <p id="manage_members_options">
+ <p class="manage_members_shown">
<label><%= l(:label_member_management) %></label>
<label class="block">
<%= radio_button_tag 'role[all_roles_managed]', 1, @role.all_roles_managed?, :id => 'role_all_roles_managed_on',
@@ -52,7 +52,8 @@
<% perms_by_module[mod].each do |permission| %>
<label class="floating">
<%= check_box_tag 'role[permissions][]', permission.name, (@role.permissions.include? permission.name),
- :id => "role_permissions_#{permission.name}" %>
+ :id => "role_permissions_#{permission.name}",
+ :data => {:shows => ".#{permission.name}_shown"} %>
<%= l_or_humanize(permission.name, :prefix => 'permission_') %>
</label>
<% end %>
@@ -62,10 +63,50 @@
<%= hidden_field_tag 'role[permissions][]', '' %>
</div>
-<%= javascript_tag do %>
-$(document).ready(function(){
- $("#role_permissions_manage_members").change(function(){
- $("#manage_members_options").toggle($(this).is(":checked"));
- }).change();
-});
+<div id="role-permissions-trackers" class="view_issues_shown">
+<h3><%= l(:label_issue_tracking) %></h3>
+<% permissions = %w(view_issues add_issues edit_issues add_issue_notes delete_issues) %>
+
+<div class="autoscroll">
+<table class="list">
+ <thead>
+ <tr>
+ <th><%= l(:label_tracker) %></th>
+ <% permissions.each do |permission| %>
+ <th class="<%= "#{permission}_shown" %>"><%= l("permission_#{permission}") %></th>
+ <% end %>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="name"><b><%= l(:label_tracker_all) %></b></td>
+ <% permissions.each do |permission| %>
+ <td class="<%= "#{permission}_shown" %>">
+ <%= hidden_field_tag "role[permissions_all_trackers][#{permission}]", '0', :id => nil %>
+ <%= check_box_tag "role[permissions_all_trackers][#{permission}]",
+ '1',
+ @role.permissions_all_trackers?(permission),
+ :class => "#{permission}_shown",
+ :data => {:disables => ".#{permission}_tracker"} %>
+ </td>
+ <% end %>
+ </tr>
+ <% Tracker.sorted.all.each do |tracker| %>
+ <tr class="<%= cycle("odd", "even") %>">
+ <td class="name"><%= tracker.name %></td>
+ <% permissions.each do |permission| %>
+ <td class="<%= "#{permission}_shown" %>"><%= check_box_tag "role[permissions_tracker_ids][#{permission}][]",
+ tracker.id,
+ @role.permissions_tracker_ids?(permission, tracker.id),
+ :class => "#{permission}_tracker",
+ :id => "role_permissions_tracker_ids_add_issues_#{tracker.id}" %></td>
+ <% end %>
+ </tr>
+ <% end %>
+ </tbody>
+</table>
+</div>
+
+<% permissions.each do |permission| %>
+ <%= hidden_field_tag "role[permissions_tracker_ids][#{permission}][]", '' %>
<% end %>
+</div>