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 %>
diff -Nur redmine-1.1.0/app/views/issues/_edit.rhtml redmine-1.1.0-issue-permissions/app/views/issues/_edit.rhtml --- redmine-1.1.0/app/views/issues/_edit.rhtml 2011-01-26 11:55:33.165232500 -0700 +++ redmine-1.1.0-issue-permissions/app/views/issues/_edit.rhtml 2011-02-09 10:15:51.278831600 -0700 @@ -6,13 +6,13 @@ :multipart => true} do |f| %> <%= error_messages_for 'issue', 'time_entry' %>
- <% if @edit_allowed || !@allowed_statuses.empty? %> + <% if @issue.editable? || (!@allowed_statuses.empty? && @issue.assigned_to == User.current) %>
<%= l(:label_change_properties) %> - <% if !@issue.new_record? && !@issue.errors.any? && @edit_allowed %> + <% if !@issue.new_record? && !@issue.errors.any? && @issue.descr_editable? %> (<%= link_to l(:label_more), {}, :onclick => 'Effect.toggle("issue_descr_fields", "appear", {duration:0.3}); return false;' %>) <% end %> - <%= render :partial => (@edit_allowed ? 'form' : 'form_update'), :locals => {:f => f} %> + <%= render :partial => (@issue.editable? ? 'form' : 'form_update'), :locals => {:f => f} %>
<% end %> <% if authorize_for('timelog', 'edit') %> diff -Nur redmine-1.1.0/app/views/issues/_form_update.rhtml redmine-1.1.0-issue-permissions/app/views/issues/_form_update.rhtml --- redmine-1.1.0/app/views/issues/_form_update.rhtml 2011-01-09 17:05:00.000000000 -0700 +++ redmine-1.1.0-issue-permissions/app/views/issues/_form_update.rhtml 2011-02-09 10:15:51.278831600 -0700 @@ -1,14 +1,14 @@

<%= 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? %>

<% if 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 %> <% 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 %>
diff -Nur redmine-1.1.0/config/locales/en.yml redmine-1.1.0-issue-permissions/config/locales/en.yml --- redmine-1.1.0/config/locales/en.yml 2011-01-09 17:05:00.000000000 -0700 +++ redmine-1.1.0-issue-permissions/config/locales/en.yml 2011-02-09 10:15:51.294457000 -0700 @@ -373,7 +373,11 @@ permission_manage_categories: Manage issue categories permission_view_issues: View Issues permission_add_issues: Add issues - permission_edit_issues: Edit issues + permission_edit_issues: Edit all issues + permission_edit_authored_issues: Edit authored issues + permission_edit_assigned_issues: Edit assigned issues + permission_edit_issue_progress: Edit issue progress + permission_edit_issue_planning: Edit issue planning permission_manage_issue_relations: Manage issue relations permission_add_issue_notes: Add notes permission_edit_issue_notes: Edit notes diff -Nur redmine-1.1.0/lib/redmine/default_data/loader.rb redmine-1.1.0-issue-permissions/lib/redmine/default_data/loader.rb --- redmine-1.1.0/lib/redmine/default_data/loader.rb 2011-01-09 17:05:00.000000000 -0700 +++ redmine-1.1.0-issue-permissions/lib/redmine/default_data/loader.rb 2011-02-09 10:15:51.310082400 -0700 @@ -51,7 +51,9 @@ :manage_categories, :view_issues, :add_issues, - :edit_issues, + :edit_authored_issues, + :edit_assigned_issues, + :edit_issue_progress, :manage_issue_relations, :manage_subtasks, :add_issue_notes, @@ -79,6 +81,7 @@ :permissions => [:view_issues, :add_issues, :add_issue_notes, + :edit_authored_issues, :save_queries, :view_gantt, :view_calendar, diff -Nur redmine-1.1.0/lib/redmine.rb redmine-1.1.0-issue-permissions/lib/redmine.rb --- redmine-1.1.0/lib/redmine.rb 2011-01-09 17:05:00.000000000 -0700 +++ redmine-1.1.0-issue-permissions/lib/redmine.rb 2011-02-09 10:15:51.325707800 -0700 @@ -67,6 +67,10 @@ :reports => [:issue_report, :issue_report_details]} map.permission :add_issues, {:issues => [:new, :create, :update_form]} map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]} + map.permission :edit_authored_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]} + map.permission :edit_assigned_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]} + map.permission :edit_issue_progress, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]} + map.permission :edit_issue_planning, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]} map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]} map.permission :manage_subtasks, {} map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}