application_setting.rb 9.03 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

Douwe Maan's avatar
Douwe Maan committed
8
  CACHE_KEY = 'application_setting.last'.freeze
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

44
  validates :admin_notification_email,
45
            email: true,
46
            allow_blank: true
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

Jeroen Nijhof's avatar
Jeroen Nijhof committed
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?

Jacob Vosmaer's avatar
Jacob Vosmaer committed
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
115
116
117
  validates :terminal_max_session_time,
            presence: true,
            numericality: { only_integer: true, greater_than_or_equal_to: 0 }

118
  validates_each :restricted_visibility_levels do |record, attr, value|
Z.J. van de Weg's avatar
Z.J. van de Weg committed
119
120
121
    value&.each do |level|
      unless Gitlab::VisibilityLevel.options.has_value?(level)
        record.errors.add(attr, "'#{level}' is not a valid visibility level")
122
123
124
125
      end
    end
  end

126
  validates_each :import_sources do |record, attr, value|
Z.J. van de Weg's avatar
Z.J. van de Weg committed
127
128
129
    value&.each do |source|
      unless Gitlab::ImportSources.options.has_value?(source)
        record.errors.add(attr, "'#{source}' is not a import source")
130
131
132
133
      end
    end
  end

134
  validates_each :disabled_oauth_sign_in_sources do |record, attr, value|
Z.J. van de Weg's avatar
Z.J. van de Weg committed
135
136
137
    value&.each do |source|
      unless Devise.omniauth_providers.include?(source.to_sym)
        record.errors.add(attr, "'#{source}' is not an OAuth sign-in source")
138
139
140
141
      end
    end
  end

142
  before_save :ensure_runners_registration_token
143
  before_save :ensure_health_check_access_token
144

145
  after_commit do
146
    Rails.cache.write(CACHE_KEY, self)
147
148
  end

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

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

162
163
164
165
  def self.cached
    Rails.cache.fetch(CACHE_KEY)
  end

166
167
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
  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,
205
206
      user_default_external: false,
      terminal_max_session_time: 0
207
208
209
210
211
212
213
    }
  end

  def self.defaults
    defaults_ce
  end

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

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

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

226
  def domain_whitelist_raw
Z.J. van de Weg's avatar
Z.J. van de Weg committed
227
    self.domain_whitelist&.join("\n")
228
229
  end

230
  def domain_blacklist_raw
Z.J. van de Weg's avatar
Z.J. van de Weg committed
231
    self.domain_blacklist&.join("\n")
232
233
  end

234
235
236
237
238
  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
239
  end
240

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

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

252
  def repository_storages
253
    Array(read_attribute(:repository_storages))
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  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

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

  def health_check_access_token
    ensure_health_check_access_token!
  end
278

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

    sidekiq_throttling_enabled
  end

285
286
287
288
289
290
291
  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
292
end