# frozen_string_literal: true module Gitlab module BackgroundMigration # Populates missing dismissal information for vulnerabilities. class PopulateVulnerabilityDismissalFields < BatchedMigrationJob feature_category :vulnerability_management scope_to ->(relation) { relation.where('state = 2 AND (dismissed_at IS NULL OR dismissed_by_id IS NULL)') } operation_name :populate_vulnerability_dismissal_fields # rubocop:disable Style/Documentation class Vulnerability < ApplicationRecord self.table_name = 'vulnerabilities' has_one :finding, class_name: 'Finding' 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 < ApplicationRecord self.table_name = 'vulnerability_occurrences' validates :details, json_schema: { filename: "filename" } def dismissal_feedback Feedback.dismissal.where(finding_uuid: uuid).first end end class Feedback < ApplicationRecord DISMISSAL_TYPE = 0 # dismissal self.table_name = 'vulnerability_feedback' scope :dismissal, -> { where(feedback_type: DISMISSAL_TYPE) } end # rubocop:enable Style/Documentation def perform each_sub_batch do |sub_batch| vulnerability_ids = sub_batch.pluck(:id) Vulnerability.includes(:finding).where(id: vulnerability_ids).each do |vulnerability| populate_for(vulnerability) end log_info(vulnerability_ids) end 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