summaryrefslogtreecommitdiff
path: root/lib/gitlab/database/migration_helpers/restrict_gitlab_schema.rb
blob: b4e31565c6090d1a9134cb5389391772e1d3e664 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# frozen_string_literal: true

module Gitlab
  module Database
    module MigrationHelpers
      module RestrictGitlabSchema
        extend ActiveSupport::Concern

        MigrationSkippedError = Class.new(StandardError)

        included do
          class_attribute :allowed_gitlab_schemas
        end

        class_methods do
          def restrict_gitlab_migration(gitlab_schema:)
            unless Gitlab::Database::GitlabSchema.schema_names.include?(gitlab_schema)
              raise "Unknown 'gitlab_schema: #{gitlab_schema}' specified. It needs to be one of: " \
                "#{Gitlab::Database::GitlabSchema.schema_names.to_a}"
            end

            self.allowed_gitlab_schemas = [gitlab_schema]
          end
        end

        def migrate(direction)
          if unmatched_schemas.any?
            # TODO: Today skipping migration would raise an exception.
            # Ideally, skipped migration should be ignored (not loaded), or softly ignored.
            # Read more in: https://gitlab.com/gitlab-org/gitlab/-/issues/355014
            raise MigrationSkippedError, "Current migration is skipped since it modifies "\
              "'#{self.class.allowed_gitlab_schemas}' which is outside of '#{allowed_schemas_for_connection}'"
          end

          Gitlab::Database::QueryAnalyzer.instance.within([validator_class]) do
            validator_class.allowed_gitlab_schemas = self.allowed_gitlab_schemas

            super
          end
        end

        private

        def validator_class
          Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas
        end

        def unmatched_schemas
          (self.allowed_gitlab_schemas || []) - allowed_schemas_for_connection
        end

        def allowed_schemas_for_connection
          Gitlab::Database.gitlab_schemas_for_connection(connection)
        end
      end
    end
  end
end