diff -Nur redmine-1.1.0/app/controllers/issues_controller.rb redmine-1.1.0-issue-permissions/app/controllers/issues_controller.rb --- redmine-1.1.0/app/controllers/issues_controller.rb 2011-01-09 17:05:00.000000000 -0700 +++ redmine-1.1.0-issue-permissions/app/controllers/issues_controller.rb 2011-02-09 10:15:51.216330000 -0700 @@ -109,7 +109,6 @@ @changesets = @issue.changesets.visible.all @changesets.reverse! if User.current.wants_comments_in_reverse_order? @allowed_statuses = @issue.new_statuses_allowed_to(User.current) - @edit_allowed = User.current.allowed_to?(:edit_issues, @project) @priorities = IssuePriority.all @time_entry = TimeEntry.new respond_to do |format| @@ -263,7 +262,6 @@ def update_issue_from_params @allowed_statuses = @issue.new_statuses_allowed_to(User.current) @priorities = IssuePriority.all - @edit_allowed = User.current.allowed_to?(:edit_issues, @project) @time_entry = TimeEntry.new @time_entry.attributes = params[:time_entry] diff -Nur redmine-1.1.0/app/models/issue.rb redmine-1.1.0-issue-permissions/app/models/issue.rb --- redmine-1.1.0/app/models/issue.rb 2011-01-25 13:02:02.750334900 -0700 +++ redmine-1.1.0-issue-permissions/app/models/issue.rb 2011-02-09 10:24:17.119905800 -0700 @@ -97,6 +97,35 @@ (usr || User.current).allowed_to?(:view_issues, self.project) end + # Returns true if usr or current user is allowed to edit the issue + def editable?(usr=nil) + user = usr || User.current + return new_record? || + user.allowed_to?(:edit_issues, self.project) || + (user.allowed_to?(:edit_assigned_issues, self.project) && self.assigned_to == user) || + (user.allowed_to?(:edit_authored_issues, self.project) && self.author == user && (self.assigned_to.nil? || self.closed?)) + end + + # Returns true if usr or current user is allowed to edit the description and subject + def descr_editable?(usr=nil) + user = usr || User.current + return new_record? || + user.allowed_to?(:edit_issues, self.project) || + (user.allowed_to?(:edit_authored_issues, self.project) && self.author == user && self.assigned_to.nil?) + end + + # Returns true if usr or current user is allowed to edit the progress of an issue + def progress_editable?(usr=nil) + user = usr || User.current + return user.allowed_to?(:edit_issue_progress, self.project) + end + + # Returns true if usr or current user is allowed to edit the planning of an issue + def planning_editable?(usr=nil) + user = usr || User.current + return user.allowed_to?(:edit_issue_planning, self.project) + end + def after_initialize if new_record? # set default values for new records only @@ -216,28 +245,33 @@ write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h) end + safe_attributes 'subject', + 'description', + :if => lambda {|issue, user| issue.descr_editable?(user)} + + safe_attributes 'parent_issue_id', + :if => lambda {|issue, user| user.allowed_to?(:manage_subtasks, issue.project)} + safe_attributes 'tracker_id', 'status_id', - 'parent_issue_id', 'category_id', - 'assigned_to_id', + 'custom_field_values', + 'custom_fields', + 'lock_version', + :if => lambda {|issue, user| issue.new_record? || issue.editable?(user) } + + safe_attributes 'assigned_to_id', 'priority_id', 'fixed_version_id', - 'subject', - 'description', 'start_date', 'due_date', - 'done_ratio', + :if => lambda {|issue, user| issue.planning_editable?(user)} + + safe_attributes 'done_ratio', 'estimated_hours', - 'custom_field_values', - 'custom_fields', - 'lock_version', - :if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) } - + :if => lambda {|issue, user| issue.progress_editable?(user)} + safe_attributes 'status_id', - 'assigned_to_id', - 'fixed_version_id', - 'done_ratio', :if => lambda {|issue, user| issue.new_statuses_allowed_to(user).any? } # Safely sets attributes diff -Nur redmine-1.1.0/app/models/mail_handler.rb redmine-1.1.0-issue-permissions/app/models/mail_handler.rb --- redmine-1.1.0/app/models/mail_handler.rb 2011-01-09 17:05:00.000000000 -0700 +++ redmine-1.1.0-issue-permissions/app/models/mail_handler.rb 2011-02-09 10:15:51.247580800 -0700 @@ -145,7 +145,7 @@ return unless issue # check permission unless @@handler_options[:no_permission_check] - raise UnauthorizedAction unless user.allowed_to?(:add_issue_notes, issue.project) || user.allowed_to?(:edit_issues, issue.project) + raise UnauthorizedAction unless user.allowed_to?(:add_issue_notes, issue.project) || issue.editable?(user) end # ignore CLI-supplied defaults for new issues diff -Nur redmine-1.1.0/app/views/issues/_attributes.rhtml redmine-1.1.0-issue-permissions/app/views/issues/_attributes.rhtml --- redmine-1.1.0/app/views/issues/_attributes.rhtml 2011-01-09 17:05:00.000000000 -0700 +++ redmine-1.1.0-issue-permissions/app/views/issues/_attributes.rhtml 2011-02-09 10:15:51.263206200 -0700 @@ -7,8 +7,8 @@
<%= @issue.status.name %>
<% end %> -<%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true}, :disabled => !@issue.leaf? %>
-<%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), :include_blank => true %>
+<%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true}, :disabled => !@issue.leaf? || !@issue.planning_editable? %>
+<%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), {:include_blank => true}, :disabled => !@issue.planning_editable? %>
<% unless @project.issue_categories.empty? %><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}), :include_blank => true %> <%= prompt_to_remote(image_tag('add.png', :style => 'vertical-align: middle;'), @@ -19,7 +19,7 @@ :tabindex => 199) if authorize_for('issue_categories', 'new') %>
<% end %> <% unless @issue.assignable_versions.empty? %> -<%= f.select :fixed_version_id, version_options_for_select(@issue.assignable_versions, @issue.fixed_version), :include_blank => true %> +
<%= f.select :fixed_version_id, version_options_for_select(@issue.assignable_versions, @issue.fixed_version), {:include_blank => true}, :disabled => !@issue.planning_editable? %> <%= prompt_to_remote(image_tag('add.png', :style => 'vertical-align: middle;'), l(:label_version_new), 'version[name]', @@ -31,11 +31,11 @@
<%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf? %><%= calendar_for('issue_start_date') if @issue.leaf? %>
-<%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf? %><%= calendar_for('issue_due_date') if @issue.leaf? %>
-<%= f.text_field :estimated_hours, :size => 3, :disabled => !@issue.leaf? %> <%= l(:field_hours) %>
+<%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf? || !@issue.planning_editable? %><%= calendar_for('issue_start_date') if @issue.leaf? && @issue.planning_editable? %>
+<%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf? || !@issue.planning_editable? %><%= calendar_for('issue_due_date') if @issue.leaf? && @issue.planning_editable? %>
+<%= f.text_field :estimated_hours, :size => 3, :disabled => !@issue.leaf? || !@issue.progress_editable? %> <%= l(:field_hours) %>
<% if @issue.leaf? && Issue.use_field_for_done_ratio? %> -<%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %>
+<%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }), {},:disabled => !@issue.progress_editable? %>
<% end %><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), :required => true %>
-<%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), :include_blank => true %>
+<%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), {:include_blank => true}, :disabled => !@issue.planning_editable? %>
<%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %>
+<%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10]}), {}, :disabled => !@issue.progress_editable? %>
<% end %> <% unless @issue.assignable_versions.empty? %> -<%= f.select :fixed_version_id, (@issue.assignable_versions.collect {|v| [v.name, v.id]}), :include_blank => true %>
+<%= f.select :fixed_version_id, (@issue.assignable_versions.collect {|v| [v.name, v.id]}), {:include_blank => true}, :disabled => !@issue.planning_editable? %>
<% end %>