debian-mirror-gitlab/app/models/application_setting.rb

340 lines
12 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2019-07-07 11:18:12 +05:30
class ApplicationSetting < ApplicationRecord
2018-11-08 19:23:39 +05:30
include CacheableAttributes
2016-11-03 12:29:30 +05:30
include CacheMarkdownField
2015-12-23 02:04:40 +05:30
include TokenAuthenticatable
2018-12-13 13:39:08 +05:30
include ChronicDurationAttribute
2016-11-03 12:29:30 +05:30
2019-10-31 01:37:42 +05:30
GRAFANA_URL_RULES = {
allow_localhost: true,
allow_local_network: true,
enforce_sanitization: true,
require_absolute: false
}.freeze
2019-07-07 11:18:12 +05:30
add_authentication_token_field :runners_registration_token, encrypted: -> { Feature.enabled?(:application_settings_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
2016-06-02 11:05:42 +05:30
add_authentication_token_field :health_check_access_token
2019-12-04 20:38:33 +05:30
add_authentication_token_field :static_objects_external_storage_auth_token
2015-12-23 02:04:40 +05:30
2019-10-12 21:52:04 +05:30
belongs_to :instance_administration_project, class_name: "Project"
2019-07-07 11:18:12 +05:30
# Include here so it can override methods from
# `add_authentication_token_field`
# We don't prepend for now because otherwise we'll need to
# fix a lot of tests using allow_any_instance_of
include ApplicationSettingImplementation
2018-03-17 18:26:18 +05:30
2019-09-04 21:01:54 +05:30
attr_encrypted :asset_proxy_secret_key,
mode: :per_attribute_iv,
insecure_mode: true,
key: Settings.attr_encrypted_db_key_base_truncated,
algorithm: 'aes-256-cbc'
2017-09-10 17:25:29 +05:30
serialize :restricted_visibility_levels # rubocop:disable Cop/ActiveRecordSerialize
serialize :import_sources # rubocop:disable Cop/ActiveRecordSerialize
serialize :disabled_oauth_sign_in_sources, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :domain_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :domain_blacklist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize
2019-09-04 21:01:54 +05:30
serialize :asset_proxy_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
2016-08-24 12:49:21 +05:30
2016-11-03 12:29:30 +05:30
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
2018-03-17 18:26:18 +05:30
default_value_for :id, 1
2018-12-13 13:39:08 +05:30
chronic_duration_attr_writer :archive_builds_in_human_readable, :archive_builds_in_seconds
2017-08-17 22:00:37 +05:30
validates :uuid, presence: true
2019-10-12 21:52:04 +05:30
validates :outbound_local_requests_whitelist,
length: { maximum: 1_000, message: N_('is too long (maximum is 1000 entries)') },
allow_nil: false,
qualified_domain_array: true
2019-10-31 01:37:42 +05:30
validates :grafana_url,
allow_blank: true,
allow_nil: true,
addressable_url: GRAFANA_URL_RULES
2015-09-11 14:41:01 +05:30
validates :session_expire_delay,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2015-04-26 12:48:37 +05:30
validates :home_page_url,
allow_blank: true,
2019-07-31 22:56:46 +05:30
addressable_url: true,
2017-09-10 17:25:29 +05:30
if: :home_page_url_column_exists?
validates :help_page_support_url,
allow_blank: true,
2019-07-31 22:56:46 +05:30
addressable_url: true,
2017-09-10 17:25:29 +05:30
if: :help_page_support_url_column_exists?
2015-04-26 12:48:37 +05:30
2015-09-11 14:41:01 +05:30
validates :after_sign_out_path,
allow_blank: true,
2019-07-31 22:56:46 +05:30
addressable_url: true
2015-10-24 18:46:33 +05:30
validates :admin_notification_email,
2019-07-07 11:18:12 +05:30
devise_email: true,
2016-04-02 18:10:28 +05:30
allow_blank: true
validates :two_factor_grace_period,
numericality: { greater_than_or_equal_to: 0 }
validates :recaptcha_site_key,
presence: true,
2019-09-04 21:01:54 +05:30
if: :recaptcha_or_login_protection_enabled
validates :recaptcha_private_key,
presence: true,
2019-09-04 21:01:54 +05:30
if: :recaptcha_or_login_protection_enabled
2015-10-24 18:46:33 +05:30
2016-04-02 18:10:28 +05:30
validates :akismet_api_key,
presence: true,
if: :akismet_enabled
2017-08-17 22:00:37 +05:30
validates :unique_ips_limit_per_user,
numericality: { greater_than_or_equal_to: 1 },
presence: true,
if: :unique_ips_limit_enabled
validates :unique_ips_limit_time_window,
numericality: { greater_than_or_equal_to: 0 },
presence: true,
if: :unique_ips_limit_enabled
validates :plantuml_url,
presence: true,
if: :plantuml_enabled
2019-10-12 21:52:04 +05:30
validates :snowplow_collector_hostname,
presence: true,
hostname: true,
if: :snowplow_enabled
2016-04-02 18:10:28 +05:30
validates :max_attachment_size,
presence: true,
numericality: { only_integer: true, greater_than: 0 }
2017-08-17 22:00:37 +05:30
validates :max_artifacts_size,
presence: true,
numericality: { only_integer: true, greater_than: 0 }
validates :default_artifacts_expire_in, presence: true, duration: true
validates :container_registry_token_expire_delay,
presence: true,
numericality: { only_integer: true, greater_than: 0 }
2016-11-24 13:41:30 +05:30
validates :repository_storages, presence: true
validate :check_repository_storages
2016-08-24 12:49:21 +05:30
2018-03-17 18:26:18 +05:30
validates :auto_devops_domain,
allow_blank: true,
hostname: { allow_numeric_hostname: true, require_valid_tld: true },
if: :auto_devops_enabled?
2016-08-24 12:49:21 +05:30
validates :enabled_git_access_protocol,
inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true }
validates :domain_blacklist,
presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' },
if: :domain_blacklist_enabled?
2017-08-17 22:00:37 +05:30
validates :housekeeping_incremental_repack_period,
presence: true,
numericality: { only_integer: true, greater_than: 0 }
validates :housekeeping_full_repack_period,
presence: true,
2018-03-17 18:26:18 +05:30
numericality: { only_integer: true, greater_than_or_equal_to: :housekeeping_incremental_repack_period }
2017-08-17 22:00:37 +05:30
validates :housekeeping_gc_period,
presence: true,
2018-03-17 18:26:18 +05:30
numericality: { only_integer: true, greater_than_or_equal_to: :housekeeping_full_repack_period }
2017-08-17 22:00:37 +05:30
validates :terminal_max_session_time,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :polling_interval_multiplier,
presence: true,
numericality: { greater_than_or_equal_to: 0 }
2018-03-17 18:26:18 +05:30
validates :gitaly_timeout_default,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :gitaly_timeout_medium,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :gitaly_timeout_medium,
numericality: { less_than_or_equal_to: :gitaly_timeout_default },
if: :gitaly_timeout_default
validates :gitaly_timeout_medium,
numericality: { greater_than_or_equal_to: :gitaly_timeout_fast },
if: :gitaly_timeout_fast
validates :gitaly_timeout_fast,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :gitaly_timeout_fast,
numericality: { less_than_or_equal_to: :gitaly_timeout_default },
if: :gitaly_timeout_default
2018-12-05 23:21:45 +05:30
validates :diff_max_patch_bytes,
presence: true,
numericality: { only_integer: true,
greater_than_or_equal_to: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
less_than_or_equal_to: Gitlab::Git::Diff::MAX_PATCH_BYTES_UPPER_BOUND }
2018-11-20 20:47:30 +05:30
validates :user_default_internal_regex, js_regex: true, allow_nil: true
2018-12-13 13:39:08 +05:30
validates :commit_email_hostname, format: { with: /\A[^@]+\z/ }
validates :archive_builds_in_seconds,
allow_nil: true,
numericality: { only_integer: true, greater_than_or_equal_to: 1.day.seconds }
2019-03-02 22:35:43 +05:30
validates :local_markdown_version,
allow_nil: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than: 65536 }
2019-09-04 21:01:54 +05:30
validates :asset_proxy_url,
presence: true,
allow_blank: false,
url: true,
if: :asset_proxy_enabled?
validates :asset_proxy_secret_key,
presence: true,
allow_blank: false,
if: :asset_proxy_enabled?
2019-12-04 20:38:33 +05:30
validates :static_objects_external_storage_url,
addressable_url: true, allow_blank: true
validates :static_objects_external_storage_auth_token,
presence: true,
if: :static_objects_external_storage_url?
2018-03-17 18:26:18 +05:30
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
validates :allowed_key_types, presence: true
2015-04-26 12:48:37 +05:30
validates_each :restricted_visibility_levels do |record, attr, value|
2017-08-17 22:00:37 +05:30
value&.each do |level|
2017-09-10 17:25:29 +05:30
unless Gitlab::VisibilityLevel.options.value?(level)
2019-07-31 22:56:46 +05:30
record.errors.add(attr, _("'%{level}' is not a valid visibility level") % { level: level })
2015-04-26 12:48:37 +05:30
end
end
end
2015-09-25 12:07:36 +05:30
validates_each :import_sources do |record, attr, value|
2017-08-17 22:00:37 +05:30
value&.each do |source|
2017-09-10 17:25:29 +05:30
unless Gitlab::ImportSources.options.value?(source)
2019-07-31 22:56:46 +05:30
record.errors.add(attr, _("'%{source}' is not a import source") % { source: source })
2015-09-25 12:07:36 +05:30
end
end
end
2018-10-15 14:42:47 +05:30
validate :terms_exist, if: :enforce_terms?
2019-07-07 11:18:12 +05:30
validates :external_authorization_service_default_label,
presence: true,
if: :external_authorization_service_enabled
validates :external_authorization_service_url,
2019-07-31 22:56:46 +05:30
addressable_url: true, allow_blank: true,
2019-07-07 11:18:12 +05:30
if: :external_authorization_service_enabled
validates :external_authorization_service_timeout,
numericality: { greater_than: 0, less_than_or_equal_to: 10 },
if: :external_authorization_service_enabled
validates :external_auth_client_key,
presence: true,
if: -> (setting) { setting.external_auth_client_cert.present? }
2019-07-31 22:56:46 +05:30
validates :lets_encrypt_notification_email,
devise_email: true,
format: { without: /@example\.(com|org|net)\z/,
message: N_("Let's Encrypt does not accept emails on example.com") },
allow_blank: true
validates :lets_encrypt_notification_email,
presence: true,
if: :lets_encrypt_terms_of_service_accepted?
2019-07-07 11:18:12 +05:30
validates_with X509CertificateCredentialsValidator,
certificate: :external_auth_client_cert,
pkey: :external_auth_client_key,
pass: :external_auth_client_key_pass,
if: -> (setting) { setting.external_auth_client_cert.present? }
2019-12-04 20:38:33 +05:30
private_class_method def self.encryption_options_base_truncated_aes_256_gcm
{
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
algorithm: 'aes-256-gcm',
encode: true
}
end
2019-07-07 11:18:12 +05:30
2019-12-04 20:38:33 +05:30
attr_encrypted :external_auth_client_key, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :external_auth_client_key_pass, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :lets_encrypt_private_key, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :akismet_api_key, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :recaptcha_private_key, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :recaptcha_site_key, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :slack_app_secret, encryption_options_base_truncated_aes_256_gcm
attr_encrypted :slack_app_verification_token, encryption_options_base_truncated_aes_256_gcm
2019-09-04 21:01:54 +05:30
2017-08-17 22:00:37 +05:30
before_validation :ensure_uuid!
2018-03-17 18:26:18 +05:30
2015-12-23 02:04:40 +05:30
before_save :ensure_runners_registration_token
2016-06-02 11:05:42 +05:30
before_save :ensure_health_check_access_token
2015-12-23 02:04:40 +05:30
2015-11-26 14:37:03 +05:30
after_commit do
2018-10-15 14:42:47 +05:30
reset_memoized_terms
2017-08-17 22:00:37 +05:30
end
2018-11-08 19:23:39 +05:30
after_commit :expire_performance_bar_allowed_user_ids_cache, if: -> { previous_changes.key?('performance_bar_allowed_group_id') }
2017-08-17 22:00:37 +05:30
def self.create_from_defaults
2019-07-31 22:56:46 +05:30
transaction(requires_new: true) do
super
end
2019-07-07 11:18:12 +05:30
rescue ActiveRecord::RecordNotUnique
# We already have an ApplicationSetting record, so just return it.
current_without_cache
2018-11-08 19:23:39 +05:30
end
2019-09-04 21:01:54 +05:30
2019-10-31 01:37:42 +05:30
def grafana_url
if Gitlab::UrlBlocker.blocked_url?(self[:grafana_url], GRAFANA_URL_RULES)
ApplicationSetting.column_defaults["grafana_url"]
else
self[:grafana_url]
end
end
2019-09-30 21:07:59 +05:30
# By default, the backend is Rails.cache, which uses
# ActiveSupport::Cache::RedisStore. Since loading ApplicationSetting
# can cause a significant amount of load on Redis, let's cache it in
# memory.
def self.cache_backend
Gitlab::ThreadMemoryCache.cache_backend
end
2019-09-04 21:01:54 +05:30
def recaptcha_or_login_protection_enabled
recaptcha_enabled || login_recaptcha_protection_enabled
end
2015-04-26 12:48:37 +05:30
end
2019-12-04 20:38:33 +05:30
ApplicationSetting.prepend_if_ee('EE::ApplicationSetting')