summaryrefslogtreecommitdiff
path: root/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb')
-rw-r--r--lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb86
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb b/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb
new file mode 100644
index 00000000000..bc0a181a06c
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class populates missing dismissal information for
+ # vulnerability entries.
+ class PopulateMissingVulnerabilityDismissalInformation
+ class Vulnerability < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include EachBatch
+
+ self.table_name = 'vulnerabilities'
+
+ has_one :finding, class_name: '::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation::Finding'
+
+ scope :broken, -> { where('state = 2 AND (dismissed_at IS NULL OR dismissed_by_id IS NULL)') }
+
+ def copy_dismissal_information
+ return unless finding&.dismissal_feedback
+
+ update_columns(
+ dismissed_at: finding.dismissal_feedback.created_at,
+ dismissed_by_id: finding.dismissal_feedback.author_id
+ )
+ end
+ end
+
+ class Finding < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include ShaAttribute
+
+ self.table_name = 'vulnerability_occurrences'
+
+ sha_attribute :project_fingerprint
+
+ def dismissal_feedback
+ Feedback.dismissal.where(category: report_type, project_fingerprint: project_fingerprint, project_id: project_id).first
+ end
+ end
+
+ class Feedback < ActiveRecord::Base # rubocop:disable Style/Documentation
+ DISMISSAL_TYPE = 0
+
+ self.table_name = 'vulnerability_feedback'
+
+ scope :dismissal, -> { where(feedback_type: DISMISSAL_TYPE) }
+ end
+
+ def perform(*vulnerability_ids)
+ Vulnerability.includes(:finding).where(id: vulnerability_ids).each { |vulnerability| populate_for(vulnerability) }
+
+ log_info(vulnerability_ids)
+ end
+
+ private
+
+ def populate_for(vulnerability)
+ log_warning(vulnerability) unless vulnerability.copy_dismissal_information
+ rescue StandardError => error
+ log_error(error, vulnerability)
+ end
+
+ def log_info(vulnerability_ids)
+ ::Gitlab::BackgroundMigration::Logger.info(
+ migrator: self.class.name,
+ message: 'Dismissal information has been copied',
+ count: vulnerability_ids.length
+ )
+ end
+
+ def log_warning(vulnerability)
+ ::Gitlab::BackgroundMigration::Logger.warn(
+ migrator: self.class.name,
+ message: 'Could not update vulnerability!',
+ vulnerability_id: vulnerability.id
+ )
+ end
+
+ def log_error(error, vulnerability)
+ ::Gitlab::BackgroundMigration::Logger.error(
+ migrator: self.class.name,
+ message: error.message,
+ vulnerability_id: vulnerability.id
+ )
+ end
+ end
+ end
+end