Module: Gitlab::GonHelper

Instance Method Summary collapse

Methods included from Organizations::OrganizationHelper

#admin_organizations_index_app_data, #organization_activity_app_data, #organization_groups_and_projects_app_data, #organization_groups_edit_app_data, #organization_groups_new_app_data, #organization_index_app_data, #organization_layout_nav, #organization_new_app_data, #organization_projects_edit_app_data, #organization_settings_general_app_data, #organization_show_app_data, #organization_user_app_data, #ui_for_organizations_enabled?

Methods included from WebpackHelper

#prefetch_link_tag, #webpack_bundle_tag, #webpack_controller_bundle_tags, #webpack_entrypoint_paths, #webpack_preload_asset_tag, #webpack_public_host, #webpack_public_path

Methods included from ViteHelper

#universal_path_to_stylesheet, #universal_stylesheet_link_tag, #vite_enabled?, #vite_page_entrypoint_paths

Instance Method Details

#add_gon_feature_flagsObject

Initialize gon.features with any flags that should be made globally available to the frontend



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/gitlab/gon_helper.rb', line 96

def add_gon_feature_flags
  # Use `push_to_gon_attributes` directly since we have a computed feature flag with
  # an opt-out in ui_for_organizations_enabled?
  push_to_gon_attributes(:features, :ui_for_organizations, ui_for_organizations_enabled?)
  push_frontend_feature_flag(:organization_switching, current_user)
  push_frontend_feature_flag(:find_and_replace, current_user)
  # To be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/399248
  push_frontend_feature_flag(:remove_monitor_metrics)
  push_frontend_feature_flag(:new_project_creation_form, current_user, type: :wip)
  push_frontend_feature_flag(:work_items_client_side_boards, current_user)
  push_frontend_feature_flag(:glql_work_items, current_user)
  push_frontend_feature_flag(:glql_aggregation, current_user, type: :wip)
  push_frontend_feature_flag(:glql_typescript, current_user, type: :wip)
  push_frontend_feature_flag(:archive_group)
  push_frontend_feature_flag(:accessible_loading_button, current_user)

  # Expose the Project Studio user preference as if it were a feature flag
  push_force_frontend_feature_flag(:project_studio_enabled, true)

  push_force_frontend_feature_flag(:security_manager_role_enabled, Gitlab::Security::SecurityManagerConfig.enabled?)
end

#add_gon_user_specificObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/gitlab/gon_helper.rb', line 78

def add_gon_user_specific
  return unless current_user

  gon.version = Gitlab::VERSION # publish version only for logged in users
  gon.current_user_id = current_user.id
  gon.current_username = current_user.username
  gon.current_user_fullname = current_user.name
  gon.current_user_avatar_url = current_user.avatar_url
  gon.time_display_relative = current_user.time_display_relative
  gon.time_display_format = current_user.time_display_format

  return unless current_user.user_preference

  gon.text_editor = current_user.user_preference.text_editor
end

#add_gon_variablesObject



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/gitlab/gon_helper.rb', line 10

def add_gon_variables
  gon.api_version                   = 'v4'
  gon.default_avatar_url            = default_avatar_url
  gon.max_file_size                 = Gitlab::CurrentSettings.max_attachment_size
  gon.asset_host                    = ActionController::Base.asset_host
  gon.webpack_public_path           = webpack_public_path
  gon.relative_url_root             = Gitlab.config.gitlab.relative_url_root
  gon.user_color_mode               = Gitlab::ColorModes.for_user(current_user).css_class
  gon.user_color_scheme             = Gitlab::ColorSchemes.for_user(current_user).css_class
  gon.markdown_surround_selection   = current_user&.markdown_surround_selection
  gon.markdown_automatic_lists      = current_user&.markdown_automatic_lists
  gon.markdown_maintain_indentation = current_user&.markdown_maintain_indentation
  gon.math_rendering_limits_enabled = Gitlab::CurrentSettings.math_rendering_limits_enabled
  gon.allow_immediate_namespaces_deletion =
    Gitlab::CurrentSettings.allow_immediate_namespaces_deletion_for_user?(current_user)
  gon.iframe_rendering_enabled      = Gitlab::CurrentSettings.iframe_rendering_enabled?
  gon.iframe_rendering_allowlist    = Gitlab::CurrentSettings.iframe_rendering_allowlist

  # Sentry configurations for the browser client are done
  # via `Gitlab::CurrentSettings` from the Admin panel:
  # `/admin/application_settings/metrics_and_profiling`
  if Gitlab::CurrentSettings.sentry_enabled
    gon.sentry_dsn           = Gitlab::CurrentSettings.sentry_clientside_dsn
    gon.sentry_environment   = Gitlab::CurrentSettings.sentry_environment
    gon.sentry_clientside_traces_sample_rate = Gitlab::CurrentSettings.sentry_clientside_traces_sample_rate
  end

  gon.recaptcha_api_server_url = ::Recaptcha.configuration.api_server_url
  gon.recaptcha_sitekey      = Gitlab::CurrentSettings.recaptcha_site_key
  gon.gitlab_url             = Gitlab.config.gitlab.url
  gon.promo_url              = Gitlab::Routing.url_helpers.promo_url
  gon.forum_url              = Gitlab.community_forum_url
  gon.docs_url               = Gitlab.doc_url
  gon.revision               = Gitlab.revision
  gon.feature_category       = Gitlab::ApplicationContext.current_context_attribute(:feature_category).presence
  gon.            = ActionController::Base.helpers.asset_path('gitlab_logo.png')
  gon.secure                 = Gitlab.config.gitlab.https
  gon.sprite_icons           = IconsHelper.sprite_icon_path
  gon.sprite_file_icons      = IconsHelper.sprite_file_icons_path
  gon.illustrations_path     = IconsHelper.illustrations_path
  gon.emoji_sprites_css_path = universal_path_to_stylesheet('emoji_sprites')
  gon.emoji_backend_version  = Gitlab::Emoji::EMOJI_VERSION
  gon.gridstack_css_path     = universal_path_to_stylesheet('lazy_bundles/gridstack')
  gon.test_env               = Rails.env.test?
  gon.disable_animations     = Gitlab.config.gitlab['disable_animations']
  gon.suggested_label_colors = LabelsHelper.suggested_colors
  gon.first_day_of_week      = current_user&.first_day_of_week || Gitlab::CurrentSettings.first_day_of_week
  gon.time_display_relative  = true
  gon.time_display_format    = 0
  gon.ee                     = Gitlab.ee?
  gon.jh                     = Gitlab.jh?
  gon.dot_com                = Gitlab.com?
  gon.uf_error_prefix        = ::Gitlab::Utils::ErrorMessage::UF_ERROR_PREFIX
  gon.pat_prefix             = Gitlab::CurrentSettings.current_application_settings.personal_access_token_prefix
  gon.keyboard_shortcuts_enabled = current_user ? current_user.keyboard_shortcuts_enabled : true
  gon.broadcast_message_dismissal_path =
    current_user ? Gitlab::Routing.url_helpers.broadcast_message_dismissals_path : nil

  gon.diagramsnet_url = Gitlab::CurrentSettings.diagramsnet_url if Gitlab::CurrentSettings.diagramsnet_enabled

  if current_organization && ui_for_organizations_enabled?
    gon.current_organization = current_organization.slice(:id, :name, :full_path, :web_url, :avatar_url)
  end

  add_gon_user_specific
  add_gon_feature_flags
end

#current_organizationObject

::Current.organization is only valid within the context of a request, but it can be called from everywhere. So how do we avoid accidentally calling it outside of the context of a request? We banned it with Rubocop.

This method is acceptable because it is only included by controllers. This method intentionally looks like Devise’s current_user method, which has similar properties. rubocop:disable Gitlab/AvoidCurrentOrganization – This method follows the spirit of the rule



187
188
189
190
191
# File 'lib/gitlab/gon_helper.rb', line 187

def current_organization
  return unless ::Current.organization_assigned

  Organizations::FallbackOrganizationTracker.without_tracking { ::Current.organization }
end

#default_avatar_urlObject



168
169
170
171
172
173
174
175
176
# File 'lib/gitlab/gon_helper.rb', line 168

def default_avatar_url
  # We can't use ActionController::Base.helpers.image_url because it
  # doesn't return an actual URL because request is nil for some reason.
  #
  # We also can't use Gitlab::Utils.append_path because the image path
  # may be an absolute URL.
  URI.join(Gitlab.config.gitlab.url,
    ActionController::Base.helpers.image_path('no_avatar.png')).to_s
end

#push_application_setting(key) ⇒ Object



148
149
150
151
152
# File 'lib/gitlab/gon_helper.rb', line 148

def push_application_setting(key)
  return unless Gitlab::CurrentSettings.respond_to?(key)

  gon.push({ key => Gitlab::CurrentSettings.public_send(key) }) # rubocop:disable GitlabSecurity/PublicSend
end

#push_force_frontend_feature_flag(name, enabled) ⇒ Object

Exposes the state of a feature flag to the frontend code. Can be used for more complex feature flag checks.

name - The name of the feature flag, e.g. my_feature. enabled - Boolean to be pushed directly to the frontend. Should be fetched by checking a feature flag.

Raises:

  • (ArgumentError)


142
143
144
145
146
# File 'lib/gitlab/gon_helper.rb', line 142

def push_force_frontend_feature_flag(name, enabled)
  raise ArgumentError, 'enabled flag must be a Boolean' unless enabled.in?([true, false])

  push_to_gon_attributes(:features, name, enabled)
end

#push_frontend_ability(ability:, user:, resource: :global) ⇒ Object



129
130
131
132
133
134
135
# File 'lib/gitlab/gon_helper.rb', line 129

def push_frontend_ability(ability:, user:, resource: :global)
  push_to_gon_attributes(
    :abilities,
    ability,
    Ability.allowed?(user, ability, resource)
  )
end

#push_frontend_feature_flag(name, *args, **kwargs) ⇒ Object

Exposes the state of a feature flag to the frontend code.

name - The name of the feature flag, e.g. my_feature. args - Any additional arguments to pass to Feature.enabled?. This allows

you to check if a flag is enabled for a particular user.


123
124
125
126
127
# File 'lib/gitlab/gon_helper.rb', line 123

def push_frontend_feature_flag(name, *args, **kwargs)
  enabled = Feature.enabled?(name, *args, **kwargs)

  push_to_gon_attributes(:features, name, enabled)
end

#push_namespace_setting(key, object) ⇒ Object



154
155
156
157
158
# File 'lib/gitlab/gon_helper.rb', line 154

def push_namespace_setting(key, object)
  return unless object&.namespace_settings.respond_to?(key)

  gon.push({ key => object.namespace_settings.public_send(key) }) # rubocop:disable GitlabSecurity/PublicSend
end

#push_to_gon_attributes(key, name, enabled) ⇒ Object



160
161
162
163
164
165
166
# File 'lib/gitlab/gon_helper.rb', line 160

def push_to_gon_attributes(key, name, enabled)
  var_name = name.to_s.camelize(:lower)
  # Here the `true` argument signals gon that the value should be merged
  # into any existing ones, instead of overwriting them. This allows you to
  # use this method to push multiple feature flags.
  gon.push({ key => { var_name => enabled } }, true)
end