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

848 lines
34 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
2021-10-27 15:23:28 +05:30
include IgnorableColumns
2021-11-11 11:23:49 +05:30
include Sanitizable
2021-10-27 15:23:28 +05:30
ignore_columns %i[elasticsearch_shards elasticsearch_replicas], remove_with: '14.4', remove_after: '2021-09-22'
2022-03-02 08:16:31 +05:30
ignore_columns %i[static_objects_external_storage_auth_token], remove_with: '14.9', remove_after: '2022-03-22'
2022-05-07 20:08:51 +05:30
ignore_column :user_email_lookup_limit, remove_with: '15.0', remove_after: '2022-04-18'
2023-03-04 22:38:38 +05:30
ignore_column :send_user_confirmation_email, remove_with: '15.8', remove_after: '2022-12-18'
2016-11-03 12:29:30 +05:30
2021-01-03 14:25:43 +05:30
INSTANCE_REVIEW_MIN_USERS = 50
2020-03-07 23:17:34 +05:30
GRAFANA_URL_ERROR_MESSAGE = 'Please check your Grafana URL setting in ' \
'Admin Area > Settings > Metrics and profiling > Metrics - Grafana'
2021-02-22 17:27:13 +05:30
KROKI_URL_ERROR_MESSAGE = 'Please check your Kroki URL setting in ' \
'Admin Area > Settings > General > Kroki'
2021-06-08 01:23:25 +05:30
enum whats_new_variant: { all_tiers: 0, current_tier: 1, disabled: 2 }, _prefix: true
2023-03-04 22:38:38 +05:30
enum email_confirmation_setting: { off: 0, soft: 1, hard: 2 }, _prefix: true
2021-06-08 01:23:25 +05:30
2020-10-24 23:57:45 +05:30
add_authentication_token_field :runners_registration_token, encrypted: -> { Feature.enabled?(:application_settings_tokens_optional_encryption) ? :optional : :required }
2016-06-02 11:05:42 +05:30
add_authentication_token_field :health_check_access_token
2022-03-02 08:16:31 +05:30
add_authentication_token_field :static_objects_external_storage_auth_token, encrypted: :required
2022-08-13 15:12:31 +05:30
add_authentication_token_field :error_tracking_access_token, encrypted: :required
2015-12-23 02:04:40 +05:30
2020-03-13 15:44:24 +05:30
belongs_to :self_monitoring_project, class_name: "Project", foreign_key: 'instance_administration_project_id'
2020-04-22 19:07:51 +05:30
belongs_to :push_rule
2020-03-13 15:44:24 +05:30
alias_attribute :self_monitoring_project_id, :instance_administration_project_id
2020-11-24 15:15:51 +05:30
belongs_to :instance_group, class_name: "Group", foreign_key: 'instance_administrators_group_id'
alias_attribute :instance_group_id, :instance_administrators_group_id
alias_attribute :instance_administrators_group, :instance_group
2023-03-17 16:20:25 +05:30
alias_attribute :housekeeping_optimize_repository_period, :housekeeping_incremental_repack_period
2019-10-12 21:52:04 +05:30
2021-11-11 11:23:49 +05:30
sanitizes! :default_branch_name
2021-03-11 19:13:27 +05:30
def self.kroki_formats_attributes
{
blockdiag: {
2021-10-27 15:23:28 +05:30
label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, and RackDiag)'
2021-03-11 19:13:27 +05:30
},
bpmn: {
label: 'BPMN'
},
excalidraw: {
label: 'Excalidraw'
}
}
end
store_accessor :kroki_formats, *ApplicationSetting.kroki_formats_attributes.keys, prefix: true
2020-06-23 00:09:42 +05:30
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
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
2021-01-29 00:20:46 +05:30
serialize :domain_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :domain_denylist, Array # rubocop:disable Cop/ActiveRecordSerialize
2017-09-10 17:25:29 +05:30
serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize
2021-03-11 19:13:27 +05:30
# See https://gitlab.com/gitlab-org/gitlab/-/issues/300916
serialize :asset_proxy_allowlist, Array # 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
2023-01-13 00:05:48 +05:30
attribute :id, default: 1
attribute :repository_storages_weighted, default: -> { {} }
attribute :kroki_formats, default: -> { {} }
2018-03-17 18:26:18 +05:30
2018-12-13 13:39:08 +05:30
chronic_duration_attr_writer :archive_builds_in_human_readable, :archive_builds_in_seconds
2022-03-02 08:16:31 +05:30
chronic_duration_attr :runner_token_expiration_interval_human_readable, :runner_token_expiration_interval
chronic_duration_attr :group_runner_token_expiration_interval_human_readable, :group_runner_token_expiration_interval
chronic_duration_attr :project_runner_token_expiration_interval_human_readable, :project_runner_token_expiration_interval
2020-03-07 23:17:34 +05:30
validates :grafana_url,
system_hook_url: {
2023-03-04 22:38:38 +05:30
blocked_message: "is blocked: %{exception_message}. #{GRAFANA_URL_ERROR_MESSAGE}"
2020-03-07 23:17:34 +05:30
},
if: :grafana_url_absolute?
validate :validate_grafana_url
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
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
2020-01-01 13:55:28 +05:30
validates :minimum_password_length,
presence: true,
numericality: { only_integer: true,
greater_than_or_equal_to: DEFAULT_MINIMUM_PASSWORD_LENGTH,
less_than_or_equal_to: Devise.password_length.max }
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
2021-01-03 14:25:43 +05:30
validates :help_page_documentation_base_url,
2022-11-25 23:54:43 +05:30
length: { maximum: 255, message: N_("is too long (maximum is %{count} characters)") },
2021-01-03 14:25:43 +05:30
allow_blank: true,
addressable_url: true
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
2019-12-21 20:55:43 +05:30
2021-01-03 14:25:43 +05:30
validates :abuse_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
2021-06-08 01:23:25 +05:30
validates :spam_check_api_key,
2022-11-25 23:54:43 +05:30
length: { maximum: 2000, message: N_('is too long (maximum is %{count} characters)') },
2021-06-08 01:23:25 +05:30
allow_blank: true
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
2021-02-22 17:27:13 +05:30
validates :kroki_url,
presence: { if: :kroki_enabled }
validate :validate_kroki_url, if: :kroki_enabled
2021-03-11 19:13:27 +05:30
validates :kroki_formats, json_schema: { filename: 'application_setting_kroki_formats' }
2022-08-13 15:12:31 +05:30
validates :metrics_method_call_threshold,
numericality: { greater_than_or_equal_to: 0 },
presence: true,
if: :prometheus_metrics_enabled
2017-08-17 22:00:37 +05:30
validates :plantuml_url,
presence: true,
if: :plantuml_enabled
2019-12-26 22:10:19 +05:30
validates :sourcegraph_url,
presence: true,
if: :sourcegraph_enabled
2020-11-24 15:15:51 +05:30
validates :gitpod_url,
presence: true,
addressable_url: { enforce_sanitization: true },
if: :gitpod_enabled
2021-09-30 23:02:18 +05:30
validates :mailgun_signing_key,
presence: true,
length: { maximum: 255 },
if: :mailgun_events_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 }
2022-07-16 23:28:13 +05:30
validates :max_export_size,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2020-06-23 00:09:42 +05:30
validates :max_import_size,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2020-03-13 15:44:24 +05:30
validates :max_pages_size,
presence: true,
2020-04-22 19:07:51 +05:30
numericality: { only_integer: true, greater_than_or_equal_to: 0,
2020-03-13 15:44:24 +05:30
less_than: ::Gitlab::Pages::MAX_SIZE / 1.megabyte }
2022-10-11 01:57:18 +05:30
validates :max_pages_custom_domains_per_project,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2021-11-11 11:23:49 +05:30
validates :jobs_per_stage_page_size,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2023-03-04 22:38:38 +05:30
validates :max_terraform_state_size_bytes,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2017-08-17 22:00:37 +05:30
validates :default_artifacts_expire_in, presence: true, duration: true
2020-04-22 19:07:51 +05:30
validates :container_expiration_policies_enable_historic_entries,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2020-04-22 19:07:51 +05:30
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
2020-06-23 00:09:42 +05:30
validate :check_repository_storages_weighted
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,
2020-03-13 15:44:24 +05:30
inclusion: { in: %w(ssh http), allow_blank: true }
2016-08-24 12:49:21 +05:30
2021-01-29 00:20:46 +05:30
validates :domain_denylist,
presence: { message: 'Domain denylist cannot be empty if denylist is enabled.' },
if: :domain_denylist_enabled?
2016-08-24 12:49:21 +05:30
2023-03-17 16:20:25 +05:30
validates :housekeeping_optimize_repository_period,
2017-08-17 22:00:37 +05:30
presence: true,
numericality: { only_integer: true, greater_than: 0 }
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,
2020-04-08 14:13:33 +05:30
if: :gitaly_timeout_default_changed?,
2020-03-13 15:44:24 +05:30
numericality: {
only_integer: true,
greater_than_or_equal_to: 0,
less_than_or_equal_to: Settings.gitlab.max_request_duration_seconds
}
2018-03-17 18:26:18 +05:30
validates :gitaly_timeout_medium,
presence: true,
2020-04-08 14:13:33 +05:30
if: :gitaly_timeout_medium_changed?,
2018-03-17 18:26:18 +05:30
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,
2020-04-08 14:13:33 +05:30
if: :gitaly_timeout_fast_changed?,
2018-03-17 18:26:18 +05:30
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 }
2021-09-04 01:27:46 +05:30
validates :diff_max_files,
presence: true,
numericality: { only_integer: true,
greater_than_or_equal_to: Commit::DEFAULT_MAX_DIFF_FILES_SETTING,
less_than_or_equal_to: Commit::MAX_DIFF_FILES_SETTING_UPPER_BOUND }
validates :diff_max_lines,
presence: true,
numericality: { only_integer: true,
greater_than_or_equal_to: Commit::DEFAULT_MAX_DIFF_LINES_SETTING,
less_than_or_equal_to: Commit::MAX_DIFF_LINES_SETTING_UPPER_BOUND }
2018-11-20 20:47:30 +05:30
validates :user_default_internal_regex, js_regex: true, allow_nil: true
2023-01-13 00:05:48 +05:30
validates :default_preferred_language, presence: true, inclusion: { in: Gitlab::I18n.available_locales }
2018-11-20 20:47:30 +05:30
2021-02-22 17:27:13 +05:30
validates :personal_access_token_prefix,
2021-09-30 23:02:18 +05:30
format: { with: %r{\A[a-zA-Z0-9_+=/@:.-]+\z},
2022-11-25 23:54:43 +05:30
message: N_("can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'") },
length: { maximum: 20, message: N_('is too long (maximum is %{count} characters)') },
2021-02-22 17:27:13 +05:30
allow_blank: 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?
2019-12-21 20:55:43 +05:30
validates :protected_paths,
length: { maximum: 100, message: N_('is too long (maximum is 100 entries)') },
allow_nil: false
validates :push_event_hooks_limit,
numericality: { greater_than_or_equal_to: 0 }
validates :push_event_activities_limit,
numericality: { greater_than_or_equal_to: 0 }
2020-01-01 13:55:28 +05:30
validates :snippet_size_limit, numericality: { only_integer: true, greater_than: 0 }
2020-10-24 23:57:45 +05:30
validates :wiki_page_max_content_bytes, numericality: { only_integer: true, greater_than_or_equal_to: 1.kilobytes }
2021-11-11 11:23:49 +05:30
validates :max_yaml_size_bytes, numericality: { only_integer: true, greater_than: 0 }, presence: true
validates :max_yaml_depth, numericality: { only_integer: true, greater_than: 0 }, presence: true
2020-01-01 13:55:28 +05:30
2020-04-22 19:07:51 +05:30
validates :email_restrictions, untrusted_regexp: true
2020-04-08 14:13:33 +05:30
2022-11-25 23:54:43 +05:30
validates :hashed_storage_enabled, inclusion: { in: [true], message: N_("Hashed storage can't be disabled anymore for new projects") }
2020-05-24 23:13:21 +05:30
2020-11-24 15:15:51 +05:30
validates :container_registry_delete_tags_service_timeout,
2022-03-02 08:16:31 +05:30
:container_registry_cleanup_tags_service_max_list_size,
:container_registry_expiration_policies_worker_capacity,
2020-11-24 15:15:51 +05:30
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2022-05-07 20:08:51 +05:30
validates :container_registry_expiration_policies_caching,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2022-05-07 20:08:51 +05:30
2022-03-02 08:16:31 +05:30
validates :container_registry_import_max_tags_count,
:container_registry_import_max_retries,
:container_registry_import_start_max_retries,
:container_registry_import_max_step_duration,
2022-07-16 23:28:13 +05:30
:container_registry_pre_import_timeout,
:container_registry_import_timeout,
2022-03-02 08:16:31 +05:30
allow_nil: false,
2021-03-08 18:12:59 +05:30
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2022-07-23 23:45:48 +05:30
validates :container_registry_pre_import_tags_rate,
allow_nil: false,
numericality: { greater_than_or_equal_to: 0 }
2022-03-02 08:16:31 +05:30
validates :container_registry_import_target_plan, presence: true
validates :container_registry_import_created_before, presence: true
2021-01-29 00:20:46 +05:30
2021-11-18 22:05:49 +05:30
validates :dependency_proxy_ttl_group_policy_worker_capacity,
allow_nil: false,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2022-03-02 08:16:31 +05:30
validates :packages_cleanup_package_file_worker_capacity,
2022-08-13 15:12:31 +05:30
:package_registry_cleanup_policies_worker_capacity,
2022-03-02 08:16:31 +05:30
allow_nil: false,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2021-03-08 18:12:59 +05:30
validates :invisible_captcha_enabled,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2021-03-08 18:12:59 +05:30
2023-03-17 16:20:25 +05:30
validates :invitation_flow_enforcement, :can_create_group, :user_defaults_to_private_profile,
2022-10-11 01:57:18 +05:30
allow_nil: false,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
validates :deactivate_dormant_users_period,
presence: true,
2023-03-04 22:38:38 +05:30
numericality: { only_integer: true, greater_than_or_equal_to: 90, message: N_("'%{value}' days of inactivity must be greater than or equal to 90") },
2022-11-25 23:54:43 +05:30
if: :deactivate_dormant_users?
2022-10-11 01:57:18 +05:30
2022-06-21 17:19:12 +05:30
Gitlab::SSHPublicKey.supported_types.each do |type|
2018-03-17 18:26:18 +05:30
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
2021-09-30 23:02:18 +05:30
validate :check_valid_runner_registrars
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
2020-06-23 00:09:42 +05:30
validates :spam_check_endpoint_url,
2022-01-26 12:08:38 +05:30
addressable_url: { schemes: %w(tls grpc) }, allow_blank: true
2020-06-23 00:09:42 +05:30
validates :spam_check_endpoint_url,
presence: true,
if: :spam_check_endpoint_enabled
2019-07-07 11:18:12 +05:30
validates :external_auth_client_key,
presence: true,
2023-03-04 22:38:38 +05:30
if: ->(setting) { setting.external_auth_client_cert.present? }
2019-07-07 11:18:12 +05:30
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-12-26 22:10:19 +05:30
validates :eks_integration_enabled,
inclusion: { in: [true, false] }
validates :eks_account_id,
format: { with: Gitlab::Regex.aws_account_id_regex,
message: Gitlab::Regex.aws_account_id_message },
if: :eks_integration_enabled?
validates :eks_access_key_id,
length: { in: 16..128 },
2023-03-04 22:38:38 +05:30
if: ->(setting) { setting.eks_integration_enabled? && setting.eks_access_key_id.present? }
2019-12-26 22:10:19 +05:30
validates :eks_secret_access_key,
presence: true,
2023-03-04 22:38:38 +05:30
if: ->(setting) { setting.eks_integration_enabled? && setting.eks_access_key_id.present? }
2019-12-26 22:10:19 +05:30
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,
2023-03-04 22:38:38 +05:30
if: ->(setting) { setting.external_auth_client_cert.present? }
2019-07-07 11:18:12 +05:30
2019-12-26 22:10:19 +05:30
validates :default_ci_config_path,
format: { without: %r{(\.{2}|\A/)},
message: N_('cannot include leading slash or directory traversal.') },
length: { maximum: 255 },
allow_blank: true
2020-05-24 23:13:21 +05:30
validates :issues_create_limit,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :raw_blob_request_limit,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2022-07-16 23:28:13 +05:30
validates :pipeline_limit_per_project_user_sha,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2021-01-29 00:20:46 +05:30
validates :ci_jwt_signing_key,
rsa_key: true, allow_nil: true
2021-10-27 15:23:28 +05:30
validates :customers_dot_jwt_signing_key,
rsa_key: true, allow_nil: true
2021-03-08 18:12:59 +05:30
validates :rate_limiting_response_text,
2022-11-25 23:54:43 +05:30
length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
2021-03-08 18:12:59 +05:30
allow_blank: true
2022-07-23 23:45:48 +05:30
validates :jira_connect_application_key,
2022-11-25 23:54:43 +05:30
length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
2022-07-23 23:45:48 +05:30
allow_blank: true
2023-01-13 00:05:48 +05:30
validates :jira_connect_proxy_url,
length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
allow_blank: true,
public_url: true
2021-11-11 11:23:49 +05:30
with_options(presence: true, numericality: { only_integer: true, greater_than: 0 }) do
validates :throttle_unauthenticated_api_requests_per_period
validates :throttle_unauthenticated_api_period_in_seconds
validates :throttle_unauthenticated_requests_per_period
validates :throttle_unauthenticated_period_in_seconds
validates :throttle_unauthenticated_packages_api_requests_per_period
validates :throttle_unauthenticated_packages_api_period_in_seconds
validates :throttle_unauthenticated_files_api_requests_per_period
validates :throttle_unauthenticated_files_api_period_in_seconds
2021-11-18 22:05:49 +05:30
validates :throttle_unauthenticated_deprecated_api_requests_per_period
validates :throttle_unauthenticated_deprecated_api_period_in_seconds
2021-11-11 11:23:49 +05:30
validates :throttle_authenticated_api_requests_per_period
validates :throttle_authenticated_api_period_in_seconds
validates :throttle_authenticated_git_lfs_requests_per_period
validates :throttle_authenticated_git_lfs_period_in_seconds
validates :throttle_authenticated_web_requests_per_period
validates :throttle_authenticated_web_period_in_seconds
validates :throttle_authenticated_packages_api_requests_per_period
validates :throttle_authenticated_packages_api_period_in_seconds
validates :throttle_authenticated_files_api_requests_per_period
validates :throttle_authenticated_files_api_period_in_seconds
2021-11-18 22:05:49 +05:30
validates :throttle_authenticated_deprecated_api_requests_per_period
validates :throttle_authenticated_deprecated_api_period_in_seconds
2021-11-11 11:23:49 +05:30
validates :throttle_protected_paths_requests_per_period
validates :throttle_protected_paths_period_in_seconds
end
2021-03-08 18:12:59 +05:30
2021-03-11 19:13:27 +05:30
validates :notes_create_limit,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2022-05-07 20:08:51 +05:30
validates :search_rate_limit,
2022-03-02 08:16:31 +05:30
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2022-05-07 20:08:51 +05:30
validates :search_rate_limit_unauthenticated,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2021-03-11 19:13:27 +05:30
validates :notes_create_limit_allowlist,
length: { maximum: 100, message: N_('is too long (maximum is 100 entries)') },
allow_nil: false
2021-04-29 21:17:54 +05:30
validates :admin_mode,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2021-04-29 21:17:54 +05:30
validates :external_pipeline_validation_service_url,
addressable_url: true, allow_blank: true
validates :external_pipeline_validation_service_timeout,
allow_nil: true,
numericality: { only_integer: true, greater_than: 0 }
2021-06-08 01:23:25 +05:30
validates :whats_new_variant,
inclusion: { in: ApplicationSetting.whats_new_variants.keys }
validates :floc_enabled,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2021-06-08 01:23:25 +05:30
2021-11-11 11:23:49 +05:30
enum sidekiq_job_limiter_mode: {
Gitlab::SidekiqMiddleware::SizeLimiter::Validator::TRACK_MODE => 0,
Gitlab::SidekiqMiddleware::SizeLimiter::Validator::COMPRESS_MODE => 1 # The default
}
validates :sidekiq_job_limiter_mode,
inclusion: { in: self.sidekiq_job_limiter_modes }
validates :sidekiq_job_limiter_compression_threshold_bytes,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :sidekiq_job_limiter_limit_bytes,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
2021-12-11 22:18:48 +05:30
validates :sentry_enabled,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2021-12-11 22:18:48 +05:30
validates :sentry_dsn,
addressable_url: true, presence: true, length: { maximum: 255 },
if: :sentry_enabled?
validates :sentry_clientside_dsn,
addressable_url: true, allow_blank: true, length: { maximum: 255 },
if: :sentry_enabled?
validates :sentry_environment,
presence: true, length: { maximum: 255 },
if: :sentry_enabled?
2022-08-13 15:12:31 +05:30
validates :error_tracking_enabled,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2022-08-13 15:12:31 +05:30
validates :error_tracking_api_url,
presence: true,
addressable_url: true,
length: { maximum: 255 },
if: :error_tracking_enabled?
2022-04-04 11:22:00 +05:30
validates :users_get_by_id_limit,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :users_get_by_id_limit_allowlist,
length: { maximum: 100, message: N_('is too long (maximum is 100 entries)') },
allow_nil: false
2022-06-21 17:19:12 +05:30
validates :public_runner_releases_url, addressable_url: true, presence: true
validates :inactive_projects_min_size_mb,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :inactive_projects_delete_after_months,
numericality: { only_integer: true, greater_than: 0 }
validates :inactive_projects_send_warning_email_after_months,
numericality: { only_integer: true, greater_than: 0, less_than: :inactive_projects_delete_after_months }
2019-12-26 22:10:19 +05:30
attr_encrypted :asset_proxy_secret_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
algorithm: 'aes-256-cbc',
insecure_mode: true
2021-06-08 01:23:25 +05:30
private_class_method def self.encryption_options_base_32_aes_256_gcm
2019-12-04 20:38:33 +05:30
{
mode: :per_attribute_iv,
2021-06-08 01:23:25 +05:30
key: Settings.attr_encrypted_db_key_base_32,
2019-12-04 20:38:33 +05:30
algorithm: 'aes-256-gcm',
encode: true
}
end
2019-07-07 11:18:12 +05:30
2021-06-08 01:23:25 +05:30
attr_encrypted :external_auth_client_key, encryption_options_base_32_aes_256_gcm
attr_encrypted :external_auth_client_key_pass, encryption_options_base_32_aes_256_gcm
attr_encrypted :lets_encrypt_private_key, encryption_options_base_32_aes_256_gcm
attr_encrypted :eks_secret_access_key, encryption_options_base_32_aes_256_gcm
attr_encrypted :akismet_api_key, encryption_options_base_32_aes_256_gcm
attr_encrypted :spam_check_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false)
attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_32_aes_256_gcm
attr_encrypted :elasticsearch_password, encryption_options_base_32_aes_256_gcm.merge(encode: false)
attr_encrypted :recaptcha_private_key, encryption_options_base_32_aes_256_gcm
attr_encrypted :recaptcha_site_key, encryption_options_base_32_aes_256_gcm
attr_encrypted :slack_app_secret, encryption_options_base_32_aes_256_gcm
2022-07-16 23:28:13 +05:30
attr_encrypted :slack_app_signing_secret, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false)
2021-06-08 01:23:25 +05:30
attr_encrypted :slack_app_verification_token, encryption_options_base_32_aes_256_gcm
attr_encrypted :ci_jwt_signing_key, encryption_options_base_32_aes_256_gcm
2021-10-27 15:23:28 +05:30
attr_encrypted :customers_dot_jwt_signing_key, encryption_options_base_32_aes_256_gcm
2021-06-08 01:23:25 +05:30
attr_encrypted :secret_detection_token_revocation_token, encryption_options_base_32_aes_256_gcm
attr_encrypted :cloud_license_auth_token, encryption_options_base_32_aes_256_gcm
attr_encrypted :external_pipeline_validation_service_token, encryption_options_base_32_aes_256_gcm
2021-09-30 23:02:18 +05:30
attr_encrypted :mailgun_signing_key, encryption_options_base_32_aes_256_gcm.merge(encode: false)
2022-06-21 17:19:12 +05:30
attr_encrypted :database_grafana_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false)
attr_encrypted :arkose_labs_public_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false)
attr_encrypted :arkose_labs_private_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false)
2022-10-11 01:57:18 +05:30
attr_encrypted :cube_api_key, encryption_options_base_32_aes_256_gcm
2022-11-25 23:54:43 +05:30
attr_encrypted :jitsu_administrator_password, encryption_options_base_32_aes_256_gcm
2023-01-13 00:05:48 +05:30
attr_encrypted :telesign_customer_xid, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false)
attr_encrypted :telesign_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false)
2019-09-04 21:01:54 +05:30
2021-02-22 17:27:13 +05:30
validates :disable_feed_token,
2022-11-25 23:54:43 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2021-02-22 17:27:13 +05:30
2023-01-13 00:05:48 +05:30
validates :disable_admin_oauth_scopes,
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2023-03-04 22:38:38 +05:30
validates :bulk_import_enabled,
allow_nil: false,
2023-03-17 16:20:25 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
validates :allow_runner_registration_token,
allow_nil: false,
2023-03-04 22:38:38 +05:30
inclusion: { in: [true, false], message: N_('must be a boolean value') }
2017-08-17 22:00:37 +05:30
before_validation :ensure_uuid!
2021-04-17 20:07:23 +05:30
before_validation :coerce_repository_storages_weighted, if: :repository_storages_weighted_changed?
2021-11-11 11:23:49 +05:30
before_validation :normalize_default_branch_name
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
2022-08-13 15:12:31 +05:30
before_save :ensure_error_tracking_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') }
2022-07-16 23:28:13 +05:30
after_commit :reset_deletion_warning_redis_key, if: :saved_change_to_inactive_projects_delete_after_months?
2017-08-17 22:00:37 +05:30
2020-03-07 23:17:34 +05:30
def validate_grafana_url
2021-02-22 17:27:13 +05:30
validate_url(parsed_grafana_url, :grafana_url, GRAFANA_URL_ERROR_MESSAGE)
2020-03-07 23:17:34 +05:30
end
def grafana_url_absolute?
parsed_grafana_url&.absolute?
end
2021-02-22 17:27:13 +05:30
def validate_kroki_url
validate_url(parsed_kroki_url, :kroki_url, KROKI_URL_ERROR_MESSAGE)
end
def kroki_url_absolute?
parsed_kroki_url&.absolute?
end
2019-12-26 22:10:19 +05:30
def sourcegraph_url_is_com?
2021-09-30 23:02:18 +05:30
!!(sourcegraph_url =~ %r{\Ahttps://(www\.)?sourcegraph\.com})
2019-12-26 22:10:19 +05:30
end
2021-11-11 11:23:49 +05:30
def normalize_default_branch_name
self.default_branch_name = default_branch_name.presence
2021-10-27 15:23:28 +05:30
end
2021-01-03 14:25:43 +05:30
def instance_review_permitted?
users_count = Rails.cache.fetch('limited_users_count', expires_in: 1.day) do
::User.limit(INSTANCE_REVIEW_MIN_USERS + 1).count(:all)
end
users_count >= INSTANCE_REVIEW_MIN_USERS
end
2022-05-07 20:08:51 +05:30
Recursion = Class.new(RuntimeError)
2017-08-17 22:00:37 +05:30
def self.create_from_defaults
2022-05-07 20:08:51 +05:30
# this is posssible if calls to create the record depend on application
# settings themselves. This was seen in the case of a feature flag called by
# `transaction` that ended up requiring application settings to determine metrics behavior.
# If something like that happens, we break the loop here, and let the caller decide how to manage it.
raise Recursion if Thread.current[:application_setting_create_from_defaults]
Thread.current[:application_setting_create_from_defaults] = true
2020-10-04 03:57:07 +05:30
check_schema!
2021-11-11 11:23:49 +05:30
transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
2019-07-31 22:56:46 +05:30
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
2022-05-07 20:08:51 +05:30
ensure
Thread.current[:application_setting_create_from_defaults] = nil
2018-11-08 19:23:39 +05:30
end
2019-09-04 21:01:54 +05:30
2021-03-11 19:13:27 +05:30
def self.find_or_create_without_cache
current_without_cache || create_from_defaults
end
2020-10-04 03:57:07 +05:30
# Due to the frequency with which settings are accessed, it is
# likely that during a backup restore a running GitLab process
# will insert a new `application_settings` row before the
# constraints have been added to the table. This would add an
# extra row with ID 1 and prevent the primary key constraint from
# being added, which made ActiveRecord throw a
# IrreversibleOrderError anytime the settings were accessed
# (https://gitlab.com/gitlab-org/gitlab/-/issues/36405). To
# prevent this from happening, we do a sanity check that the
# primary key constraint is present before inserting a new entry.
def self.check_schema!
2021-10-27 15:23:28 +05:30
return if connection.primary_key(self.table_name).present?
2020-10-04 03:57:07 +05:30
raise "The `#{self.table_name}` table is missing a primary key constraint in the database schema"
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
2020-05-24 23:13:21 +05:30
Gitlab::ProcessMemoryCache.cache_backend
2019-09-30 21:07:59 +05:30
end
2019-09-04 21:01:54 +05:30
def recaptcha_or_login_protection_enabled
recaptcha_enabled || login_recaptcha_protection_enabled
end
2020-03-07 23:17:34 +05:30
2021-03-11 19:13:27 +05:30
kroki_formats_attributes.keys.each do |key|
define_method :"kroki_formats_#{key}=" do |value|
super(::Gitlab::Utils.to_boolean(value))
end
end
def kroki_format_supported?(diagram_type)
case diagram_type
when 'excalidraw'
return kroki_formats_excalidraw
when 'bpmn'
return kroki_formats_bpmn
end
return kroki_formats_blockdiag if ::Gitlab::Kroki::BLOCKDIAG_FORMATS.include?(diagram_type)
::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES.include?(diagram_type)
end
2023-03-04 22:38:38 +05:30
def personal_access_tokens_disabled?
false
end
2020-03-07 23:17:34 +05:30
private
def parsed_grafana_url
@parsed_grafana_url ||= Gitlab::Utils.parse_url(grafana_url)
end
2021-02-22 17:27:13 +05:30
def parsed_kroki_url
@parsed_kroki_url ||= Gitlab::UrlBlocker.validate!(kroki_url, schemes: %w(http https), enforce_sanitization: true)[0]
2022-08-27 11:52:29 +05:30
rescue Gitlab::UrlBlocker::BlockedUrlError => e
2021-02-22 17:27:13 +05:30
self.errors.add(
:kroki_url,
2022-08-27 11:52:29 +05:30
"is not valid. #{e}"
2021-02-22 17:27:13 +05:30
)
end
def validate_url(parsed_url, name, error_message)
unless parsed_url
self.errors.add(
name,
"must be a valid relative or absolute URL. #{error_message}"
)
end
end
2022-07-16 23:28:13 +05:30
def reset_deletion_warning_redis_key
Gitlab::InactiveProjectsDeletionWarningTracker.reset_all
end
2015-04-26 12:48:37 +05:30
end
2019-12-04 20:38:33 +05:30
2021-06-08 01:23:25 +05:30
ApplicationSetting.prepend_mod_with('ApplicationSetting')