app/helpers/application_settings_helper.rb (682 lines of code) (raw):

# frozen_string_literal: true module ApplicationSettingsHelper extend self delegate :allow_signup?, :gravatar_enabled?, :password_authentication_enabled_for_web?, :akismet_enabled?, :spam_check_endpoint_enabled?, :require_personal_access_token_expiry?, to: :'Gitlab::CurrentSettings.current_application_settings' def user_oauth_applications? Gitlab::CurrentSettings.user_oauth_applications end def allowed_protocols_present? Gitlab::CurrentSettings.enabled_git_access_protocol.present? end def enabled_protocol case Gitlab::CurrentSettings.enabled_git_access_protocol when 'http' Gitlab.config.gitlab.protocol when 'ssh' 'ssh' end end def kroki_available_formats ApplicationSetting.kroki_formats_attributes.map do |key, value| { name: "kroki_formats_#{key}", label: value[:label], value: @application_setting.kroki_formats[key] || false } end end def storage_weights # Instead of using a `Struct` we could wrap this into an object. # See https://gitlab.com/gitlab-org/gitlab/-/issues/358419 storages_weighted = @application_setting.repository_storages_with_default_weight weights = Struct.new(*storages_weighted.keys.map(&:to_sym)) weights.new(*storages_weighted.values) end def all_protocols_enabled? Gitlab::CurrentSettings.enabled_git_access_protocol.blank? end def ssh_enabled? all_protocols_enabled? || enabled_protocol == 'ssh' end def http_enabled? all_protocols_enabled? || Gitlab::CurrentSettings.enabled_git_access_protocol == 'http' end def anti_spam_service_enabled? akismet_enabled? || spam_check_endpoint_enabled? end def enabled_protocol_button(container, protocol) case protocol when 'ssh' ssh_clone_button(container, append_link: false) else http_clone_button(container, append_link: false) end end def global_search_settings_checkboxes(form) [ form.gitlab_ui_checkbox_component( :global_search_block_anonymous_searches_enabled, _("Restrict global search to authenticated users only"), checkbox_options: { checked: @application_setting.global_search_block_anonymous_searches_enabled, multiple: false } ), form.gitlab_ui_checkbox_component( :global_search_issues_enabled, _("Show issues in global search results"), checkbox_options: { checked: @application_setting.global_search_issues_enabled, multiple: false } ), form.gitlab_ui_checkbox_component( :global_search_merge_requests_enabled, _("Show merge requests in global search results"), checkbox_options: { checked: @application_setting.global_search_merge_requests_enabled, multiple: false } ), form.gitlab_ui_checkbox_component( :global_search_snippet_titles_enabled, _("Show snippets in global search results"), checkbox_options: { checked: @application_setting.global_search_snippet_titles_enabled, multiple: false } ), form.gitlab_ui_checkbox_component( :global_search_users_enabled, _("Show users in global search results"), checkbox_options: { checked: @application_setting.global_search_users_enabled, multiple: false } ) ] end def restricted_level_checkboxes(form) restricted_visibility_levels_help_text = { Gitlab::VisibilityLevel::PUBLIC => s_( 'AdminSettings|If selected, only administrators are able to create public groups, projects, ' \ 'and snippets. Also, profiles are only visible to authenticated users.' ), Gitlab::VisibilityLevel::INTERNAL => s_( 'AdminSettings|If selected, only administrators are able to create internal groups, projects, and ' \ 'snippets.' ), Gitlab::VisibilityLevel::PRIVATE => s_( 'AdminSettings|If selected, only administrators are able to create private groups, projects, and ' \ 'snippets.' ) } Gitlab::VisibilityLevel.options.map do |label, level| checked = restricted_visibility_levels(true).include?(level) form.gitlab_ui_checkbox_component( :restricted_visibility_levels, checkbox_options: { checked: checked, multiple: true, autocomplete: 'off' }, checked_value: level, unchecked_value: nil ) do |c| c.with_label do visibility_level_icon(level) + content_tag(:span, label, { class: 'gl-ml-2' }) end c.with_help_text do restricted_visibility_levels_help_text.fetch(level) end end end end def import_sources_checkboxes(form) Gitlab::ImportSources.options.map do |name, source| checked = @application_setting.import_sources.include?(source) form.gitlab_ui_checkbox_component( :import_sources, name, checkbox_options: { checked: checked, multiple: true, autocomplete: 'off' }, checked_value: source, unchecked_value: nil ) end end def oauth_providers_checkboxes(form) button_based_providers.map do |source| checked = @application_setting.disabled_oauth_sign_in_sources.exclude?(source.to_s) name = Gitlab::Auth::OAuth::Provider.label_for(source) form.gitlab_ui_checkbox_component( :enabled_oauth_sign_in_sources, name, checkbox_options: { checked: checked, multiple: true, autocomplete: 'off' }, checked_value: source, unchecked_value: nil ) end end def key_restriction_options_for_select(type) bit_size_options = Gitlab::SSHPublicKey.supported_sizes(type).map do |bits| ["Must be at least #{bits} bits", bits] end [ ['Are allowed', 0], *bit_size_options, ['Are forbidden', ApplicationSetting::FORBIDDEN_KEY_VALUE] ] end def repository_storages_options_json options = Gitlab.config.repositories.storages.map do |name, storage| { label: "#{name} - #{storage['gitaly_address']}", value: name } end options.to_json end def external_authorization_description s_("ExternalAuthorization|Access to projects is validated on an external service " \ "using their classification label.") end def external_authorization_allow_token_help_text s_("ExternalAuthorization|Does not apply if service URL is specified.") end def external_authorization_timeout_help_text s_("ExternalAuthorization|Period GitLab waits for a response from the external " \ "service. If there is no response, access is denied. Default: 0.5 seconds.") end def external_authorization_url_help_text s_("ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project " \ "features are available and can still specify classification " \ "labels for projects.") end def external_authorization_client_certificate_help_text s_("ExternalAuthorization|Certificate used to authenticate with the external authorization service. " \ "If blank, the server certificate is validated when accessing over HTTPS.") end def external_authorization_client_key_help_text s_("ExternalAuthorization|Private key of client authentication certificate. " \ "Encrypted when stored.") end def external_authorization_client_pass_help_text s_("ExternalAuthorization|Passphrase required to decrypt the private key. " \ "Encrypted when stored.") end def external_authorization_client_url_help_text s_("ExternalAuthorization|Classification label to use when requesting authorization if no specific " \ "label is defined on the project.") end def sidekiq_job_limiter_mode_help_text _("How the job limiter handles jobs exceeding the thresholds specified below. " \ "The 'track' mode only logs the jobs. The 'compress' mode compresses the jobs and " \ "raises an exception if the compressed size exceeds the limit.") end def sidekiq_job_limiter_modes_for_select ApplicationSetting.sidekiq_job_limiter_modes.keys.map { |mode| [mode.humanize, mode] } end def visible_attributes [ :abuse_notification_email, :admin_mode, :after_sign_out_path, :after_sign_up_text, :akismet_api_key, :akismet_enabled, :allow_local_requests_from_hooks_and_services, :allow_local_requests_from_web_hooks_and_services, :allow_local_requests_from_system_hooks, :allow_possible_spam, :dns_rebinding_protection_enabled, :archive_builds_in_human_readable, :asset_proxy_enabled, :asset_proxy_secret_key, :asset_proxy_url, :asset_proxy_allowlist, :static_objects_external_storage_auth_token, :static_objects_external_storage_url, :authorized_keys_enabled, :auto_devops_enabled, :auto_devops_domain, :autocomplete_users_limit, :autocomplete_users_unauthenticated_limit, :allow_bypass_placeholder_confirmation, :ci_delete_pipelines_in_seconds_limit_human_readable, :ci_job_live_trace_enabled, :ci_partitions_size_limit, :concurrent_github_import_jobs_limit, :concurrent_bitbucket_import_jobs_limit, :concurrent_bitbucket_server_import_jobs_limit, :container_expiration_policies_enable_historic_entries, :container_registry_expiration_policies_caching, :container_registry_token_expire_delay, :decompress_archive_file_timeout, :default_artifacts_expire_in, :default_branch_name, :default_branch_protection, :default_branch_protection_defaults, :default_ci_config_path, :default_group_visibility, :default_preferred_language, :default_project_creation, :default_project_visibility, :default_projects_limit, :default_snippet_visibility, :default_syntax_highlighting_theme, :delete_inactive_projects, :deletion_adjourned_period, :deny_all_requests_except_allowed, :disable_admin_oauth_scopes, :disable_feed_token, :disable_password_authentication_for_users_with_sso_identities, :root_moved_permanently_redirection, :disabled_oauth_sign_in_sources, :domain_denylist, :domain_denylist_enabled, # TODO Remove domain_denylist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204) :domain_denylist_raw, :domain_allowlist, # TODO Remove domain_allowlist_raw in APIv5 (See https://gitlab.com/gitlab-org/gitlab-foss/issues/67204) :domain_allowlist_raw, :outbound_local_requests_allowlist_raw, :dsa_key_restriction, :ecdsa_key_restriction, :ecdsa_sk_key_restriction, :ed25519_key_restriction, :ed25519_sk_key_restriction, :eks_integration_enabled, :eks_account_id, :eks_access_key_id, :eks_secret_access_key, :email_author_in_body, :email_confirmation_setting, :enabled_git_access_protocol, :enforce_ci_inbound_job_token_scope_enabled, :enforce_email_subaddress_restrictions, :enforce_terms, :error_tracking_enabled, :error_tracking_api_url, :external_pipeline_validation_service_timeout, :external_pipeline_validation_service_token, :external_pipeline_validation_service_url, :failed_login_attempts_unlock_period_in_minutes, :first_day_of_week, :floc_enabled, :force_pages_access_control, :gitaly_timeout_default, :gitaly_timeout_medium, :gitaly_timeout_fast, :gitpod_enabled, :gitpod_url, :grafana_enabled, :grafana_url, :gravatar_enabled, :hashed_storage_enabled, :help_page_hide_commercial_content, :help_page_support_url, :help_page_documentation_base_url, :help_page_text, :hide_third_party_offers, :home_page_url, :housekeeping_enabled, :housekeeping_full_repack_period, :housekeeping_gc_period, :housekeeping_incremental_repack_period, :housekeeping_optimize_repository_period, :html_emails_enabled, :import_sources, :inactive_projects_delete_after_months, :inactive_projects_min_size_mb, :inactive_projects_send_warning_email_after_months, :include_optional_metrics_in_service_ping, :invisible_captcha_enabled, :jira_connect_application_key, :jira_connect_public_key_storage_enabled, :jira_connect_proxy_url, :jira_connect_additional_audience_url, :math_rendering_limits_enabled, :max_artifacts_content_include_size, :max_artifacts_size, :max_attachment_size, :max_decompressed_archive_size, :max_export_size, :max_github_response_size_limit, :max_github_response_json_value_count, :max_import_size, :max_import_remote_file_size, :max_login_attempts, :max_pages_size, :max_pages_custom_domains_per_project, :max_terraform_state_size_bytes, :max_yaml_size_bytes, :max_yaml_depth, :metrics_method_call_threshold, :minimum_password_length, :mirror_available, :notify_on_unknown_sign_in, :organization_cluster_agent_authorization_enabled, :pages_domain_verification_enabled, :password_authentication_enabled_for_web, :password_authentication_enabled_for_git, :performance_bar_allowed_group_path, :performance_bar_enabled, :personal_access_token_prefix, :instance_token_prefix, :kroki_enabled, :kroki_url, :kroki_formats, :plantuml_enabled, :plantuml_url, :diagramsnet_enabled, :diagramsnet_url, :pages_extra_deployments_default_expiry_seconds, :polling_interval_multiplier, :project_export_enabled, :prometheus_metrics_enabled, :recaptcha_enabled, :recaptcha_private_key, :recaptcha_site_key, :login_recaptcha_protection_enabled, :receive_max_input_size, :repository_checks_enabled, :repository_storages_weighted, :require_admin_approval_after_user_signup, :require_admin_two_factor_authentication, :require_two_factor_authentication, :remember_me_enabled, :restricted_visibility_levels, :rsa_key_restriction, :session_expire_delay, :session_expire_from_init, :shared_runners_enabled, :shared_runners_text, :sign_in_restrictions, :signup_enabled, :silent_mode_enabled, :slack_app_enabled, :slack_app_id, :slack_app_secret, :slack_app_signing_secret, :slack_app_verification_token, :sourcegraph_enabled, :sourcegraph_url, :sourcegraph_public_only, :spam_check_endpoint_enabled, :spam_check_endpoint_url, :spam_check_api_key, :terminal_max_session_time, :terms, :throttle_authenticated_api_enabled, :throttle_authenticated_api_period_in_seconds, :throttle_authenticated_api_requests_per_period, :throttle_authenticated_git_lfs_enabled, :throttle_authenticated_git_lfs_period_in_seconds, :throttle_authenticated_git_lfs_requests_per_period, :throttle_authenticated_web_enabled, :throttle_authenticated_web_period_in_seconds, :throttle_authenticated_web_requests_per_period, :throttle_authenticated_packages_api_enabled, :throttle_authenticated_packages_api_period_in_seconds, :throttle_authenticated_packages_api_requests_per_period, :throttle_authenticated_files_api_enabled, :throttle_authenticated_files_api_period_in_seconds, :throttle_authenticated_files_api_requests_per_period, :throttle_authenticated_deprecated_api_enabled, :throttle_authenticated_deprecated_api_period_in_seconds, :throttle_authenticated_deprecated_api_requests_per_period, :throttle_unauthenticated_api_enabled, :throttle_unauthenticated_api_period_in_seconds, :throttle_unauthenticated_api_requests_per_period, :throttle_unauthenticated_enabled, :throttle_unauthenticated_period_in_seconds, :throttle_unauthenticated_requests_per_period, :throttle_unauthenticated_packages_api_enabled, :throttle_unauthenticated_packages_api_period_in_seconds, :throttle_unauthenticated_packages_api_requests_per_period, :throttle_unauthenticated_files_api_enabled, :throttle_unauthenticated_files_api_period_in_seconds, :throttle_unauthenticated_files_api_requests_per_period, :throttle_unauthenticated_git_http_enabled, :throttle_unauthenticated_git_http_period_in_seconds, :throttle_unauthenticated_git_http_requests_per_period, :throttle_unauthenticated_deprecated_api_enabled, :throttle_unauthenticated_deprecated_api_period_in_seconds, :throttle_unauthenticated_deprecated_api_requests_per_period, :throttle_protected_paths_enabled, :throttle_protected_paths_period_in_seconds, :throttle_protected_paths_requests_per_period, :top_level_group_creation_enabled, :protected_paths_raw, :protected_paths_for_get_request_raw, :time_tracking_limit_to_hours, :two_factor_grace_period, :update_runner_versions_enabled, :unique_ips_limit_enabled, :unique_ips_limit_per_user, :unique_ips_limit_time_window, :usage_ping_enabled, :usage_ping_features_enabled, :use_clickhouse_for_analytics, :user_default_external, :user_show_add_ssh_key_message, :user_default_internal_regex, :user_oauth_applications, :version_check_enabled, :diff_max_patch_bytes, :diff_max_files, :diff_max_lines, :commit_email_hostname, :protected_ci_variables, :local_markdown_version, :mailgun_signing_key, :mailgun_events_enabled, :snowplow_collector_hostname, :snowplow_cookie_domain, :snowplow_database_collector_hostname, :snowplow_enabled, :snowplow_app_id, :gitlab_product_usage_data_enabled, :push_event_hooks_limit, :push_event_activities_limit, :custom_http_clone_url_root, :snippet_size_limit, :email_restrictions_enabled, :email_restrictions, :issues_create_limit, :notes_create_limit, :notes_create_limit_allowlist_raw, :members_delete_limit, :raw_blob_request_limit, :project_import_limit, :project_export_limit, :project_download_export_limit, :group_import_limit, :group_export_limit, :group_download_export_limit, :wiki_page_max_content_bytes, :wiki_asciidoc_allow_uri_includes, :container_registry_delete_tags_service_timeout, :rate_limiting_response_text, :package_registry_allow_anyone_to_pull_option, :package_registry_cleanup_policies_worker_capacity, :container_registry_expiration_policies_worker_capacity, :container_registry_cleanup_tags_service_max_list_size, :keep_latest_artifact, :whats_new_variant, :user_deactivation_emails_enabled, :resource_access_token_notify_inherited, :lock_resource_access_token_notify_inherited, :sentry_enabled, :sentry_dsn, :sentry_clientside_dsn, :sentry_environment, :sentry_clientside_traces_sample_rate, :sidekiq_job_limiter_mode, :sidekiq_job_limiter_compression_threshold_bytes, :sidekiq_job_limiter_limit_bytes, :suggest_pipeline_enabled, :enable_artifact_external_redirect_warning_page, :search_rate_limit, :search_rate_limit_unauthenticated, :search_rate_limit_allowlist_raw, :users_get_by_id_limit, :users_get_by_id_limit_allowlist_raw, :runner_token_expiration_interval, :group_runner_token_expiration_interval, :project_runner_token_expiration_interval, :pipeline_limit_per_project_user_sha, :invitation_flow_enforcement, :can_create_group, :can_create_organization, :bulk_import_concurrent_pipeline_batch_limit, :concurrent_relation_batch_export_limit, :bulk_import_enabled, :bulk_import_max_download_file_size, :silent_admin_exports_enabled, :allow_contribution_mapping_to_admins, :allow_runner_registration_token, :user_defaults_to_private_profile, :deactivation_email_additional_text, :projects_api_rate_limit_unauthenticated, :group_api_limit, :group_archive_unarchive_api_limit, :group_invited_groups_api_limit, :group_shared_groups_api_limit, :group_projects_api_limit, :groups_api_limit, :project_api_limit, :project_invited_groups_api_limit, :projects_api_limit, :create_organization_api_limit, :user_contributed_projects_api_limit, :user_projects_api_limit, :user_starred_projects_api_limit, :users_api_limit_followers, :users_api_limit_following, :users_api_limit_status, :users_api_limit_ssh_keys, :users_api_limit_ssh_key, :users_api_limit_gpg_keys, :users_api_limit_gpg_key, :gitlab_dedicated_instance, :gitlab_environment_toolkit_instance, :ci_max_includes, :allow_account_deletion, :gitlab_shell_operation_limit, :namespace_aggregation_schedule_lease_duration_in_seconds, :ci_max_total_yaml_size_bytes, :project_jobs_api_rate_limit, :security_txt_content, :allow_project_creation_for_guest_and_below, :downstream_pipeline_trigger_limit_per_project_user_sha, :asciidoc_max_includes, :ai_action_api_rate_limit, :code_suggestions_api_rate_limit, :require_personal_access_token_expiry, :observability_backend_ssl_verification_enabled, :show_migrate_from_jenkins_banner, :ropc_without_client_credentials, :global_search_snippet_titles_enabled, :global_search_users_enabled, :global_search_issues_enabled, :global_search_merge_requests_enabled, :global_search_block_anonymous_searches_enabled, :vscode_extension_marketplace, :vscode_extension_marketplace_enabled, :reindexing_minimum_index_size, :reindexing_minimum_relative_bloat_size, :anonymous_searches_allowed, :git_push_pipeline_limit ].tap do |settings| unless Gitlab.com? settings << :resource_usage_limits settings << :deactivate_dormant_users settings << :deactivate_dormant_users_period settings << :nuget_skip_metadata_url_validation settings << :helm_max_packages_count end end end def runner_token_expiration_interval_attributes { instance_runner_token_expiration_interval: @application_setting.runner_token_expiration_interval, group_runner_token_expiration_interval: @application_setting.group_runner_token_expiration_interval, project_runner_token_expiration_interval: @application_setting.project_runner_token_expiration_interval } end def external_authorization_service_attributes [ :external_auth_client_cert, :external_auth_client_key, :external_auth_client_key_pass, :external_authorization_service_default_label, :external_authorization_service_enabled, :external_authorization_service_timeout, :external_authorization_service_url, :allow_deploy_tokens_and_keys_with_external_authn ] end # ok to remove in REST API v5 def deprecated_attributes [ :admin_notification_email, :asset_proxy_whitelist ] end def expanded_by_default? Rails.env.test? end def integration_expanded?(substring) @application_setting.errors.messages.any? { |k, _| k.to_s.start_with?(substring) } end def instance_clusters_enabled? clusterable = Clusters::Instance.new clusterable.certificate_based_clusters_enabled? && can?(current_user, :read_cluster, clusterable) end def valid_runner_registrars Gitlab::CurrentSettings.valid_runner_registrars end def signup_enabled? !!Gitlab::CurrentSettings.signup_enabled end def pending_user_count User.blocked_pending_approval.count end def registration_features_can_be_prompted? !Gitlab::CurrentSettings.usage_ping_enabled? end def signup_form_data { host: new_user_registration_url(host: Gitlab.config.gitlab.host), settings_path: general_admin_application_settings_path(anchor: 'js-signup-settings'), signup_enabled: @application_setting[:signup_enabled].to_s, require_admin_approval_after_user_signup: @application_setting[:require_admin_approval_after_user_signup].to_s, email_confirmation_setting: @application_setting[:email_confirmation_setting].to_s, minimum_password_length: @application_setting[:minimum_password_length], minimum_password_length_min: ApplicationSetting::DEFAULT_MINIMUM_PASSWORD_LENGTH, minimum_password_length_max: Devise.password_length.max, minimum_password_length_help_link: 'https://about.gitlab.com/handbook/security/#gitlab-password-policy-guidelines', domain_allowlist_raw: @application_setting.domain_allowlist_raw, new_user_signups_cap: @application_setting[:new_user_signups_cap].to_s, domain_denylist_enabled: @application_setting[:domain_denylist_enabled].to_s, denylist_type_raw_selected: (@application_setting.domain_denylist.present? || @application_setting.domain_denylist.blank?).to_s, domain_denylist_raw: @application_setting.domain_denylist_raw, email_restrictions_enabled: @application_setting[:email_restrictions_enabled].to_s, supported_syntax_link_url: 'https://github.com/google/re2/wiki/Syntax', email_restrictions: @application_setting.email_restrictions.to_s, after_sign_up_text: @application_setting[:after_sign_up_text].to_s, pending_user_count: pending_user_count } end def vscode_extension_marketplace_settings_view # NOTE: This is intentionally not scoped to a specific actor since it affects instance-level settings. return unless Feature.enabled?(:vscode_extension_marketplace_settings, nil) presets = ::WebIde::ExtensionMarketplacePreset.all.map do |preset| preset.to_h.deep_transform_keys { |key| key.to_s.camelize(:lower) } end { title: _('VS Code Extension Marketplace'), description: vscode_extension_marketplace_settings_description, view_model: { presets: presets, initialSettings: @application_setting.vscode_extension_marketplace || {} } } end def vscode_extension_marketplace_settings_description # NOTE: description is overridden in EE _('Enable VS Code Extension Marketplace and configure the extensions registry for Web IDE.') end def deletion_protection_data { deletion_adjourned_period: @application_setting[:deletion_adjourned_period] } end end ApplicationSettingsHelper.prepend_mod_with('ApplicationSettingsHelper') # The methods in `EE::ApplicationSettingsHelper` should be available as both # instance and class methods. ApplicationSettingsHelper.extend_mod_with('ApplicationSettingsHelper')