diff --git a/ee/app/models/vulnerabilities/external_issue_link.rb b/ee/app/models/vulnerabilities/external_issue_link.rb index a7e7c7633fa3e9cbc286e04a950be3ae3629dbf3..94c6323883d7cb9b13d50fb05759b809e3d64f13 100644 --- a/ee/app/models/vulnerabilities/external_issue_link.rb +++ b/ee/app/models/vulnerabilities/external_issue_link.rb @@ -18,5 +18,7 @@ class ExternalIssueLink < ApplicationRecord message: N_('already has a "created" issue link') }, if: :created? + + scope :created_for_vulnerability, -> (vulnerability) { where(vulnerability: vulnerability, link_type: 'created') } end end diff --git a/ee/app/services/vulnerability_external_issue_links/create_service.rb b/ee/app/services/vulnerability_external_issue_links/create_service.rb index ee0cf992f28bf5ad6f7a566eeb0446022f5162ed..30b9fb62878097a82edabd11ec5bf54bfce029fa 100644 --- a/ee/app/services/vulnerability_external_issue_links/create_service.rb +++ b/ee/app/services/vulnerability_external_issue_links/create_service.rb @@ -13,6 +13,9 @@ def initialize(user, vulnerability, external_provider, link_type: Vulnerabilitie def execute return error(['External provider service is not configured to create issues.']) unless external_provider_service&.configured_to_create_issues_from_vulnerabilities? + + remove_links_for_nonexistent_external_issues + return error(external_issue_link.errors.full_messages) unless external_issue_link.valid? external_issue = create_external_issue @@ -57,6 +60,14 @@ def prepare_external_issue_link ) end + def remove_links_for_nonexistent_external_issues + Vulnerabilities::ExternalIssueLink.created_for_vulnerability(vulnerability).each do |link| + unless external_provider_service.find_issue(link.external_issue_key) + link.destroy + end + end + end + def success ServiceResponse.success(payload: { record: external_issue_link }) end diff --git a/ee/spec/models/vulnerabilities/external_issue_link_spec.rb b/ee/spec/models/vulnerabilities/external_issue_link_spec.rb index a4a6cdac87252f05665708d1ad8508f75381de7c..6fb513fdad5cd9dd15179016d9980381f0e57158 100644 --- a/ee/spec/models/vulnerabilities/external_issue_link_spec.rb +++ b/ee/spec/models/vulnerabilities/external_issue_link_spec.rb @@ -45,4 +45,12 @@ end end end + + describe 'created_for_vulnerability' do + let_it_be(:external_links) { create_list(:vulnerabilities_external_issue_link, 2, :created) } + + it 'gets external issue links for the specified vulnerability' do + expect(described_class.created_for_vulnerability(external_links.first.vulnerability).take).to eq(external_links.first) + end + end end diff --git a/ee/spec/services/vulnerability_external_issue_links/create_service_spec.rb b/ee/spec/services/vulnerability_external_issue_links/create_service_spec.rb index 69bbbeb33e34f1ef5f7bcf56b1bd19a109975d14..ec3d763ad0a42e38f920436604ece4a3c1ce8680 100644 --- a/ee/spec/services/vulnerability_external_issue_links/create_service_spec.rb +++ b/ee/spec/services/vulnerability_external_issue_links/create_service_spec.rb @@ -38,10 +38,35 @@ create(:vulnerabilities_external_issue_link, vulnerability: vulnerability) end - it { is_expected.not_to be_success } + context 'and the external issue exists' do + let!(:jira_issue) { ExternalIssue.new('JIRA-123', project) } - it 'returns response with error messages' do - expect(subject.message).to eq(['Vulnerability already has a "created" issue link']) + before do + allow(jira_integration).to receive(:find_issue).and_return(jira_issue) + end + + it { is_expected.not_to be_success } + + it 'returns response with error messages' do + expect(subject.message).to match_array(['Vulnerability already has a "created" issue link']) + end + end + + context 'and the external issue does not exist' do + let(:jira_issue_id) { nil } + let(:errors) { {} } + let(:jira_issue) { double(has_errors?: errors.present?, id: jira_issue_id, errors: errors) } + + before do + allow(jira_integration).to receive(:create_issue).and_return(jira_issue) + allow(jira_integration).to receive(:find_issue).and_return(nil) + end + + it 'creates issue using jira service' do + expect(jira_integration).to receive(:create_issue).with("Investigate vulnerability: #{vulnerability.title}", kind_of(String), user) + + subject + end end end