# 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 include ::Gitlab::Utils::StrongMemoize self.table_name = 'vulnerability_occurrences' sha_attribute :project_fingerprint def dismissal_feedback strong_memoize(:dismissal_feedback) do Feedback.dismissal.where(category: report_type, project_fingerprint: project_fingerprint, project_id: project_id).first end 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