diff --git a/app/models/issue.rb b/app/models/issue.rb index b20da8d91..b6e223aec 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -178,7 +178,9 @@ class Issue < ActiveRecord::Base # Returns true if user or current user is allowed to edit the issue def attributes_editable?(user=User.current) - user_tracker_permission?(user, :edit_issues) + user_tracker_permission?(user, :edit_issues) || ( + user_tracker_permission?(user, :edit_own_issues) && author == user + ) end # Overrides Redmine::Acts::Attachable::InstanceMethods#attachments_editable? diff --git a/config/locales/en.yml b/config/locales/en.yml index 74e03d34e..7e30b33eb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -485,6 +485,7 @@ en: permission_view_issues: View Issues permission_add_issues: Add issues permission_edit_issues: Edit issues + permission_edit_own_issues: Edit own issues permission_copy_issues: Copy issues permission_manage_issue_relations: Manage issue relations permission_set_issues_private: Set issues public or private diff --git a/lib/redmine.rb b/lib/redmine.rb index 9bf00f366..e913d7cd2 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -100,6 +100,7 @@ Redmine::AccessControl.map do |map| :read => true map.permission :add_issues, {:issues => [:new, :create], :attachments => :upload} map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update], :journals => [:new], :attachments => :upload} + map.permission :edit_own_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update], :journals => [:new], :attachments => :upload} map.permission :copy_issues, {:issues => [:new, :create, :bulk_edit, :bulk_update], :attachments => :upload} map.permission :manage_issue_relations, {:issue_relations => [:index, :show, :create, :destroy]} map.permission :manage_subtasks, {} diff --git a/test/functional/context_menus_controller_test.rb b/test/functional/context_menus_controller_test.rb index aeaf7391a..68860f199 100644 --- a/test/functional/context_menus_controller_test.rb +++ b/test/functional/context_menus_controller_test.rb @@ -103,6 +103,32 @@ class ContextMenusControllerTest < Redmine::ControllerTest assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&issue%5Bassigned_to_id%5D=2", :text => 'John Smith' end + def test_context_menu_by_author_should_selectable_edit_the_own_created_issues + Role.all.each do |r| + r.remove_permission! :edit_issues + r.add_permission! :edit_own_issues + end + + author_id = 2 # jsmith + @request.session[:user_id] = author_id + + # Include author only + assert_equal [author_id], Issue.where(:id => [1, 2]).collect(&:author_id).uniq + get :issues, :params => { + :ids => [1, 2] + } + assert_response :success + assert_select 'a[href=?]', '/issues/bulk_edit?ids%5B%5D=1&ids%5B%5D=2', :text => 'Edit' + + # Including other than authors + assert_not_equal [author_id], Issue.where(:id => [1, 2, 12]).collect(&:author_id).uniq + get :issues, :params => { + :ids => [1, 2, 12] + } + assert_response :success + assert_select 'a.disabled[href=?]', '#', :text => 'Edit' + end + def test_context_menu_should_include_list_custom_fields field = IssueCustomField.create!(:name => 'List', :field_format => 'list', :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3]) @@ -317,7 +343,7 @@ class ContextMenusControllerTest < Redmine::ControllerTest def test_time_entries_context_menu_without_edit_permission @request.session[:user_id] = 2 Role.find_by_name('Manager').remove_permission! :edit_time_entries - + get :time_entries, :params => { :ids => [1, 2] } diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index 047c98782..a8ee6639b 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -4525,6 +4525,46 @@ class IssuesControllerTest < Redmine::ControllerTest assert_select 'input[name=?]', 'time_entry[hours]', 0 end + def test_get_edit_should_display_the_change_properties_area_with_attributes_editable_permission + @request.session[:user_id] = 2 # jsmith + role_manager = Role.find_by_name('Manager') # jsmith's role + + role_manager.remove_permission! :edit_issues, :edit_own_issues + role_manager.add_permission! :edit_issues + get :edit, :params => { + :id => 1 + } + assert_response :success + assert_select '#all_attributes', :count => 1 + + role_manager.remove_permission! :edit_issues, :edit_own_issues + role_manager.add_permission! :edit_own_issues + get :edit, :params => { + :id => 1 + } + assert_response :success + assert_select '#all_attributes', :count => 1 + + role_manager.remove_permission! :edit_issues, :edit_own_issues + role_manager.add_permission! :edit_issues, :edit_own_issues + get :edit, :params => { + :id => 1 + } + assert_response :success + assert_select '#all_attributes', :count => 1 + end + + def test_get_edit_should_not_display_the_change_properties_area_without_attributes_editable_permission + @request.session[:user_id] = 2 # jsmith + + Role.find_by_name('Manager').remove_permission! :edit_issues, :edit_own_issues + get :edit, :params => { + :id => 1 + } + assert_response :success + assert_select '#all_attributes', :count => 0 + end + def test_get_edit_with_params @request.session[:user_id] = 2 get :edit, :params => { diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index 3bbe75158..8ad7abe23 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -541,6 +541,23 @@ class IssueTest < ActiveSupport::TestCase assert_equal false, issue.deletable?(user) end + def test_issue_should_editable_by_author + Role.all.each do |r| + r.remove_permission! :edit_issues + r.add_permission! :edit_own_issues + end + + issue = Issue.find(1) + user = User.find_by_login('jsmith') + + # author + assert_equal user, issue.author + assert_equal true, issue.attributes_editable?(user) + + # not author + assert_equal false, issue.attributes_editable?(User.find_by_login('dlopper')) + end + def test_errors_full_messages_should_include_custom_fields_errors field = IssueCustomField.find_by_name('Database')