diff --git a/CHANGELOG b/CHANGELOG index ab34661ce05b022cbe150db18c775cff808f0f51..f765899b42d08e00e9775a36bb9d77e0226faa0d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -38,6 +38,7 @@ v 8.4.0 (unreleased) - Ajax filter by message for commits page - API: Add support for deleting a tag via the API (Robert Schilling) - Allow subsequent validations in CI Linter + - Show referenced MRs & Issues only when the current viewer can access them v 8.3.3 - Preserve CE behavior with JIRA integration by only calling API if URL is set diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index b59b52291fb0c90da3c27ff177afcb9b6d830d34..f476afb2d9267643c9946a0f237a8b56ce02b2b3 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -61,7 +61,7 @@ class Projects::IssuesController < Projects::ApplicationController @note = @project.notes.new(noteable: @issue) @notes = @issue.notes.nonawards.with_associations.fresh @noteable = @issue - @merge_requests = @issue.referenced_merge_requests + @merge_requests = @issue.referenced_merge_requests(current_user) respond_with(@issue) end diff --git a/app/models/issue.rb b/app/models/issue.rb index f52e47f3e627f7c6c7d3a76f1b1ab363ac6ca3de..7beba9846089b51f6d6263fbc29af6f6a35e97aa 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -85,10 +85,10 @@ class Issue < ActiveRecord::Base reference end - def referenced_merge_requests + def referenced_merge_requests(current_user = nil) Gitlab::ReferenceExtractor.lazily do [self, *notes].flat_map do |note| - note.all_references.merge_requests + note.all_references(current_user).merge_requests end end.sort_by(&:iid) end diff --git a/app/views/projects/notes/_notes.html.haml b/app/views/projects/notes/_notes.html.haml index ca60dd239b234033e6106d5466ce86689ba83d52..a4ff947c656d010d77f26b43456bfa75fcb03f42 100644 --- a/app/views/projects/notes/_notes.html.haml +++ b/app/views/projects/notes/_notes.html.haml @@ -8,4 +8,5 @@ - else - @notes.each do |note| - next unless note.author + - next if note.cross_reference? && note.referenced_mentionables(current_user).empty? = render note diff --git a/features/project/issues/references.feature b/features/project/issues/references.feature new file mode 100644 index 0000000000000000000000000000000000000000..bf7a4c6cb91cd77314bb0e59c01e3d1ef5e205e3 --- /dev/null +++ b/features/project/issues/references.feature @@ -0,0 +1,31 @@ +@project_issues +Feature: Project Issues References + Background: + Given I sign in as "John Doe" + And "John Doe" owns public project "Community" + And project "Community" has "Public Issue 01" open issue + And I logout + And I sign in as "Mary Jane" + And "Mary Jane" owns private project "Private Library" + And project "Private Library" has "Fix NS-01" open merge request + And project "Private Library" has "Private Issue 01" open issue + And I visit merge request page "Fix NS-01" + And I leave a comment referencing issue "Public Issue 01" from "Fix NS-01" merge request + And I visit issue page "Private Issue 01" + And I leave a comment referencing issue "Public Issue 01" from "Private Issue 01" issue + And I logout + + @javascript + Scenario: Viewing the public issue as a "John Doe" + Given I sign in as "John Doe" + When I visit issue page "Public Issue 01" + Then I should not see any related merge requests + And I should see no notes at all + + @javascript + Scenario: Viewing the public issue as "Mary Jane" + Given I sign in as "Mary Jane" + When I visit issue page "Public Issue 01" + Then I should see the "Fix NS-01" related merge request + And I should see a note linking to "Fix NS-01" merge request + And I should see a note linking to "Private Issue 01" issue diff --git a/features/steps/project/issues/references.rb b/features/steps/project/issues/references.rb new file mode 100644 index 0000000000000000000000000000000000000000..9c7725e8c14f0c8cfb6f5f8414c4716579fbacb6 --- /dev/null +++ b/features/steps/project/issues/references.rb @@ -0,0 +1,106 @@ +class Spinach::Features::ProjectIssuesReferences < Spinach::FeatureSteps + include SharedAuthentication + include SharedNote + include SharedProject + include SharedUser + + step 'project "Community" has "Public Issue 01" open issue' do + project = Project.find_by(name: 'Community') + create(:issue, + title: 'Public Issue 01', + project: project, + author: project.users.first, + description: '# Description header' + ) + end + + step 'project "Private Library" has "Fix NS-01" open merge request' do + project = Project.find_by(name: 'Private Library') + create(:merge_request, + title: 'Fix NS-01', + source_project: project, + target_project: project, + source_branch: 'fix', + target_branch: 'master', + author: project.users.first, + description: '# Description header' + ) + end + + step 'project "Private Library" has "Private Issue 01" open issue' do + project = Project.find_by(name: 'Private Library') + create(:issue, + title: 'Private Issue 01', + project: project, + author: project.users.first, + description: '# Description header' + ) + end + + step 'I leave a comment referencing issue "Public Issue 01" from "Fix NS-01" merge request' do + project = Project.find_by(name: 'Private Library') + issue = Issue.find_by!(title: 'Public Issue 01') + + page.within(".js-main-target-form") do + fill_in "note[note]", with: "##{issue.to_reference(project)}" + click_button "Add Comment" + end + end + + step 'I leave a comment referencing issue "Public Issue 01" from "Private Issue 01" issue' do + project = Project.find_by(name: 'Private Library') + issue = Issue.find_by!(title: 'Public Issue 01') + + page.within(".js-main-target-form") do + fill_in "note[note]", with: "##{issue.to_reference(project)}" + click_button "Add Comment" + end + end + + step 'I visit merge request page "Fix NS-01"' do + mr = MergeRequest.find_by(title: "Fix NS-01") + visit namespace_project_merge_request_path(mr.target_project.namespace, mr.target_project, mr) + end + + step 'I visit issue page "Private Issue 01"' do + issue = Issue.find_by(title: "Private Issue 01") + visit namespace_project_issue_path(issue.project.namespace, issue.project, issue) + end + + step 'I visit issue page "Public Issue 01"' do + issue = Issue.find_by(title: "Public Issue 01") + visit namespace_project_issue_path(issue.project.namespace, issue.project, issue) + end + + step 'I should not see any related merge requests' do + page.within '.issue-details' do + expect(page).not_to have_content('.merge-requests') + end + end + + step 'I should see the "Fix NS-01" related merge request' do + page.within '.merge-requests' do + expect(page).to have_content("1 Related Merge Request") + expect(page).to have_content('Fix NS-01') + end + end + + step 'I should see a note linking to "Fix NS-01" merge request' do + project = Project.find_by(name: 'Community') + mr = MergeRequest.find_by(title: 'Fix NS-01') + page.within('.notes') do + expect(page).to have_content('Mary Jane') + expect(page).to have_content("mentioned in merge request #{mr.to_reference(project)}") + end + end + + step 'I should see a note linking to "Private Issue 01" issue' do + project = Project.find_by(name: 'Community') + issue = Issue.find_by(title: 'Private Issue 01') + page.within('.notes') do + expect(page).to have_content('Mary Jane') + expect(page).to have_content("mentioned in issue #{issue.to_reference(project)}") + end + end + +end diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index f6aabfefeffb3eab37e11c414feca40785192e1c..6de58c6e2b1818b81879fbb1767d372ac0eb63c5 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -106,6 +106,12 @@ module SharedNote end end + step 'I should see no notes at all' do + page.within('.notes') do + expect(page).to_not have_css('.note') + end + end + # Markdown step 'I leave a comment with a header containing "Comment with a header"' do diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index da643bf3ba964950a38753fa81d7a333bb1a4af4..43a15f434709b6fe7448777f3c604a0c4fb8f0be 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -181,6 +181,13 @@ module SharedProject project.team << [user, :master] end + step '"Mary Jane" owns private project "Private Library"' do + user = user_exists('Mary Jane', username: 'mary_jane') + project = Project.find_by(name: 'Private Library') + project ||= create(:project, name: 'Private Library', namespace: user.namespace) + project.team << [user, :master] + end + step 'public empty project "Empty Public Project"' do create :project_empty_repo, :public, name: "Empty Public Project" end