1# frozen_string_literal: true
2
3module Sha256Attribute
4  extend ActiveSupport::Concern
5
6  class_methods do
7    def sha256_attribute(name)
8      return if ENV['STATIC_VERIFICATION']
9
10      validate_binary_column_exists!(name) unless Rails.env.production?
11
12      attribute(name, Gitlab::Database::Sha256Attribute.new)
13    end
14
15    # This only gets executed in non-production environments as an additional check to ensure
16    # the column is the correct type.  In production it should behave like any other attribute.
17    # See https://gitlab.com/gitlab-org/gitlab/merge_requests/5502 for more discussion
18    def validate_binary_column_exists!(name)
19      return unless database_exists?
20
21      unless table_exists?
22        warn "WARNING: sha256_attribute #{name.inspect} is invalid since the table doesn't exist - you may need to run database migrations"
23        return
24      end
25
26      column = columns.find { |c| c.name == name.to_s }
27
28      unless column
29        warn "WARNING: sha256_attribute #{name.inspect} is invalid since the column doesn't exist - you may need to run database migrations"
30        return
31      end
32
33      unless column.type == :binary
34        raise ArgumentError, "sha256_attribute #{name.inspect} is invalid since the column type is not :binary"
35      end
36    rescue StandardError => error
37      Gitlab::AppLogger.error "Sha256Attribute initialization: #{error.message}"
38      raise
39    end
40
41    def database_exists?
42      database.exists?
43    end
44  end
45end
46