application_setting.rb 9.0 KB
Newer Older
1
class ApplicationSetting < ActiveRecord::Base
2
  include CacheMarkdownField
3
  include TokenAuthenticatable
4

5
  add_authentication_token_field :runners_registration_token
6
  add_authentication_token_field :health_check_access_token
7

8
  CACHE_KEY = 'application_setting.last'
9 10 11 12 13 14
  DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s*     # comma or semicolon, optionally surrounded by whitespace
                            |               # or
                            \s              # any whitespace character
                            |               # or
                            [\r\n]          # any number of newline characters
                          }x
15

16
  serialize :restricted_visibility_levels
17
  serialize :import_sources
18
  serialize :disabled_oauth_sign_in_sources, Array
19
  serialize :domain_whitelist, Array
20
  serialize :domain_blacklist, Array
21
  serialize :repository_storages
22
  serialize :sidekiq_throttling_queues, Array
23

24 25 26 27 28
  cache_markdown_field :sign_in_text
  cache_markdown_field :help_page_text
  cache_markdown_field :shared_runners_text, pipeline: :plain_markdown
  cache_markdown_field :after_sign_up_text

29
  attr_accessor :domain_whitelist_raw, :domain_blacklist_raw
30 31

  validates :session_expire_delay,
32 33
            presence: true,
            numericality: { only_integer: true, greater_than_or_equal_to: 0 }
34

35
  validates :home_page_url,
36 37 38
            allow_blank: true,
            url: true,
            if: :home_page_url_column_exist
39

40
  validates :after_sign_out_path,
41 42
            allow_blank: true,
            url: true
43

D
Douwe Maan 已提交
44
  validates :admin_notification_email,
45
            email: true,
46
            allow_blank: true
D
Douwe Maan 已提交
47

48
  validates :two_factor_grace_period,
49 50 51 52 53 54 55 56 57
            numericality: { greater_than_or_equal_to: 0 }

  validates :recaptcha_site_key,
            presence: true,
            if: :recaptcha_enabled

  validates :recaptcha_private_key,
            presence: true,
            if: :recaptcha_enabled
58

J
Jeroen Nijhof 已提交
59 60 61 62
  validates :sentry_dsn,
            presence: true,
            if: :sentry_enabled

63 64 65 66
  validates :akismet_api_key,
            presence: true,
            if: :akismet_enabled

67 68 69 70
  validates :koding_url,
            presence: true,
            if: :koding_enabled

71 72 73 74
  validates :plantuml_url,
            presence: true,
            if: :plantuml_enabled

75 76 77 78
  validates :max_attachment_size,
            presence: true,
            numericality: { only_integer: true, greater_than: 0 }

79 80 81 82
  validates :container_registry_token_expire_delay,
            presence: true,
            numericality: { only_integer: true, greater_than: 0 }

83 84
  validates :repository_storages, presence: true
  validate :check_repository_storages
85

86
  validates :enabled_git_access_protocol,
87
            inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true }
88

89
  validates :domain_blacklist,
90
            presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' },
91 92
            if: :domain_blacklist_enabled?

93 94 95 96 97 98 99 100 101
  validates :sidekiq_throttling_factor,
            numericality: { greater_than: 0, less_than: 1 },
            presence: { message: 'Throttling factor cannot be empty if Sidekiq Throttling is enabled.' },
            if: :sidekiq_throttling_enabled?

  validates :sidekiq_throttling_queues,
            presence: { message: 'Queues to throttle cannot be empty if Sidekiq Throttling is enabled.' },
            if: :sidekiq_throttling_enabled?

J
Jacob Vosmaer 已提交
102 103 104 105 106 107 108 109 110 111 112 113
  validates :housekeeping_incremental_repack_period,
            presence: true,
            numericality: { only_integer: true, greater_than: 0 }

  validates :housekeeping_full_repack_period,
            presence: true,
            numericality: { only_integer: true, greater_than: :housekeeping_incremental_repack_period }

  validates :housekeeping_gc_period,
            presence: true,
            numericality: { only_integer: true, greater_than: :housekeeping_full_repack_period }

114
  validates_each :restricted_visibility_levels do |record, attr, value|
V
Vinnie Okada 已提交
115 116 117 118 119
    unless value.nil?
      value.each do |level|
        unless Gitlab::VisibilityLevel.options.has_value?(level)
          record.errors.add(attr, "'#{level}' is not a valid visibility level")
        end
120 121 122 123
      end
    end
  end

124 125 126 127 128 129 130 131 132 133
  validates_each :import_sources do |record, attr, value|
    unless value.nil?
      value.each do |source|
        unless Gitlab::ImportSources.options.has_value?(source)
          record.errors.add(attr, "'#{source}' is not a import source")
        end
      end
    end
  end

134 135 136 137
  validates_each :disabled_oauth_sign_in_sources do |record, attr, value|
    unless value.nil?
      value.each do |source|
        unless Devise.omniauth_providers.include?(source.to_sym)
A
typo  
Andrei Gliga 已提交
138
          record.errors.add(attr, "'#{source}' is not an OAuth sign-in source")
139 140 141 142 143
        end
      end
    end
  end

144
  before_save :ensure_runners_registration_token
145
  before_save :ensure_health_check_access_token
146

147
  after_commit do
148
    Rails.cache.write(CACHE_KEY, self)
149 150
  end

151
  def self.current
152
    Rails.cache.fetch(CACHE_KEY) do
153 154
      ApplicationSetting.last
    end
155
  end
156

157
  def self.expire
158
    Rails.cache.delete(CACHE_KEY)
159 160
  rescue
    # Gracefully handle when Redis is not available. For example,
161
    # omnibus may fail here during gitlab:assets:compile.
162 163
  end

164 165 166 167
  def self.cached
    Rails.cache.fetch(CACHE_KEY)
  end

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
  def self.defaults_ce
    {
      after_sign_up_text: nil,
      akismet_enabled: false,
      container_registry_token_expire_delay: 5,
      default_branch_protection: Settings.gitlab['default_branch_protection'],
      default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
      default_projects_limit: Settings.gitlab['default_projects_limit'],
      default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
      disabled_oauth_sign_in_sources: [],
      domain_whitelist: Settings.gitlab['domain_whitelist'],
      gravatar_enabled: Settings.gravatar['enabled'],
      help_page_text: nil,
      housekeeping_bitmaps_enabled: true,
      housekeeping_enabled: true,
      housekeeping_full_repack_period: 50,
      housekeeping_gc_period: 200,
      housekeeping_incremental_repack_period: 10,
      import_sources: Gitlab::ImportSources.values,
      koding_enabled: false,
      koding_url: nil,
      max_artifacts_size: Settings.artifacts['max_size'],
      max_attachment_size: Settings.gitlab['max_attachment_size'],
      plantuml_enabled: false,
      plantuml_url: nil,
      recaptcha_enabled: false,
      repository_checks_enabled: true,
      repository_storages: ['default'],
      require_two_factor_authentication: false,
      restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
      session_expire_delay: Settings.gitlab['session_expire_delay'],
      send_user_confirmation_email: false,
      shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
      shared_runners_text: nil,
      sidekiq_throttling_enabled: false,
      sign_in_text: nil,
      signin_enabled: Settings.gitlab['signin_enabled'],
      signup_enabled: Settings.gitlab['signup_enabled'],
      two_factor_grace_period: 48,
      user_default_external: false
    }
  end

  def self.defaults
    defaults_ce
  end

215
  def self.create_from_defaults
216
    create(defaults)
217
  end
218 219 220 221

  def home_page_url_column_exist
    ActiveRecord::Base.connection.column_exists?(:application_settings, :home_page_url)
  end
222

223 224 225 226
  def sidekiq_throttling_column_exists?
    ActiveRecord::Base.connection.column_exists?(:application_settings, :sidekiq_throttling_enabled)
  end

227 228
  def domain_whitelist_raw
    self.domain_whitelist.join("\n") unless self.domain_whitelist.nil?
229 230
  end

231 232 233 234
  def domain_blacklist_raw
    self.domain_blacklist.join("\n") unless self.domain_blacklist.nil?
  end

235 236 237 238 239
  def domain_whitelist_raw=(values)
    self.domain_whitelist = []
    self.domain_whitelist = values.split(DOMAIN_LIST_SEPARATOR)
    self.domain_whitelist.reject! { |d| d.empty? }
    self.domain_whitelist
240
  end
241

242 243
  def domain_blacklist_raw=(values)
    self.domain_blacklist = []
244
    self.domain_blacklist = values.split(DOMAIN_LIST_SEPARATOR)
245
    self.domain_blacklist.reject! { |d| d.empty? }
246
    self.domain_blacklist
247 248 249 250 251 252
  end

  def domain_blacklist_file=(file)
    self.domain_blacklist_raw = file.read
  end

253
  def repository_storages
254
    Array(read_attribute(:repository_storages))
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
  end

  # repository_storage is still required in the API. Remove in 9.0
  def repository_storage
    repository_storages.first
  end

  def repository_storage=(value)
    self.repository_storages = [value]
  end

  # Choose one of the available repository storage options. Currently all have
  # equal weighting.
  def pick_repository_storage
    repository_storages.sample
  end

272 273 274
  def runners_registration_token
    ensure_runners_registration_token!
  end
275 276 277 278

  def health_check_access_token
    ensure_health_check_access_token!
  end
279

280 281 282 283 284 285
  def sidekiq_throttling_enabled?
    return false unless sidekiq_throttling_column_exists?

    sidekiq_throttling_enabled
  end

286 287 288 289 290 291 292
  private

  def check_repository_storages
    invalid = repository_storages - Gitlab.config.repositories.storages.keys
    errors.add(:repository_storages, "can't include: #{invalid.join(", ")}") unless
      invalid.empty?
  end
293
end