Class: ApplicationSetting

Inherits:
ApplicationRecord show all
Includes:
ApplicationSettingImplementation, CacheMarkdownField, CacheableAttributes, ChronicDurationAttribute, Gitlab::EncryptedAttribute, IgnorableColumns, Sanitizable, TokenAuthenticatable
Defined in:
app/models/application_setting.rb,
app/models/application_setting/term.rb,
app/policies/application_setting/term_policy.rb

Defined Under Namespace

Classes: Term, TermPolicy

Constant Summary collapse

INSTANCE_REVIEW_MIN_USERS =
50
GRAFANA_URL_ERROR_MESSAGE =
'Please check your Grafana URL setting in ' \
'Admin area > Settings > Metrics and profiling > Metrics - Grafana'
KROKI_URL_ERROR_MESSAGE =
'Please check your Kroki URL setting in ' \
'Admin area > Settings > General > Kroki'
ADDRESSABLE_URL_VALIDATION_OPTIONS =

Validate URIs in this model according to the current value of the deny_all_requests_except_allowed property, rather than the persisted value.

{
  deny_all_requests_except_allowed: ->(settings) do
    settings.deny_all_requests_except_allowed
  end
}.freeze
HUMANIZED_ATTRIBUTES =
{
  archive_builds_in_seconds: 'Archive job value'
}.freeze
DEFAULT_BRANCH_PROTECTIONS_DEFAULT_MAX_SIZE =

matches the size set in the database constraint

1.kilobyte
USERS_UNCONFIRMED_SECONDARY_EMAILS_DELETE_AFTER_DAYS =
3
DEFAULT_HELM_MAX_PACKAGES_COUNT =
1000
DEFAULT_AUTHENTICATED_GIT_HTTP_LIMIT =
3600
DEFAULT_AUTHENTICATED_GIT_HTTP_PERIOD =
3600
SEARCH_SCOPE_SYSTEM_DEFAULT =
'system default'
Recursion =
Class.new(RuntimeError)

Constants included from ApplicationSettingImplementation

ApplicationSettingImplementation::DEFAULT_MINIMUM_PASSWORD_LENGTH, ApplicationSettingImplementation::DEFAULT_NUMBER_OF_DAYS_BEFORE_REMOVAL, ApplicationSettingImplementation::DEFAULT_PROTECTED_PATHS, ApplicationSettingImplementation::FORBIDDEN_KEY_VALUE, ApplicationSettingImplementation::STRING_LIST_SEPARATOR, ApplicationSettingImplementation::VALID_RUNNER_REGISTRAR_TYPES

Constants included from CacheMarkdownField

CacheMarkdownField::INVALIDATED_BY

Constants inherited from ApplicationRecord

ApplicationRecord::MAX_PLUCK

Constants included from HasCheckConstraints

HasCheckConstraints::NOT_NULL_CHECK_PATTERN

Constants included from ResetOnColumnErrors

ResetOnColumnErrors::MAX_RESET_PERIOD

Instance Attribute Summary

Attributes included from CacheMarkdownField

#skip_markdown_cache_validation

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ApplicationSettingImplementation

#add_to_outbound_local_requests_whitelist, #allow_immediate_namespaces_deletion_for_user?, #allow_signup?, #allowed_key_types, #archive_builds_older_than, #asset_proxy_allowlist, #asset_proxy_whitelist=, #coerce_iframe_rendering_allowlist, #commit_email_hostname, #default_group_visibility=, #default_project_visibility=, #default_snippet_visibility=, #disabled_oauth_sign_in_sources=, #domain_allowlist_raw, #domain_allowlist_raw=, #domain_denylist_file=, #domain_denylist_raw, #domain_denylist_raw=, #ensure_key_restrictions!, #error_tracking_access_token, #health_check_access_token, #help_page_support_url_column_exists?, #home_page_url_column_exists?, #iframe_rendering_allowlist_raw, #iframe_rendering_allowlist_raw=, #key_restriction_for, #latest_terms, #normalized_repository_storage_weights, #notes_create_limit_allowlist_raw, #notes_create_limit_allowlist_raw=, #outbound_local_requests_allowlist_arrays, #outbound_local_requests_allowlist_raw, #outbound_local_requests_allowlist_raw=, #password_authentication_enabled?, #performance_bar_allowed_group, #performance_bar_enabled, #pick_repository_storage, #protected_paths_for_get_request_raw, #protected_paths_for_get_request_raw=, #protected_paths_raw, #protected_paths_raw=, #repository_storages_with_default_weight, #reset_memoized_terms, #restricted_visibility_levels=, #runners_registration_token, #search_rate_limit_allowlist_raw, #search_rate_limit_allowlist_raw=, #static_objects_external_storage_auth_token=, #static_objects_external_storage_enabled?, #usage_ping_can_be_configured?, #usage_ping_enabled, #usage_ping_features_enabled, #usage_ping_generation_enabled, #user_default_internal_regex_enabled?, #user_default_internal_regex_instance, #users_get_by_id_limit_allowlist_raw, #users_get_by_id_limit_allowlist_raw=

Methods included from ChronicDurationAttribute

#chronic_duration_attributes, #output_chronic_duration_attribute

Methods included from CacheMarkdownField

#attribute_invalidated?, #banzai_render_context, #cached_html_for, #cached_html_up_to_date?, #can_cache_field?, #invalidated_markdown_cache?, #latest_cached_markdown_version, #mentionable_attributes_changed?, #mentioned_filtered_user_ids_for, #parent_user, #refresh_markdown_cache, #refresh_markdown_cache!, #rendered_field_content, #skip_project_check?, #store_mentions!, #store_mentions?, #store_mentions_after_commit?, #updated_cached_html_for

Methods included from CacheableAttributes

#cache!

Methods inherited from ApplicationRecord

===, cached_column_list, #create_or_load_association, current_transaction, declarative_enum, default_select_columns, delete_all_returning, #deleted_from_database?, id_in, id_not_in, iid_in, nullable_column?, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order

Methods included from Organizations::Sharding

#sharding_organization

Methods included from ResetOnColumnErrors

#reset_on_union_error, #reset_on_unknown_attribute_error

Methods included from Gitlab::SensitiveSerializableHash

#serializable_hash

Class Method Details

.cache_backendObject

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.



1208
1209
1210
# File 'app/models/application_setting.rb', line 1208

def self.cache_backend
  Gitlab::ProcessMemoryCache.cache_backend
end

.check_schema!Object

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 (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.



1198
1199
1200
1201
1202
# File 'app/models/application_setting.rb', line 1198

def self.check_schema!
  return if connection.primary_key(table_name).present?

  raise "The `#{table_name}` table is missing a primary key constraint in the database schema"
end

.ci_cd_settings_definitionObject



528
529
530
531
532
533
534
535
536
# File 'app/models/application_setting.rb', line 528

def self.ci_cd_settings_definition
  {
    pipeline_variables_default_allowed: [:boolean, { default: true }],
    ci_job_live_trace_enabled: [:boolean, { default: false }],
    ci_partitions_size_limit: [::Gitlab::Database::Type::JsonbInteger.new, { default: 100.gigabytes }],
    ci_delete_pipelines_in_seconds_limit: [:integer, { default: ChronicDuration.parse('1 year') }],
    git_push_pipeline_limit: [:integer, { default: 4 }]
  }
end

.create_from_defaultsObject



1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
# File 'app/models/application_setting.rb', line 1163

def self.create_from_defaults
  # this is possible 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

  check_schema!

  transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
    super
  end
rescue ActiveRecord::RecordNotUnique
  # We already have an ApplicationSetting record, so just return it.
  current_without_cache
ensure
  Thread.current[:application_setting_create_from_defaults] = nil
end

.find_or_create_without_cacheObject



1184
1185
1186
# File 'app/models/application_setting.rb', line 1184

def self.find_or_create_without_cache
  current_without_cache || create_from_defaults
end

.human_attribute_name(attribute, *options) ⇒ Object



1212
1213
1214
# File 'app/models/application_setting.rb', line 1212

def self.human_attribute_name(attribute, *options)
  HUMANIZED_ATTRIBUTES[attribute.to_sym] || super
end

.kroki_formats_attributesObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'app/models/application_setting.rb', line 64

def self.kroki_formats_attributes
  {
    blockdiag: {
      label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, and RackDiag)'
    },
    bpmn: {
      label: 'BPMN'
    },
    excalidraw: {
      label: 'Excalidraw'
    },
    mermaid: {
      label: 'Mermaid'
    }
  }
end

.rate_limits_definitionObject

overriden in EE



1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
# File 'app/models/application_setting.rb', line 1217

def self.rate_limits_definition
  {
    autocomplete_users_limit: [:integer, { default: 300 }],
    autocomplete_users_unauthenticated_limit: [:integer, { default: 100 }],
    concurrent_bitbucket_import_jobs_limit: [:integer, { default: 100 }],
    concurrent_bitbucket_server_import_jobs_limit: [:integer, { default: 100 }],
    concurrent_github_import_jobs_limit: [:integer, { default: 1000 }],
    concurrent_relation_batch_export_limit: [:integer, { default: 8 }],
    downstream_pipeline_trigger_limit_per_project_user_sha: [:integer, { default: 0 }],
    group_api_limit: [:integer, { default: 400 }],
    group_invited_groups_api_limit: [:integer, { default: 60 }],
    group_projects_api_limit: [:integer, { default: 600 }],
    group_shared_groups_api_limit: [:integer, { default: 60 }],
    groups_api_limit: [:integer, { default: 200 }],
    members_delete_limit: [:integer, { default: 60 }],
    create_organization_api_limit: [:integer, { default: 10 }],
    project_api_limit: [:integer, { default: 400 }],
    group_archive_unarchive_api_limit: [:integer, { default: 60 }],
    project_invited_groups_api_limit: [:integer, { default: 60 }],
    projects_api_limit: [:integer, { default: 2000 }],
    project_members_api_limit: [:integer, { default: 200 }],
    runner_jobs_request_api_limit: [:integer, { default: 2000 }],
    runner_jobs_patch_trace_api_limit: [:integer, { default: 200 }],
    runner_jobs_endpoints_api_limit: [:integer, { default: 200 }],
    throttle_authenticated_git_http_enabled: [:boolean, { default: false }],
    throttle_authenticated_git_http_requests_per_period:
      [:integer, { default: DEFAULT_AUTHENTICATED_GIT_HTTP_LIMIT }],
    throttle_authenticated_git_http_period_in_seconds:
      [:integer, { default: DEFAULT_AUTHENTICATED_GIT_HTTP_PERIOD }],
    user_contributed_projects_api_limit: [:integer, { default: 100 }],
    user_projects_api_limit: [:integer, { default: 300 }],
    user_starred_projects_api_limit: [:integer, { default: 100 }],
    users_api_limit_followers: [:integer, { default: 100 }],
    users_api_limit_following: [:integer, { default: 100 }],
    users_api_limit_status: [:integer, { default: 240 }],
    users_api_limit_ssh_keys: [:integer, { default: 120 }],
    users_api_limit_ssh_key: [:integer, { default: 120 }],
    users_api_limit_gpg_keys: [:integer, { default: 120 }],
    users_api_limit_gpg_key: [:integer, { default: 120 }],
    pipeline_limit_per_user: [:integer, { default: 0 }]
  }
end

Instance Method Details

#allow_user_remember_me?Boolean

Returns:

  • (Boolean)


1305
1306
1307
1308
1309
# File 'app/models/application_setting.rb', line 1305

def allow_user_remember_me?
  return false if session_expire_from_init?

  remember_me_enabled?
end

#ci_delete_pipelines_in_seconds_limit_human_readable_longObject



1300
1301
1302
1303
# File 'app/models/application_setting.rb', line 1300

def ci_delete_pipelines_in_seconds_limit_human_readable_long
  value = ci_delete_pipelines_in_seconds_limit
  ChronicDuration.output(value, format: :long) if value
end

#custom_default_search_scope_set?Boolean

Returns:

  • (Boolean)


1319
1320
1321
# File 'app/models/application_setting.rb', line 1319

def custom_default_search_scope_set?
  ::Search::Scopes.all_scope_names.include?(default_search_scope)
end

#default_branch_protected?Boolean

Returns:

  • (Boolean)


1149
1150
1151
# File 'app/models/application_setting.rb', line 1149

def default_branch_protected?
  Gitlab::Access::DefaultBranchProtection.new(default_branch_protection_defaults).any?
end

#failed_login_attempts_unlock_period_in_minutes_column_exists?Boolean

Returns:

  • (Boolean)


1296
1297
1298
# File 'app/models/application_setting.rb', line 1296

def 
  self.class.database.cached_column_exists?(:failed_login_attempts_unlock_period_in_minutes)
end

#grafana_url_absolute?Boolean

Returns:

  • (Boolean)


1133
1134
1135
# File 'app/models/application_setting.rb', line 1133

def grafana_url_absolute?
  parsed_grafana_url&.absolute?
end

#instance_review_permitted?Boolean

Returns:

  • (Boolean)


1153
1154
1155
1156
1157
1158
1159
# File 'app/models/application_setting.rb', line 1153

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

#kroki_format_supported?(diagram_type) ⇒ Boolean

Returns:

  • (Boolean)


1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
# File 'app/models/application_setting.rb', line 1273

def kroki_format_supported?(diagram_type)
  case diagram_type
  when 'excalidraw'
    return kroki_formats_excalidraw
  when 'bpmn'
    return kroki_formats_bpmn
  when 'mermaid'
    return kroki_formats_mermaid
  end

  return kroki_formats_blockdiag if ::Gitlab::Kroki::BLOCKDIAG_FORMATS.include?(diagram_type)

  ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES.include?(diagram_type)
end

#max_login_attempts_column_exists?Boolean

Returns:

  • (Boolean)


1292
1293
1294
# File 'app/models/application_setting.rb', line 1292

def 
  self.class.database.cached_column_exists?(:max_login_attempts)
end

#normalize_default_branch_nameObject



1145
1146
1147
# File 'app/models/application_setting.rb', line 1145

def normalize_default_branch_name
  self.default_branch_name = default_branch_name.presence
end

#personal_access_tokens_disabled?Boolean

Returns:

  • (Boolean)


1288
1289
1290
# File 'app/models/application_setting.rb', line 1288

def personal_access_tokens_disabled?
  false
end

#push_ruleObject



1311
1312
1313
1314
1315
1316
1317
# File 'app/models/application_setting.rb', line 1311

def push_rule
  if Feature.enabled?(:update_organization_push_rules, Feature.current_request)
    nil
  else
    super
  end
end

#recaptcha_or_login_protection_enabledObject



1263
1264
1265
# File 'app/models/application_setting.rb', line 1263

def 
  recaptcha_enabled || 
end

#sourcegraph_url_is_com?Boolean

Returns:

  • (Boolean)


1141
1142
1143
# File 'app/models/application_setting.rb', line 1141

def sourcegraph_url_is_com?
  !!(sourcegraph_url =~ %r{\Ahttps://(www\.)?sourcegraph\.com})
end

#validate_grafana_urlObject



1129
1130
1131
# File 'app/models/application_setting.rb', line 1129

def validate_grafana_url
  validate_url(parsed_grafana_url, :grafana_url, GRAFANA_URL_ERROR_MESSAGE)
end

#validate_kroki_urlObject



1137
1138
1139
# File 'app/models/application_setting.rb', line 1137

def validate_kroki_url
  validate_url(parsed_kroki_url, :kroki_url, KROKI_URL_ERROR_MESSAGE)
end

#validate_object_storage_for_live_trace_configurationObject



1122
1123
1124
1125
1126
1127
# File 'app/models/application_setting.rb', line 1122

def validate_object_storage_for_live_trace_configuration
  return if Gitlab.config.artifacts.object_store.enabled

  errors.add(:ci_job_live_trace_enabled,
    'Incremental logging cannot be turned on without configuring object storage for artifacts.')
end