Module: UsersHelper

Instance Method Summary collapse

Instance Method Details

#admin_user_actions_data_attributes(user) ⇒ Object



205
206
207
208
209
210
# File 'app/helpers/users_helper.rb', line 205

def (user)
  {
    user: Admin::UserEntity.represent(user, { current_user: current_user }).to_json,
    paths: admin_users_paths.to_json
  }
end

#admin_users_data_attributes(users) ⇒ Object



4
5
6
7
8
9
# File 'app/helpers/users_helper.rb', line 4

def admin_users_data_attributes(users)
  {
    users: Admin::UserSerializer.new.represent(users, { current_user: current_user }).to_json,
    paths: admin_users_paths.to_json
  }
end

#can_force_email_confirmation?(user) ⇒ Boolean

Returns:

  • (Boolean)


161
162
163
# File 'app/helpers/users_helper.rb', line 161

def can_force_email_confirmation?(user)
  !user.confirmed?
end

#can_impersonate_user(user, impersonation_in_progress) ⇒ Object



116
117
118
# File 'app/helpers/users_helper.rb', line 116

def can_impersonate_user(user, impersonation_in_progress)
  can?(user, :log_in) && !user.password_expired? && !impersonation_in_progress
end

#confirm_user_data(user) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'app/helpers/users_helper.rb', line 165

def confirm_user_data(user)
  message = if user.unconfirmed_email.present?
              safe_format(
                _('This user has an unconfirmed email address (%{email}). You may force a confirmation.'),
                email: user.unconfirmed_email
              )
            else
              _('This user has an unconfirmed email address. You may force a confirmation.')
            end

  modal_attributes = Gitlab::Json.dump({
    title: s_('AdminUsers|Confirm user %{username}?') % { username: sanitize_name(user.name) },
    messageHtml: message,
    actionPrimary: {
      text: s_('AdminUsers|Confirm user'),
      attributes: [{ variant: 'confirm', 'data-testid': 'confirm-user-confirm-button' }]
    },
    actionSecondary: {
      text: _('Cancel'),
      attributes: [{ variant: 'default' }]
    }
  })

  {
    path: confirm_admin_user_path(user),
    method: 'put',
    modal_attributes: modal_attributes,
    testid: 'confirm-user-button'
  }
end

#current_user_menu?(item) ⇒ Boolean

Returns:

  • (Boolean)


63
64
65
# File 'app/helpers/users_helper.rb', line 63

def current_user_menu?(item)
  current_user_menu_items.include?(item)
end

#current_user_menu_itemsObject



59
60
61
# File 'app/helpers/users_helper.rb', line 59

def current_user_menu_items
  @current_user_menu_items ||= get_current_user_menu_items
end

#display_public_email?(user) ⇒ Boolean

Returns:

  • (Boolean)


218
219
220
# File 'app/helpers/users_helper.rb', line 218

def display_public_email?(user)
  user.public_email.present?
end

#email_verification_token_expired?(email_sent_at:) ⇒ Boolean

Returns:

  • (Boolean)


266
267
268
269
270
271
# File 'app/helpers/users_helper.rb', line 266

def email_verification_token_expired?(email_sent_at:)
  return false unless email_sent_at

  token_valid_for = Users::EmailVerification::ValidateTokenService::TOKEN_VALID_FOR_MINUTES.minutes
  (email_sent_at + token_valid_for).before?(Time.zone.now)
end

#has_contact_info?(user) ⇒ Boolean

Returns:

  • (Boolean)


212
213
214
215
216
# File 'app/helpers/users_helper.rb', line 212

def has_contact_info?(user)
  contact_fields = %i[bluesky discord linkedin mastodon skype twitter website_url]
  has_contact = contact_fields.any? { |field| user.public_send(field).present? }  # rubocop:disable GitlabSecurity/PublicSend -- fields are controlled, it is safe.
  has_contact || display_public_email?(user)
end

#impersonation_enabled?Boolean

Returns:

  • (Boolean)


108
109
110
# File 'app/helpers/users_helper.rb', line 108

def impersonation_enabled?
  Gitlab.config.gitlab.impersonation_enabled
end

#impersonation_error_text(user, impersonation_in_progress) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/helpers/users_helper.rb', line 120

def impersonation_error_text(user, impersonation_in_progress)
  if impersonation_in_progress
    _("You are already impersonating another user")
  elsif user.blocked?
    _("You cannot impersonate a blocked user")
  elsif user.password_expired?
    _("You cannot impersonate a user with an expired password")
  elsif user.internal?
    _("You cannot impersonate an internal user")
  else
    _("You cannot impersonate a user who cannot log in")
  end
end

#impersonation_tokens_enabled?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'app/helpers/users_helper.rb', line 112

def impersonation_tokens_enabled?
  impersonation_enabled?
end

#load_max_project_member_accesses(projects) ⇒ Object

Used to preload when you are rendering many projects and checking access



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'app/helpers/users_helper.rb', line 68

def load_max_project_member_accesses(projects)
  # There are two different request store paradigms for max member access and
  # we need to preload both of them. One is keyed User the other is keyed by
  # Project. See https://gitlab.com/gitlab-org/gitlab/-/issues/396822

  # rubocop: disable CodeReuse/ActiveRecord: `projects` can be array which also responds to pluck
  project_ids = projects.pluck(:id)
  # rubocop: enable CodeReuse/ActiveRecord

  preload_project_associations(projects)

  Preloaders::UserMaxAccessLevelInProjectsPreloader
    .new(project_ids, current_user)
    .execute

  current_user&.max_member_access_for_project_ids(project_ids)
end

#max_project_member_access(project) ⇒ Object



86
87
88
# File 'app/helpers/users_helper.rb', line 86

def max_project_member_access(project)
  current_user&.max_member_access_for_project(project.id) || Gitlab::Access::NO_ACCESS
end

#moderation_status(user) ⇒ Object



236
237
238
239
240
241
242
243
244
245
246
# File 'app/helpers/users_helper.rb', line 236

def moderation_status(user)
  return unless user.present?

  if user.banned?
    _('Banned')
  elsif user.blocked?
    _('Blocked')
  else
    _('Active')
  end
end

#profile_actions(user) ⇒ Object



40
41
42
43
44
45
46
# File 'app/helpers/users_helper.rb', line 40

def profile_actions(user)
  return [] unless can?(current_user, :read_user_profile, user)

  return [:overview, :activity] if user.bot?

  [:overview, :activity, :groups, :contributed, :projects, :starred, :snippets, :followers, :following]
end

#user_badges_in_admin_section(user) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
# File 'app/helpers/users_helper.rb', line 134

def user_badges_in_admin_section(user)
  [].tap do |badges|
    badges << blocked_user_badge(user) if user.blocked?
    badges << { text: s_('AdminUsers|Admin'), variant: 'success' } if user.admin? # rubocop:disable Cop/UserAdmin
    badges << { text: s_('AdminUsers|Bot'), variant: 'muted' } if user.bot?
    badges << { text: s_('AdminUsers|Deactivated'), variant: 'danger' } if user.deactivated?
    badges << { text: s_('AdminUsers|External'), variant: 'secondary' } if user.external?
    badges << { text: s_("AdminUsers|It's you!"), variant: 'muted' } if current_user == user
    badges << { text: s_("AdminUsers|Locked"), variant: 'warning' } if user.access_locked?
  end
end

#user_clear_status_at(user) ⇒ Object



11
12
13
14
15
16
# File 'app/helpers/users_helper.rb', line 11

def user_clear_status_at(user)
  # The user.status can be nil when the user has no status, so we need to protect against that case.
  # iso8601 is the official RFC supported format for frontend parsing of date:
  # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
  user.status&.clear_status_at&.to_fs(:iso8601)
end

#user_display_name(user) ⇒ Object



196
197
198
199
200
201
202
203
# File 'app/helpers/users_helper.rb', line 196

def user_display_name(user)
  return s_('UserProfile|Blocked user') if user.blocked?

  can_read_profile = can?(current_user, :read_user_profile, user)
  return s_('UserProfile|Unconfirmed user') unless user.confirmed? || can_read_profile

  user.name
end

#user_email_help_text(user) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'app/helpers/users_helper.rb', line 22

def user_email_help_text(user)
  return _('We also use email for avatar detection if no avatar is uploaded.') unless user.unconfirmed_email.present?

  confirmation_link = link_to _('Resend confirmation e-mail'),
    user_confirmation_path(user: { email: user.unconfirmed_email }),
    method: :post
  (
    h(
      _('Please click the link in the confirmation email before continuing. It was sent to ' \
        '%{html_tag_strong_start}%{email}%{html_tag_strong_end}.')
    ) % {
      html_tag_strong_start: '<strong>'.html_safe,
      html_tag_strong_end: '</strong>'.html_safe,
      email: user.unconfirmed_email
    }
  ) + (:p) { confirmation_link }
end

#user_internal_regex_dataObject



48
49
50
51
52
53
54
55
56
57
# File 'app/helpers/users_helper.rb', line 48

def user_internal_regex_data
  settings = Gitlab::CurrentSettings.current_application_settings

  pattern, options = if settings.user_default_internal_regex_enabled?
                       regex = settings.user_default_internal_regex_instance
                       JsRegex.new(regex).to_h.slice(:source, :options).values
                     end

  { user_internal_regex_pattern: pattern, user_internal_regex_options: options }
end


18
19
20
# File 'app/helpers/users_helper.rb', line 18

def user_link(user)
  link_to(user.name, user_path(user), title: user.email, class: 'has-tooltip commit-committer-link')
end

#user_profile_actions_data(user) ⇒ Object



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'app/helpers/users_helper.rb', line 248

def (user)
  basic_actions_data = {
    user_id: user.id
  }

  if can?(current_user, :read_user_profile, user)
    basic_actions_data[:rss_subscription_path] = user_path(user, rss_url_options)
  end

  return basic_actions_data if !current_user || current_user == user

  basic_actions_data.merge(
    report_abuse_path: add_category_abuse_reports_path,
    reported_user_id: user.id,
    reported_from_url: user_url(user)
  )
end

#user_profile_app_data(user) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'app/helpers/users_helper.rb', line 222

def (user)
  {
    followees_count: user.followees.count,
    followers_count: user.followers.count,
    user_calendar_path: user_calendar_path(user, :json),
    user_activity_path: user_activity_path(user, :json),
    utc_offset: local_timezone_instance(user.timezone).now.utc_offset,
    user_id: user.id,
    snippets_empty_state: image_path('illustrations/empty-state/empty-snippets-md.svg'),
    new_snippet_path: (new_snippet_path if can?(current_user, :create_snippet)),
    follow_empty_state: image_path('illustrations/empty-state/empty-friends-md.svg')
  }
end

#user_status(user) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'app/helpers/users_helper.rb', line 90

def user_status(user)
  return unless user

  unless user.association(:status).loaded?
    exception = RuntimeError.new("Status was not preloaded")
    Gitlab::ErrorTracking.track_and_raise_for_dev_exception(exception, user: user.inspect)
  end

  return unless user.status

   :span,
    class: 'user-status-emoji has-tooltip',
    title: user.status.message_html,
    data: { html: true, placement: 'top' } do
    emoji_icon user.status.emoji
  end
end

#work_information(user, with_schema_markup: false) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'app/helpers/users_helper.rb', line 146

def work_information(user, with_schema_markup: false)
  return unless user

  organization = user.organization
  job_title = user.job_title

  if organization.present? && job_title.present?
    render_job_title_and_organization(job_title, organization, with_schema_markup: with_schema_markup)
  elsif job_title.present?
    render_job_title(job_title, with_schema_markup: with_schema_markup)
  elsif organization.present?
    render_organization(organization, with_schema_markup: with_schema_markup)
  end
end