diff -ur redmine-0.9.4/app/controllers/issues_controller.rb redmine/app/controllers/issues_controller.rb --- redmine-0.9.4/app/controllers/issues_controller.rb 2010-05-01 16:43:49.000000000 +0400 +++ redmine/app/controllers/issues_controller.rb 2010-05-02 10:11:27.212598237 +0400 @@ -104,6 +104,7 @@ end def show + return render_403 if !@issue.visible? @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC") @journals.each_with_index {|j,i| j.indice = i+1} @journals.reverse! if User.current.wants_comments_in_reverse_order? diff -ur redmine-0.9.4/app/models/issue.rb redmine/app/models/issue.rb --- redmine-0.9.4/app/models/issue.rb 2010-05-01 16:43:49.000000000 +0400 +++ redmine/app/models/issue.rb 2010-05-02 10:34:35.590504997 +0400 @@ -62,8 +62,8 @@ after_save :create_journal # 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) + def visible?(user=User.current) + user.allowed_to?(:view_issues, self.project) || user.allowed_to?(:add_issues, self.project) && (author == user || assigned_to == user || watched_by?(user)) end def after_initialize diff -ur redmine-0.9.4/app/models/query.rb redmine/app/models/query.rb --- redmine-0.9.4/app/models/query.rb 2010-05-01 16:43:49.000000000 +0400 +++ redmine/app/models/query.rb 2010-05-05 13:15:44.608127680 +0400 @@ -346,7 +346,7 @@ group_by_column.groupable end - def project_statement + def project_statement(own=nil) project_clauses = [] if project && !@project.descendants.active.empty? ids = [project.id] @@ -368,7 +368,16 @@ elsif project project_clauses << "#{Project.table_name}.id = %d" % project.id end - project_clauses << Project.allowed_to_condition(User.current, :view_issues) + if own + wt = Watcher.table_name + uc = User.current.id.to_s + project_clauses << '('+Project.allowed_to_condition(User.current, :view_issues)+' OR '+Project.allowed_to_condition(User.current, :add_issues)+ + " AND (#{Issue.table_name}.author_id=#{uc} OR "+ + "#{Issue.table_name}.assigned_to_id=#{uc} OR "+ + "#{Issue.table_name}.id IN (SELECT #{wt}.watchable_id FROM #{wt} WHERE #{wt}.watchable_type='Issue' AND user_id=#{uc}))"+")" + else + project_clauses << Project.allowed_to_condition(User.current, :view_issues) + end project_clauses.join(' AND ') end @@ -409,7 +418,7 @@ end if filters and valid? - (filters_clauses << project_statement).join(' AND ') + (filters_clauses << project_statement(true)).join(' AND ') end # Returns the issue count diff -ur redmine-0.9.4/app/models/user.rb redmine/app/models/user.rb --- redmine-0.9.4/app/models/user.rb 2010-05-01 16:43:49.000000000 +0400 +++ redmine/app/models/user.rb 2010-05-02 14:42:56.463242646 +0400 @@ -289,7 +289,7 @@ roles = roles_for_project(project) return false unless roles - roles.detect {|role| (project.is_public? || role.member?) && role.allowed_to?(action)} + roles.any? {|role| (project.is_public? || role.member?) && role.allowed_to?(action)} elsif options[:global] # Admin users are always authorized @@ -297,7 +297,7 @@ # authorize if user has at least one role that has this permission roles = memberships.collect {|m| m.roles}.flatten.uniq - roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action)) + roles.any? {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action)) else false end diff -ur redmine-0.9.4/lib/redmine.rb redmine/lib/redmine.rb --- redmine-0.9.4/lib/redmine.rb 2010-05-01 16:43:53.000000000 +0400 +++ redmine/lib/redmine.rb 2010-05-05 22:39:13.741931615 +0400 @@ -25,7 +25,7 @@ # Permissions Redmine::AccessControl.map do |map| - map.permission :view_project, {:projects => [:show, :activity]}, :public => true + map.permission :view_project, {:projects => :show}, :public => true map.permission :search_project, {:search => :index}, :public => true map.permission :add_project, {:projects => :add}, :require => :loggedin map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member @@ -38,12 +38,12 @@ # Issue categories map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member # Issues - map.permission :view_issues, {:projects => :roadmap, + map.permission :view_issues, {:projects => [:roadmap, :activity], :issues => [:index, :changes, :show, :context_menu], :versions => [:show, :status_by], :queries => :index, :reports => :issue_report} - map.permission :add_issues, {:issues => [:new, :update_form]} + map.permission :add_issues, {:issues => [:new, :update_form, :index, :show]} map.permission :edit_issues, {:issues => [:edit, :reply, :bulk_edit, :update_form]} map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]} map.permission :add_issue_notes, {:issues => [:edit, :reply]} @@ -74,24 +74,24 @@ map.project_module :news do |map| map.permission :manage_news, {:news => [:new, :edit, :destroy, :destroy_comment]}, :require => :member map.permission :view_news, {:news => [:index, :show]}, :public => true - map.permission :comment_news, {:news => :add_comment} + map.permission :comment_news, {:projects => :activity, :news => :add_comment} end map.project_module :documents do |map| map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment]}, :require => :loggedin - map.permission :view_documents, :documents => [:index, :show, :download] + map.permission :view_documents, :projects => :activity, :documents => [:index, :show, :download] end map.project_module :files do |map| map.permission :manage_files, {:projects => :add_file}, :require => :loggedin - map.permission :view_files, :projects => :list_files, :versions => :download + map.permission :view_files, :projects => [:list_files, :activity], :versions => :download end map.project_module :wiki do |map| map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member - map.permission :view_wiki_pages, :wiki => [:index, :special] + map.permission :view_wiki_pages, :projects => :activity, :wiki => [:index, :special] map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate] map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment] map.permission :delete_wiki_pages_attachments, {} @@ -100,15 +100,15 @@ map.project_module :repository do |map| map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member - map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph] - map.permission :view_changesets, :repositories => [:show, :revisions, :revision] + map.permission :browse_repository, :projects => :activity, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph] + map.permission :view_changesets, :projects => :activity, :repositories => [:show, :revisions, :revision] map.permission :commit_access, {} end map.project_module :boards do |map| map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true - map.permission :add_messages, {:messages => [:new, :reply, :quote]} + map.permission :add_messages, {:projects => :activity, :messages => [:new, :reply, :quote]} map.permission :edit_messages, {:messages => :edit}, :require => :member map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin map.permission :delete_messages, {:messages => :destroy}, :require => :member diff -ur redmine-0.9.4/test/fixtures/issues.yml redmine/test/fixtures/issues.yml --- redmine-0.9.4/test/fixtures/issues.yml 2010-05-01 16:43:49.000000000 +0400 +++ redmine/test/fixtures/issues.yml 2010-05-02 23:55:08.325150668 +0400 @@ -86,11 +86,10 @@ category_id: description: This is an issue of a private subproject of cookbook tracker_id: 1 - assigned_to_id: + assigned_to_id: 12 author_id: 2 status_id: 1 start_date: <%= Date.today.to_s(:db) %> - due_date: <%= 1.days.from_now.to_date.to_s(:db) %> issues_007: created_on: <%= 10.days.ago.to_date.to_s(:db) %> project_id: 1 @@ -203,3 +202,17 @@ assigned_to_id: author_id: 2 status_id: 1 +issues_014: + created_on: <%= 5.days.ago.to_date.to_s(:db) %> + project_id: 5 + updated_on: <%= 2.days.ago.to_date.to_s(:db) %> + priority_id: 5 + subject: Test own message + id: 14 + fixed_version_id: + category_id: + description: Test own message + tracker_id: 1 + assigned_to_id: + author_id: 12 + status_id: 1 diff -ur redmine-0.9.4/test/fixtures/member_roles.yml redmine/test/fixtures/member_roles.yml --- redmine-0.9.4/test/fixtures/member_roles.yml 2010-05-01 16:43:49.000000000 +0400 +++ redmine/test/fixtures/member_roles.yml 2010-05-02 11:23:54.235688297 +0400 @@ -47,3 +47,8 @@ role_id: 2 member_id: 10 inherited_from: 10 +member_roles_012: + id: 12 + role_id: 6 + member_id: 11 + inherited_from: 11 diff -ur redmine-0.9.4/test/fixtures/members.yml redmine/test/fixtures/members.yml --- redmine-0.9.4/test/fixtures/members.yml 2010-05-01 16:43:49.000000000 +0400 +++ redmine/test/fixtures/members.yml 2010-05-02 14:02:44.426675930 +0400 @@ -60,3 +60,9 @@ project_id: 2 user_id: 8 mail_notification: false +members_011: + id: 11 + created_on: 2006-07-19 19:35:33 +02:00 + project_id: 5 + user_id: 12 + mail_notification: false diff -ur redmine-0.9.4/test/fixtures/roles.yml redmine/test/fixtures/roles.yml --- redmine-0.9.4/test/fixtures/roles.yml 2010-05-01 16:43:49.000000000 +0400 +++ redmine/test/fixtures/roles.yml 2010-05-02 11:30:00.746683471 +0400 @@ -181,4 +181,13 @@ - :view_changesets position: 5 +roles_006: + name: Reporter2 + id: 6 + builtin: 0 + permissions: | + --- + - :add_issues + + position: 6 diff -ur redmine-0.9.4/test/fixtures/users.yml redmine/test/fixtures/users.yml --- redmine-0.9.4/test/fixtures/users.yml 2010-05-01 16:43:49.000000000 +0400 +++ redmine/test/fixtures/users.yml 2010-05-02 13:37:29.807310462 +0400 @@ -152,5 +152,21 @@ id: 11 lastname: B Team type: Group +users_012: + id: 12 + created_on: 2006-07-19 19:33:19 +02:00 + status: 1 + last_login_on: + language: 'ru' + hashed_password: 1 + updated_on: 2006-07-19 19:33:19 +02:00 + admin: false + mail: vasia@foo.bar + lastname: Vasia + firstname: Pupkin + auth_source_id: + mail_notification: false + login: vasia + type: User \ No newline at end of file diff -ur redmine-0.9.4/test/fixtures/watchers.yml redmine/test/fixtures/watchers.yml --- redmine-0.9.4/test/fixtures/watchers.yml 2010-05-01 16:43:49.000000000 +0400 +++ redmine/test/fixtures/watchers.yml 2010-05-02 14:10:33.450735744 +0400 @@ -11,4 +11,8 @@ watchable_type: Issue watchable_id: 2 user_id: 1 +watchers_004: + watchable_type: Issue + watchable_id: 9 + user_id: 12 \ No newline at end of file diff -ur redmine-0.9.4/test/functional/issues_controller_test.rb redmine/test/functional/issues_controller_test.rb --- redmine-0.9.4/test/functional/issues_controller_test.rb 2010-05-01 16:43:48.000000000 +0400 +++ redmine/test/functional/issues_controller_test.rb 2010-05-02 14:11:07.723876157 +0400 @@ -411,6 +411,7 @@ def test_show_should_deny_member_access_without_permission Role.find(1).remove_permission!(:view_issues) + Role.find(1).remove_permission!(:add_issues) @request.session[:user_id] = 2 get :show, :id => 1 assert_response 403 @@ -458,6 +459,30 @@ assert_not_nil assigns(:issue) end + def test_show_own_issue_by_author + @request.session[:user_id] = 12 + get :show, :id => 14 + assert_response :success + end + + def test_show_own_issue_by_assigned + @request.session[:user_id] = 12 + get :show, :id => 6 + assert_response :success + end + + def test_show_own_issue_by_watcher + @request.session[:user_id] = 12 + get :show, :id => 9 + assert_response :success + end + + def test_show_should_deny_access_without_permission + @request.session[:user_id] = 12 + get :show, :id => 10 + assert_response 403 + end + def test_get_new @request.session[:user_id] = 2 get :new, :project_id => 1, :tracker_id => 1 diff -ur redmine-0.9.4/test/unit/attachment_test.rb redmine/test/unit/attachment_test.rb --- redmine-0.9.4/test/unit/attachment_test.rb 2010-05-01 16:43:48.000000000 +0400 +++ redmine/test/unit/attachment_test.rb 2010-05-05 08:51:42.104691844 +0400 @@ -20,7 +20,7 @@ require File.dirname(__FILE__) + '/../test_helper' class AttachmentTest < ActiveSupport::TestCase - fixtures :issues, :users + fixtures :issues, :users, :watchers def setup end @@ -53,4 +53,26 @@ assert_equal 'f8139524ebb8f32e51976982cd20a85d', Attachment.disk_filename("test_accentué")[13..-1] assert_equal 'cbb5b0f30978ba03731d61f9f6d10011', Attachment.disk_filename("test_accentué.ça")[13..-1] end + + def test_visible_file_for_issue + # Set "Add issue", unset "View issue" on default for user #12 + # author + a = Attachment.new(:container => Issue.find(14), :file => uploaded_test_file("testfile.txt", ""), :author => User.find(2)) + assert a.save + assert_equal true, a.visible?(User.find(12)) + # assigned to + a = Attachment.new(:container => Issue.find(6), :file => uploaded_test_file("testfile.txt", ""), :author => User.find(2)) + assert a.save + assert_equal true, a.visible?(User.find(12)) + # watcher + a = Attachment.new(:container => Issue.find(9), :file => uploaded_test_file("testfile.txt", ""), :author => User.find(2)) + assert a.save + assert_equal true, a.visible?(User.find(12)) + # other + a = Attachment.new(:container => Issue.find(10), :file => uploaded_test_file("testfile.txt", ""), :author => User.find(2)) + assert a.save + assert_equal false, a.visible?(User.find(12)) + Role.find(6).add_permission!(:view_issues) + assert_equal true, a.visible?(User.find(12)) + end end diff -ur redmine-0.9.4/test/unit/issue_test.rb redmine/test/unit/issue_test.rb --- redmine-0.9.4/test/unit/issue_test.rb 2010-05-01 16:43:48.000000000 +0400 +++ redmine/test/unit/issue_test.rb 2010-05-02 14:50:06.631821484 +0400 @@ -105,6 +105,29 @@ assert issues.detect {|issue| !issue.project.is_public?} end + def test_visible + user=User.find(12) + issue = Issue.new(:project_id => 5, :tracker_id => 1, :author_id => 2, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_own', :description => 'IssueTest#test_own', :estimated_hours => '5:30') + assert issue.save + issue.reload + # Test for user, with "View_issue" + assert_equal true, issue.visible?(User.find(8)) + # Test for user, without "View issue", but with "Add issue" + assert_equal false, issue.visible?(user) + # Test for assinged user + issue.assigned_to=user + assert_equal true, issue.visible?(user) + # Test for watcher + issue.assigned_to=nil + issue.add_watcher(user) + assert_equal true, issue.visible?(user) + # Test for author + issue = Issue.new(:project_id => 5, :tracker_id => 1, :author_id => 12, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_own', :description => 'IssueTest#test_own', :estimated_hours => '5:30') + assert issue.save + issue.reload + assert_equal true, issue.visible?(user) + end + def test_errors_full_messages_should_include_custom_fields_errors field = IssueCustomField.find_by_name('Database') diff -ur redmine-0.9.4/test/unit/mailer_test.rb redmine/test/unit/mailer_test.rb --- redmine-0.9.4/test/unit/mailer_test.rb 2010-05-01 16:43:48.000000000 +0400 +++ redmine/test/unit/mailer_test.rb 2010-05-02 15:27:00.495894531 +0400 @@ -199,6 +199,7 @@ user = User.find(9) Watcher.create!(:watchable => @issue, :user => user) Role.non_member.remove_permission!(:view_issues) + Role.non_member.remove_permission!(:add_issues) assert Mailer.deliver_issue_add(@issue) assert !last_email.bcc.include?(user.mail) end diff -ur redmine-0.9.4/vendor/plugins/acts_as_attachable/lib/acts_as_attachable.rb redmine/vendor/plugins/acts_as_attachable/lib/acts_as_attachable.rb --- redmine-0.9.4/vendor/plugins/acts_as_attachable/lib/acts_as_attachable.rb 2010-05-01 16:43:50.000000000 +0400 +++ redmine/vendor/plugins/acts_as_attachable/lib/acts_as_attachable.rb 2010-05-04 23:34:45.999335862 +0400 @@ -42,7 +42,7 @@ end def attachments_visible?(user=User.current) - user.allowed_to?(self.class.attachable_options[:view_permission], self.project) + user.allowed_to?(self.class.attachable_options[:view_permission], self.project) || is_a?(Issue) && self.visible?(user) end def attachments_deletable?(user=User.current)