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=, #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?, #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!, sharding_keys, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order

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.



1160
1161
1162
# File 'app/models/application_setting.rb', line 1160

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.



1150
1151
1152
1153
1154
# File 'app/models/application_setting.rb', line 1150

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

.create_from_defaultsObject



1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
# File 'app/models/application_setting.rb', line 1115

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



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

def self.find_or_create_without_cache
  current_without_cache || create_from_defaults
end

.human_attribute_name(attribute, *options) ⇒ Object



1164
1165
1166
# File 'app/models/application_setting.rb', line 1164

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
# 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'
    }
  }
end

.rate_limits_definitionObject

overriden in EE



1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
# File 'app/models/application_setting.rb', line 1169

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: 60 }],
    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 }]
  }
end

Instance Method Details

#allow_user_remember_me?Boolean

Returns:

  • (Boolean)


1254
1255
1256
1257
1258
# File 'app/models/application_setting.rb', line 1254

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



1249
1250
1251
1252
# File 'app/models/application_setting.rb', line 1249

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)


1268
1269
1270
# File 'app/models/application_setting.rb', line 1268

def custom_default_search_scope_set?
  ::Gitlab::Search::AbuseDetection::ALLOWED_SCOPES.include?(default_search_scope)
end

#default_branch_protected?Boolean

Returns:

  • (Boolean)


1101
1102
1103
# File 'app/models/application_setting.rb', line 1101

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)


1245
1246
1247
# File 'app/models/application_setting.rb', line 1245

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

#grafana_url_absolute?Boolean

Returns:

  • (Boolean)


1085
1086
1087
# File 'app/models/application_setting.rb', line 1085

def grafana_url_absolute?
  parsed_grafana_url&.absolute?
end

#instance_review_permitted?Boolean

Returns:

  • (Boolean)


1105
1106
1107
1108
1109
1110
1111
# File 'app/models/application_setting.rb', line 1105

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)


1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
# File 'app/models/application_setting.rb', line 1224

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

#max_login_attempts_column_exists?Boolean

Returns:

  • (Boolean)


1241
1242
1243
# File 'app/models/application_setting.rb', line 1241

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

#normalize_default_branch_nameObject



1097
1098
1099
# File 'app/models/application_setting.rb', line 1097

def normalize_default_branch_name
  self.default_branch_name = default_branch_name.presence
end

#personal_access_tokens_disabled?Boolean

Returns:

  • (Boolean)


1237
1238
1239
# File 'app/models/application_setting.rb', line 1237

def personal_access_tokens_disabled?
  false
end

#push_ruleObject



1260
1261
1262
1263
1264
1265
1266
# File 'app/models/application_setting.rb', line 1260

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

#recaptcha_or_login_protection_enabledObject



1214
1215
1216
# File 'app/models/application_setting.rb', line 1214

def 
  recaptcha_enabled || 
end

#sourcegraph_url_is_com?Boolean

Returns:

  • (Boolean)


1093
1094
1095
# File 'app/models/application_setting.rb', line 1093

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

#validate_grafana_urlObject



1081
1082
1083
# File 'app/models/application_setting.rb', line 1081

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

#validate_kroki_urlObject



1089
1090
1091
# File 'app/models/application_setting.rb', line 1089

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

#validate_object_storage_for_live_trace_configurationObject



1074
1075
1076
1077
1078
1079
# File 'app/models/application_setting.rb', line 1074

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