Commit f53be7f0 authored by Markus Koller's avatar Markus Koller

Merge branch...

Merge branch '250353-convert-issues-createfromvulnerabilityservice-to-work-similar-to-issues-buildservice-add-route' into 'master'

Add route to build issue from vulnerability

See merge request gitlab-org/gitlab!47528
parents f8165f37 7d3af592
...@@ -73,6 +73,8 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -73,6 +73,8 @@ class Projects::IssuesController < Projects::ApplicationController
feature_category :service_desk, [:service_desk] feature_category :service_desk, [:service_desk]
feature_category :importers, [:import_csv, :export_csv] feature_category :importers, [:import_csv, :export_csv]
attr_accessor :vulnerability_id
def index def index
@issues = @issuables @issues = @issuables
...@@ -124,6 +126,8 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -124,6 +126,8 @@ class Projects::IssuesController < Projects::ApplicationController
service = ::Issues::CreateService.new(project, current_user, create_params) service = ::Issues::CreateService.new(project, current_user, create_params)
@issue = service.execute @issue = service.execute
create_vulnerability_issue_link(issue)
if service.discussions_to_resolve.count(&:resolved?) > 0 if service.discussions_to_resolve.count(&:resolved?) > 0
flash[:notice] = if service.discussion_to_resolve_id flash[:notice] = if service.discussion_to_resolve_id
_("Resolved 1 discussion.") _("Resolved 1 discussion.")
...@@ -384,6 +388,9 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -384,6 +388,9 @@ class Projects::IssuesController < Projects::ApplicationController
def service_desk? def service_desk?
action_name == 'service_desk' action_name == 'service_desk'
end end
# Overridden in EE
def create_vulnerability_issue_link(issue); end
end end
Projects::IssuesController.prepend_if_ee('EE::Projects::IssuesController') Projects::IssuesController.prepend_if_ee('EE::Projects::IssuesController')
...@@ -88,3 +88,6 @@ ...@@ -88,3 +88,6 @@
= form.hidden_field :issue_type = form.hidden_field :issue_type
= form.hidden_field :lock_version = form.hidden_field :lock_version
- if @vulnerability_id
= hidden_field_tag 'vulnerability_id', @vulnerability_id
...@@ -10,6 +10,9 @@ module EE ...@@ -10,6 +10,9 @@ module EE
include DescriptionDiffActions include DescriptionDiffActions
before_action :whitelist_query_limiting_ee, only: [:update] before_action :whitelist_query_limiting_ee, only: [:update]
before_action only: [:new, :create] do
populate_vulnerability_id
end
feature_category :issue_tracking, [:delete_description_version, :description_diff] feature_category :issue_tracking, [:delete_description_version, :description_diff]
end end
...@@ -36,6 +39,57 @@ module EE ...@@ -36,6 +39,57 @@ module EE
def whitelist_query_limiting_ee def whitelist_query_limiting_ee
::Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/4794') ::Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/4794')
end end
def issue_params
super.tap do |params|
if vulnerability_id
params.merge!(issue_build_parameters)
end
end
end
def create_vulnerability_issue_link(issue)
return unless issue.persisted? && vulnerability
result = VulnerabilityIssueLinks::CreateService.new(
current_user,
vulnerability,
issue,
link_type: Vulnerabilities::IssueLink.link_types[:created]
).execute
flash[:alert] = render_vulnerability_link_alert if result.status == :error
end
def vulnerability
project.vulnerabilities.find(vulnerability_id) if vulnerability_id
end
def issue_build_parameters
{
title: _("Investigate vulnerability: %{title}") % { title: vulnerability.title },
description: render_description,
confidential: true
}
end
def render_description
render_to_string(
template: 'vulnerabilities/issue_description.md.erb',
locals: { vulnerability: vulnerability.present }
)
end
def render_vulnerability_link_alert
render_to_string(
partial: 'vulnerabilities/unable_to_link_vulnerability.html.haml',
locals: { vulnerability_link: vulnerability_path(vulnerability) }
)
end
def populate_vulnerability_id
self.vulnerability_id = params[:vulnerability_id] if can?(current_user, :read_vulnerability, project)
end
end end
end end
end end
%span.gl-alert-title
= _('Unable to create link to vulnerability')
.gl-alert-body
- originating_vulnerability_link = link_to _('originating vulnerability'), vulnerability_link
= _('Manually link this issue by adding it to the linked issue section of the %{originating_vulnerability}.').html_safe % { originating_vulnerability: originating_vulnerability_link }
---
title: Issues can be built with vulnerability information
merge_request: 47528
author:
type: changed
...@@ -26,7 +26,7 @@ RSpec.describe Projects::IssuesController do ...@@ -26,7 +26,7 @@ RSpec.describe Projects::IssuesController do
context 'licensed' do context 'licensed' do
before do before do
stub_licensed_features(issue_weights: true, epics: true) stub_licensed_features(issue_weights: true, epics: true, security_dashboard: true)
end end
describe '#index' do describe '#index' do
...@@ -60,6 +60,23 @@ RSpec.describe Projects::IssuesController do ...@@ -60,6 +60,23 @@ RSpec.describe Projects::IssuesController do
end end
end end
describe '#new' do
render_views
context 'when a vulnerability_id is provided' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:finding) { create(:vulnerabilities_finding, pipelines: [pipeline]) }
let(:vulnerability) { create(:vulnerability, project: project, findings: [finding]) }
let(:vulnerability_field) { "<input type=\"hidden\" name=\"vulnerability_id\" id=\"vulnerability_id\" value=\"#{vulnerability.id}\" />" }
it 'sets the vulnerability_id' do
get :new, params: { namespace_id: project.namespace, project_id: project, vulnerability_id: vulnerability.id }
expect(response.body).to include(vulnerability_field)
end
end
end
describe '#create' do describe '#create' do
it 'sets issue weight and epic' do it 'sets issue weight and epic' do
perform :post, :create, issue: new_issue.attributes.merge(epic_id: epic.id) perform :post, :create, issue: new_issue.attributes.merge(epic_id: epic.id)
...@@ -71,12 +88,52 @@ RSpec.describe Projects::IssuesController do ...@@ -71,12 +88,52 @@ RSpec.describe Projects::IssuesController do
expect(issue.weight).to eq(new_issue.weight) expect(issue.weight).to eq(new_issue.weight)
expect(issue.epic).to eq(epic) expect(issue.epic).to eq(epic)
end end
context 'when created from a vulnerability' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:finding) { create(:vulnerabilities_finding, pipelines: [pipeline]) }
let(:vulnerability) { create(:vulnerability, project: project, findings: [finding]) }
before do
stub_licensed_features(security_dashboard: true)
end
it 'links the issue to the vulnerability' do
send_request
expect(project.issues.last.vulnerability_links.first.vulnerability).to eq(vulnerability)
end
context 'when vulnerability already has a linked issue' do
render_views
let!(:vulnerabilities_issue_link) { create(:vulnerabilities_issue_link, :created, vulnerability: vulnerability) }
it 'shows an error message' do
send_request
expect(flash[:alert]).to include('Unable to create link to vulnerability')
expect(vulnerability.issue_links.map(&:issue)).to eq([vulnerabilities_issue_link.issue])
end
end
private
def send_request
post :create, params: {
namespace_id: project.namespace.to_param,
project_id: project,
issue: { title: 'Title', description: 'Description' },
vulnerability_id: vulnerability.id
}
end
end
end end
end end
context 'unlicensed' do context 'unlicensed' do
before do before do
stub_licensed_features(issue_weights: false, epics: false) stub_licensed_features(issue_weights: false, epics: false, security_dashboard: false)
end end
describe '#index' do describe '#index' do
...@@ -100,6 +157,24 @@ RSpec.describe Projects::IssuesController do ...@@ -100,6 +157,24 @@ RSpec.describe Projects::IssuesController do
end end
end end
describe '#new' do
render_views
context 'when a vulnerability_id is provided' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:finding) { create(:vulnerabilities_finding, pipelines: [pipeline]) }
let(:vulnerability) { create(:vulnerability, project: project, findings: [finding]) }
let(:vulnerability_field) { "<input type=\"hidden\" name=\"vulnerability_id\" id=\"vulnerability_id\" value=\"#{vulnerability.id}\" />" }
it 'does not build issue from a vulnerability' do
get :new, params: { namespace_id: project.namespace, project_id: project, vulnerability_id: vulnerability.id }
expect(response.body).not_to include(vulnerability_field)
expect(issue.description).to be_nil
end
end
end
describe '#create' do describe '#create' do
it 'does not set issue weight ane epic' do it 'does not set issue weight ane epic' do
perform :post, :create, issue: new_issue.attributes perform :post, :create, issue: new_issue.attributes
......
...@@ -101,6 +101,21 @@ FactoryBot.define do ...@@ -101,6 +101,21 @@ FactoryBot.define do
end end
end end
trait :with_pipeline do
after(:build) do |vulnerability|
finding = build(
:vulnerabilities_finding,
:identifier,
:with_pipeline,
vulnerability: vulnerability,
report_type: vulnerability.report_type,
project: vulnerability.project
)
vulnerability.findings = [finding]
end
end
trait :with_findings do trait :with_findings do
after(:build) do |vulnerability| after(:build) do |vulnerability|
findings_with_solution = build_list( findings_with_solution = build_list(
......
...@@ -198,6 +198,14 @@ FactoryBot.define do ...@@ -198,6 +198,14 @@ FactoryBot.define do
end end
end end
trait :with_pipeline do
after(:create) do |finding|
pipeline = create(:ci_pipeline, project: finding.project)
finding.pipelines = [pipeline]
end
end
trait :identifier do trait :identifier do
after(:build) do |finding| after(:build) do |finding|
identifier = build( identifier = build(
......
...@@ -16494,6 +16494,9 @@ msgstr "" ...@@ -16494,6 +16494,9 @@ msgstr ""
msgid "ManualOrdering|Couldn't save the order of the issues" msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "" msgstr ""
msgid "Manually link this issue by adding it to the linked issue section of the %{originating_vulnerability}."
msgstr ""
msgid "Map a FogBugz account ID to a GitLab user" msgid "Map a FogBugz account ID to a GitLab user"
msgstr "" msgstr ""
...@@ -28977,6 +28980,9 @@ msgstr "" ...@@ -28977,6 +28980,9 @@ msgstr ""
msgid "Unable to convert Kubernetes logs encoding to UTF-8" msgid "Unable to convert Kubernetes logs encoding to UTF-8"
msgstr "" msgstr ""
msgid "Unable to create link to vulnerability"
msgstr ""
msgid "Unable to fetch unscanned projects" msgid "Unable to fetch unscanned projects"
msgstr "" msgstr ""
...@@ -32815,6 +32821,9 @@ msgstr "" ...@@ -32815,6 +32821,9 @@ msgstr ""
msgid "or" msgid "or"
msgstr "" msgstr ""
msgid "originating vulnerability"
msgstr ""
msgid "out of %d total test" msgid "out of %d total test"
msgid_plural "out of %d total tests" msgid_plural "out of %d total tests"
msgstr[0] "" msgstr[0] ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment