Module: API::Helpers

Includes:
Pagination, PaginationStrategies, Gitlab::Utils
Defined in:
lib/api/helpers.rb,
lib/api/helpers/runner.rb,
lib/api/helpers/version.rb,
lib/api/helpers/pagination.rb,
lib/api/helpers/presentable.rb,
lib/api/helpers/sse_helpers.rb,
lib/api/helpers/packages/npm.rb,
lib/api/helpers/rate_limiter.rb,
lib/api/helpers/label_helpers.rb,
lib/api/helpers/notes_helpers.rb,
lib/api/helpers/users_helpers.rb,
lib/api/helpers/wikis_helpers.rb,
lib/api/helpers/badges_helpers.rb,
lib/api/helpers/common_helpers.rb,
lib/api/helpers/events_helpers.rb,
lib/api/helpers/groups_helpers.rb,
lib/api/helpers/issues_helpers.rb,
lib/api/helpers/search_helpers.rb,
lib/api/helpers/graphql_helpers.rb,
lib/api/helpers/headers_helpers.rb,
lib/api/helpers/members_helpers.rb,
lib/api/helpers/internal_helpers.rb,
lib/api/helpers/packages_helpers.rb,
lib/api/helpers/projects_helpers.rb,
lib/api/helpers/services_helpers.rb,
lib/api/helpers/settings_helpers.rb,
lib/api/helpers/snippets_helpers.rb,
lib/api/helpers/custom_attributes.rb,
lib/api/helpers/discussions_helpers.rb,
lib/api/helpers/file_upload_helpers.rb,
lib/api/helpers/pagination_strategies.rb,
lib/api/helpers/merge_requests_helpers.rb,
lib/api/helpers/performance_bar_helpers.rb,
lib/api/helpers/project_snapshots_helpers.rb,
lib/api/helpers/related_resources_helpers.rb,
lib/api/helpers/packages/conan/api_helpers.rb,
lib/api/helpers/protected_branches_helpers.rb,
lib/api/helpers/packages/basic_auth_helpers.rb,
lib/api/helpers/resource_label_events_helpers.rb,
lib/api/helpers/packages_manager_clients_helpers.rb,
lib/api/helpers/packages/dependency_proxy_helpers.rb

Defined Under Namespace

Modules: BadgesHelpers, CommonHelpers, CustomAttributes, DiscussionsHelpers, EventsHelpers, FileUploadHelpers, GraphqlHelpers, GroupsHelpers, HeadersHelpers, InternalHelpers, IssuesHelpers, LabelHelpers, MembersHelpers, MergeRequestsHelpers, NotesHelpers, Packages, PackagesHelpers, PackagesManagerClientsHelpers, Pagination, PaginationStrategies, PerformanceBarHelpers, Presentable, ProjectSnapshotsHelpers, ProjectsHelpers, ProtectedBranchesHelpers, RateLimiter, RelatedResourcesHelpers, ResourceLabelEventsHelpers, Runner, SSEHelpers, SearchHelpers, ServicesHelpers, SettingsHelpers, SnippetsHelpers, UsersHelpers, WikisHelpers Classes: Version

Constant Summary collapse

SUDO_HEADER =
"HTTP_SUDO"
GITLAB_SHARED_SECRET_HEADER =
"Gitlab-Shared-Secret"
SUDO_PARAM =
:sudo
API_USER_ENV =
'gitlab.api.user'
API_EXCEPTION_ENV =
'gitlab.api.exception'
API_RESPONSE_STATUS_CODE =
'gitlab.api.response_status_code'

Instance Method Summary collapse

Methods included from PaginationStrategies

#paginate_with_strategies, #paginator

Methods included from Pagination

#paginate

Methods included from Gitlab::Utils

#allowlisted?, #append_path, #boolean_to_yes_no, #bytes_to_megabytes, #check_allowed_absolute_path!, #check_path_traversal!, #decode_path, #deep_indifferent_access, #ensure_array_from_string, #ensure_utf8_size, #force_utf8, #ms_to_round_sec, #multiple_key_invert, #nlbr, #parse_url, #random_string, #remove_line_breaks, #slugify, #stable_sort_by, #string_to_ip_object, #to_boolean, #to_exclusive_sentence, #try_megabytes_to_bytes, #valid_brackets?, #which

Instance Method Details

#accepted!Object


426
427
428
# File 'lib/api/helpers.rb', line 426

def accepted!
  render_api_error!('202 Accepted', 202)
end

#attributes_for_keys(keys, custom_params = nil) ⇒ Object


325
326
327
328
329
330
331
332
333
334
335
# File 'lib/api/helpers.rb', line 325

def attributes_for_keys(keys, custom_params = nil)
  params_hash = custom_params || params
  attrs = {}
  keys.each do |key|
    if params_hash[key].present? || (params_hash.key?(key) && params_hash[key] == false)
      attrs[key] = params_hash[key]
    end
  end
  permitted_attrs = ActionController::Parameters.new(attrs).permit!
  permitted_attrs.to_h
end

#authenticate!Object


223
224
225
# File 'lib/api/helpers.rb', line 223

def authenticate!
  unauthorized! unless current_user
end

#authenticate_by_gitlab_shell_token!Object


231
232
233
234
235
236
237
238
# File 'lib/api/helpers.rb', line 231

def authenticate_by_gitlab_shell_token!
  input = params['secret_token']
  input ||= Base64.decode64(headers[GITLAB_SHARED_SECRET_HEADER]) if headers.key?(GITLAB_SHARED_SECRET_HEADER)

  input&.chomp!

  unauthorized! unless Devise.secure_compare(secret_token, input)
end

#authenticate_non_get!Object


227
228
229
# File 'lib/api/helpers.rb', line 227

def authenticate_non_get!
  authenticate! unless %w[GET HEAD].include?(route.request_method)
end

#authenticated_as_admin!Object


245
246
247
248
# File 'lib/api/helpers.rb', line 245

def authenticated_as_admin!
  authenticate!
  forbidden! unless current_user.admin?
end

#authenticated_with_can_read_all_resources!Object


240
241
242
243
# File 'lib/api/helpers.rb', line 240

def authenticated_with_can_read_all_resources!
  authenticate!
  forbidden! unless current_user.can_read_all_resources?
end

#authorize!(action, subject = :global, reason = nil) ⇒ Object


250
251
252
# File 'lib/api/helpers.rb', line 250

def authorize!(action, subject = :global, reason = nil)
  forbidden!(reason) unless can?(current_user, action, subject)
end

#authorize_admin_groupObject


266
267
268
# File 'lib/api/helpers.rb', line 266

def authorize_admin_group
  authorize! :admin_group, user_group
end

#authorize_admin_projectObject


262
263
264
# File 'lib/api/helpers.rb', line 262

def authorize_admin_project
  authorize! :admin_project, user_project
end

#authorize_admin_tagObject


258
259
260
# File 'lib/api/helpers.rb', line 258

def authorize_admin_tag
  authorize! :admin_tag, user_project
end

#authorize_destroy_artifacts!Object


274
275
276
# File 'lib/api/helpers.rb', line 274

def authorize_destroy_artifacts!
  authorize! :destroy_artifacts, user_project
end

#authorize_push_projectObject


254
255
256
# File 'lib/api/helpers.rb', line 254

def authorize_push_project
  authorize! :push_code, user_project
end

#authorize_read_builds!Object


270
271
272
# File 'lib/api/helpers.rb', line 270

def authorize_read_builds!
  authorize! :read_build, user_project
end

#authorize_update_builds!Object


278
279
280
# File 'lib/api/helpers.rb', line 278

def authorize_update_builds!
  authorize! :update_build, user_project
end

#available_labels_for(label_parent, params = { include_ancestor_groups: true, only_group_labels: true }) ⇒ Object


92
93
94
95
96
97
98
99
100
101
# File 'lib/api/helpers.rb', line 92

def available_labels_for(label_parent, params = { include_ancestor_groups: true, only_group_labels: true })
  if label_parent.is_a?(Project)
    params.delete(:only_group_labels)
    params[:project_id] = label_parent.id
  else
    params[:group_id] = label_parent.id
  end

  LabelsFinder.new(current_user, params).execute
end

#bad_request!(attribute) ⇒ Object


367
368
369
370
371
# File 'lib/api/helpers.rb', line 367

def bad_request!(attribute)
  message = ["400 (Bad request)"]
  message << "\"" + attribute.to_s + "\" not given" if attribute
  render_api_error!(message.join(' '), 400)
end

#can?(object, action, subject = :global) ⇒ Boolean

Returns:

  • (Boolean)

310
311
312
# File 'lib/api/helpers.rb', line 310

def can?(object, action, subject = :global)
  Ability.allowed?(object, action, subject)
end

#check_namespace_access(namespace) ⇒ Object


149
150
151
152
153
# File 'lib/api/helpers.rb', line 149

def check_namespace_access(namespace)
  return namespace if can?(current_user, :read_namespace, namespace)

  not_found!('Namespace')
end

#check_sha_param!(params, merge_request) ⇒ Object


380
381
382
383
384
# File 'lib/api/helpers.rb', line 380

def check_sha_param!(params, merge_request)
  if params[:sha] && merge_request.diff_head_sha != params[:sha]
    render_api_error!("SHA does not match HEAD of source branch: #{merge_request.diff_head_sha}", 409)
  end
end

#check_unmodified_since!(last_modified) ⇒ Object


21
22
23
24
25
26
27
# File 'lib/api/helpers.rb', line 21

def check_unmodified_since!(last_modified)
  if_unmodified_since = Time.parse(headers['If-Unmodified-Since']) rescue nil

  if if_unmodified_since && last_modified && last_modified > if_unmodified_since
    render_api_error!('412 Precondition Failed', 412)
  end
end

#conflict!(message = nil) ⇒ Object


402
403
404
# File 'lib/api/helpers.rb', line 402

def conflict!(message = nil)
  render_api_error!(message || '409 Conflict', 409)
end

#created!Object


422
423
424
# File 'lib/api/helpers.rb', line 422

def created!
  render_api_error!('201 Created', 201)
end

#current_authenticated_jobObject

Returns the job associated with the token provided for authentication, if any


50
51
52
# File 'lib/api/helpers.rb', line 50

def current_authenticated_job
  @current_authenticated_job
end

#current_userObject

rubocop:disable Gitlab/ModuleWithInstanceVariables We can't rewrite this with StrongMemoize because `sudo!` would actually write to `@current_user`, and `sudo?` would immediately call `current_user` again which reads from `@current_user`. We should rewrite this in a way that using StrongMemoize is possible


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/api/helpers.rb', line 59

def current_user
  return @current_user if defined?(@current_user)

  @current_user = initial_current_user

  Gitlab::I18n.locale = @current_user&.preferred_language

  sudo!

  validate_access_token!(scopes: scopes_registered_for_endpoint) unless sudo?

  save_current_user_in_env(@current_user) if @current_user

  @current_user
end

#declared_params(options = {}) ⇒ Object


16
17
18
19
# File 'lib/api/helpers.rb', line 16

def declared_params(options = {})
  options = { include_parent_namespaces: false }.merge(options)
  declared(params, options).to_h.symbolize_keys
end

#destroy_conditionally!(resource, last_updated: nil) ⇒ Object


29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/api/helpers.rb', line 29

def destroy_conditionally!(resource, last_updated: nil)
  last_updated ||= resource.updated_at

  check_unmodified_since!(last_updated)

  status 204
  body false

  if block_given?
    yield resource
  else
    resource.destroy
  end
end

#file_too_large!Object


410
411
412
# File 'lib/api/helpers.rb', line 410

def file_too_large!
  render_api_error!('413 Request Entity Too Large', 413)
end

#filter_by_iid(items, iid) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


338
339
340
# File 'lib/api/helpers.rb', line 338

def filter_by_iid(items, iid)
  items.where(iid: iid)
end

#filter_by_search(items, text) ⇒ Object

rubocop: enable CodeReuse/ActiveRecord


349
350
351
# File 'lib/api/helpers.rb', line 349

def filter_by_search(items, text)
  items.search(text)
end

#filter_by_title(items, title) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


344
345
346
# File 'lib/api/helpers.rb', line 344

def filter_by_title(items, title)
  items.where(title: title)
end

#find_branch!(branch_name) ⇒ Object


177
178
179
180
181
182
183
# File 'lib/api/helpers.rb', line 177

def find_branch!(branch_name)
  if Gitlab::GitRefValidator.validate(branch_name)
    user_project.repository.find_branch(branch_name) || not_found!('Branch')
  else
    render_api_error!('The branch refname is invalid', 400)
  end
end

#find_build!(id) ⇒ Object

rubocop: enable CodeReuse/ActiveRecord


219
220
221
# File 'lib/api/helpers.rb', line 219

def find_build!(id)
  user_project.builds.find(id.to_i)
end

#find_group(id) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


130
131
132
133
134
135
136
# File 'lib/api/helpers.rb', line 130

def find_group(id)
  if id.to_s =~ /^\d+$/
    Group.find_by(id: id)
  else
    Group.find_by_full_path(id)
  end
end

#find_group!(id) ⇒ Object

rubocop: enable CodeReuse/ActiveRecord


139
140
141
142
143
144
145
146
147
# File 'lib/api/helpers.rb', line 139

def find_group!(id)
  group = find_group(id)

  if can?(current_user, :read_group, group)
    group
  else
    not_found!('Group')
  end
end

#find_merge_request_with_access(iid, access_level = :read_merge_request) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


212
213
214
215
216
# File 'lib/api/helpers.rb', line 212

def find_merge_request_with_access(iid, access_level = :read_merge_request)
  merge_request = user_project.merge_requests.find_by!(iid: iid)
  authorize! access_level, merge_request
  merge_request
end

#find_namespace(id) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


156
157
158
159
160
161
162
# File 'lib/api/helpers.rb', line 156

def find_namespace(id)
  if id.to_s =~ /^\d+$/
    Namespace.find_by(id: id)
  else
    Namespace.find_by_full_path(id)
  end
end

#find_namespace!(id) ⇒ Object

rubocop: enable CodeReuse/ActiveRecord


165
166
167
# File 'lib/api/helpers.rb', line 165

def find_namespace!(id)
  check_namespace_access(find_namespace(id))
end

#find_namespace_by_path(path) ⇒ Object


169
170
171
# File 'lib/api/helpers.rb', line 169

def find_namespace_by_path(path)
  Namespace.find_by_full_path(path)
end

#find_namespace_by_path!(path) ⇒ Object


173
174
175
# File 'lib/api/helpers.rb', line 173

def find_namespace_by_path!(path)
  check_namespace_access(find_namespace_by_path(path))
end

#find_project(id) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


108
109
110
111
112
113
114
115
116
# File 'lib/api/helpers.rb', line 108

def find_project(id)
  projects = Project.without_deleted

  if id.is_a?(Integer) || id =~ /^\d+$/
    projects.find_by(id: id)
  elsif id.include?("/")
    projects.find_by_full_path(id)
  end
end

#find_project!(id) ⇒ Object

rubocop: enable CodeReuse/ActiveRecord


119
120
121
122
123
124
125
126
127
# File 'lib/api/helpers.rb', line 119

def find_project!(id)
  project = find_project(id)

  if can?(current_user, :read_project, project)
    project
  else
    not_found!('Project')
  end
end

#find_project_commit(id) ⇒ Object

rubocop: enable CodeReuse/ActiveRecord


207
208
209
# File 'lib/api/helpers.rb', line 207

def find_project_commit(id)
  user_project.commit_by(oid: id)
end

#find_project_issue(iid, project_id = nil) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


194
195
196
197
198
# File 'lib/api/helpers.rb', line 194

def find_project_issue(iid, project_id = nil)
  project = project_id ? find_project!(project_id) : user_project

  ::IssuesFinder.new(current_user, project_id: project.id).find_by!(iid: iid)
end

#find_project_merge_request(iid) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


202
203
204
# File 'lib/api/helpers.rb', line 202

def find_project_merge_request(iid)
  MergeRequestsFinder.new(current_user, project_id: user_project.id).find_by!(iid: iid)
end

#find_tag!(tag_name) ⇒ Object


185
186
187
188
189
190
191
# File 'lib/api/helpers.rb', line 185

def find_tag!(tag_name)
  if Gitlab::GitRefValidator.validate(tag_name)
    user_project.repository.find_tag(tag_name) || not_found!('Tag')
  else
    render_api_error!('The tag refname is invalid', 400)
  end
end

#find_user(id) ⇒ Object


103
104
105
# File 'lib/api/helpers.rb', line 103

def find_user(id)
  UserFinder.new(id).find_by_id_or_username
end

#forbidden!(reason = nil) ⇒ Object

error helpers


361
362
363
364
365
# File 'lib/api/helpers.rb', line 361

def forbidden!(reason = nil)
  message = ['403 Forbidden']
  message << " - #{reason}" if reason
  render_api_error!(message.join(' '), 403)
end

#handle_api_exception(exception) ⇒ Object


453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
# File 'lib/api/helpers.rb', line 453

def handle_api_exception(exception)
  if report_exception?(exception)
    define_params_for_grape_middleware
    Gitlab::ErrorTracking.with_context(current_user) do
      Gitlab::ErrorTracking.track_exception(exception)
    end
  end

  # This is used with GrapeLogging::Loggers::ExceptionLogger
  env[API_EXCEPTION_ENV] = exception

  # lifted from https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb#L60
  trace = exception.backtrace

  message = ["\n#{exception.class} (#{exception.message}):\n"]
  message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
  message << "  " << trace.join("\n  ")
  message = message.join

  API.logger.add Logger::FATAL, message

  response_message =
    if Rails.env.test?
      message
    else
      '500 Internal Server Error'
    end

  rack_response({ 'message' => response_message }.to_json, 500)
end

#increment_counter(event_name) ⇒ Object


539
540
541
542
543
544
545
546
# File 'lib/api/helpers.rb', line 539

def increment_counter(event_name)
  feature_name = "usage_data_#{event_name}"
  return unless Feature.enabled?(feature_name)

  Gitlab::UsageDataCounters.count(event_name)
rescue => error
  Gitlab::AppLogger.warn("Redis tracking event failed for event: #{event_name}, message: #{error.message}")
end

#increment_unique_values(event_name, values) ⇒ Object

Parameters:

  • event_name (String)

    the event name

  • values (Array|String)

    the values counted


550
551
552
553
554
555
556
557
558
559
560
# File 'lib/api/helpers.rb', line 550

def increment_unique_values(event_name, values)
  return unless values.present?

  feature_flag = "usage_data_#{event_name}"

  return unless Feature.enabled?(feature_flag, default_enabled: true)

  Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name)
rescue => error
  Gitlab::AppLogger.warn("Redis tracking event failed for event: #{event_name}, message: #{error.message}")
end

#job_token_authentication?Boolean

Returns:

  • (Boolean)

44
45
46
# File 'lib/api/helpers.rb', line 44

def job_token_authentication?
  initial_current_user && @current_authenticated_job.present? # rubocop:disable Gitlab/ModuleWithInstanceVariables
end

#model_error_messages(model) ⇒ Object


436
437
438
# File 'lib/api/helpers.rb', line 436

def model_error_messages(model)
  model.errors.messages
end

#no_content!Object


418
419
420
# File 'lib/api/helpers.rb', line 418

def no_content!
  render_api_error!('204 No Content', 204)
end

#not_acceptable!Object


394
395
396
# File 'lib/api/helpers.rb', line 394

def not_acceptable!
  render_api_error!('406 Not Acceptable', 406)
end

#not_allowed!(message = nil) ⇒ Object


390
391
392
# File 'lib/api/helpers.rb', line 390

def not_allowed!(message = nil)
  render_api_error!(message || '405 Method Not Allowed', :method_not_allowed)
end

#not_found!(resource = nil) ⇒ Object


373
374
375
376
377
378
# File 'lib/api/helpers.rb', line 373

def not_found!(resource = nil)
  message = ["404"]
  message << resource if resource
  message << "Not Found"
  render_api_error!(message.join(' '), 404)
end

#not_modified!Object


414
415
416
# File 'lib/api/helpers.rb', line 414

def not_modified!
  render_api_error!('304 Not Modified', 304)
end

#order_options_with_tie_breakerObject


353
354
355
356
357
# File 'lib/api/helpers.rb', line 353

def order_options_with_tie_breaker
  order_options = { params[:order_by] => params[:sort] }
  order_options['id'] ||= params[:sort] || 'asc'
  order_options
end

#present_carrierwave_file!(file, supports_direct_download: true) ⇒ Object


514
515
516
517
518
519
520
521
522
523
524
525
526
# File 'lib/api/helpers.rb', line 514

def present_carrierwave_file!(file, supports_direct_download: true)
  return not_found! unless file&.exists?

  if file.file_storage?
    present_disk_file!(file.path, file.filename)
  elsif supports_direct_download && file.class.direct_download_enabled?
    redirect(file.url)
  else
    header(*Gitlab::Workhorse.send_url(file.url))
    status :ok
    body ""
  end
end

#present_disk_file!(path, filename, content_type = 'application/octet-stream') ⇒ Object

file helpers


498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# File 'lib/api/helpers.rb', line 498

def present_disk_file!(path, filename, content_type = 'application/octet-stream')
  filename ||= File.basename(path)
  header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: filename)
  header['Content-Transfer-Encoding'] = 'binary'
  content_type content_type

  # Support download acceleration
  case headers['X-Sendfile-Type']
  when 'X-Sendfile'
    header['X-Sendfile'] = path
    body
  else
    sendfile path
  end
end

#process_create_params(args) ⇒ Object


74
75
76
77
78
79
80
81
82
83
# File 'lib/api/helpers/snippets_helpers.rb', line 74

def process_create_params(args)
  with_api_params do |api_params|
    args[:snippet_actions] = args.delete(:files)&.map do |file|
      file[:action] = :create
      file.symbolize_keys
    end

    args.merge(api_params)
  end
end

#process_update_params(args) ⇒ Object


85
86
87
88
89
90
91
# File 'lib/api/helpers/snippets_helpers.rb', line 85

def process_update_params(args)
  with_api_params do |api_params|
    args[:snippet_actions] = args.delete(:files)&.map(&:symbolize_keys)

    args.merge(api_params)
  end
end

#project_finder_paramsObject

rubocop: enable CodeReuse/ActiveRecord


492
493
494
# File 'lib/api/helpers.rb', line 492

def project_finder_params
  project_finder_params_ce.merge(project_finder_params_ee)
end

#render_api_error!(message, status) ⇒ Object


444
445
446
447
448
449
450
451
# File 'lib/api/helpers.rb', line 444

def render_api_error!(message, status)
  # grape-logging doesn't pass the status code, so this is a
  # workaround for getting that information in the loggers:
  # https://github.com/aserafin/grape_logging/issues/71
  env[API_RESPONSE_STATUS_CODE] = Rack::Utils.status_code(status)

  error!({ 'message' => message }, status, header)
end

#render_spam_error!Object


440
441
442
# File 'lib/api/helpers.rb', line 440

def render_spam_error!
  render_api_error!({ error: 'Spam detected' }, 400)
end

#render_validation_error!(model) ⇒ Object


430
431
432
433
434
# File 'lib/api/helpers.rb', line 430

def render_validation_error!(model)
  if model.errors.any?
    render_api_error!(model_error_messages(model) || '400 Bad Request', 400)
  end
end

#reorder_projects(projects) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord


487
488
489
# File 'lib/api/helpers.rb', line 487

def reorder_projects(projects)
  projects.reorder(order_options_with_tie_breaker)
end

#require_gitlab_workhorse!Object


286
287
288
289
290
291
292
# File 'lib/api/helpers.rb', line 286

def require_gitlab_workhorse!
  verify_workhorse_api!

  unless env['HTTP_GITLAB_WORKHORSE'].present?
    forbidden!('Request should be executed via GitLab Workhorse')
  end
end

#require_pages_config_enabled!Object


306
307
308
# File 'lib/api/helpers.rb', line 306

def require_pages_config_enabled!
  not_found! unless Gitlab.config.pages.enabled
end

#require_pages_enabled!Object


302
303
304
# File 'lib/api/helpers.rb', line 302

def require_pages_enabled!
  not_found! unless user_project.pages_available?
end

#require_repository_enabled!(subject = :global) ⇒ Object


282
283
284
# File 'lib/api/helpers.rb', line 282

def require_repository_enabled!(subject = :global)
  not_found!("Repository") unless user_project.feature_available?(:repository, current_user)
end

#required_attributes!(keys) ⇒ Object

Checks the occurrences of required attributes, each attribute must be present in the params hash or a Bad Request error is invoked.

Parameters:

keys (required) - A hash consisting of keys that must be present

319
320
321
322
323
# File 'lib/api/helpers.rb', line 319

def required_attributes!(keys)
  keys.each do |key|
    bad_request!(key) unless params[key].present?
  end
end

#save_current_user_in_env(user) ⇒ Object

rubocop:enable Gitlab/ModuleWithInstanceVariables


76
77
78
# File 'lib/api/helpers.rb', line 76

def save_current_user_in_env(user)
  env[API_USER_ENV] = { user_id: user.id, username: user.username }
end

#service_unavailable!Object


398
399
400
# File 'lib/api/helpers.rb', line 398

def service_unavailable!
  render_api_error!('503 Service Unavailable', 503)
end

#sudo?Boolean

Returns:

  • (Boolean)

80
81
82
# File 'lib/api/helpers.rb', line 80

def sudo?
  initial_current_user != current_user
end

#track_event(action = action_name, **args) ⇒ Object


528
529
530
531
532
533
534
535
536
537
# File 'lib/api/helpers.rb', line 528

def track_event(action = action_name, **args)
  category = args.delete(:category) || self.options[:for].name
  raise "invalid category" unless category

  ::Gitlab::Tracking.event(category, action.to_s, **args)
rescue => error
  Gitlab::AppLogger.warn(
    "Tracking event failed for action: #{action}, category: #{category}, message: #{error.message}"
  )
end

#unauthorized!Object


386
387
388
# File 'lib/api/helpers.rb', line 386

def unauthorized!
  render_api_error!('401 Unauthorized', 401)
end

#unprocessable_entity!(message = nil) ⇒ Object


406
407
408
# File 'lib/api/helpers.rb', line 406

def unprocessable_entity!(message = nil)
  render_api_error!(message || '422 Unprocessable Entity', :unprocessable_entity)
end

#user_groupObject


84
85
86
# File 'lib/api/helpers.rb', line 84

def user_group
  @group ||= find_group!(params[:id])
end

#user_projectObject


88
89
90
# File 'lib/api/helpers.rb', line 88

def user_project
  @project ||= find_project!(params[:id])
end

#validate_params_for_multiple_files(snippet) ⇒ Object


93
94
95
96
97
98
99
# File 'lib/api/helpers/snippets_helpers.rb', line 93

def validate_params_for_multiple_files(snippet)
  return unless params[:content] || params[:file_name]

  if snippet.multiple_files?
    render_api_error!({ error: _('To update Snippets with multiple files, you must use the `files` parameter') }, 400)
  end
end

#verify_workhorse_api!Object


294
295
296
297
298
299
300
# File 'lib/api/helpers.rb', line 294

def verify_workhorse_api!
  Gitlab::Workhorse.verify_api_request!(request.headers)
rescue => e
  Gitlab::ErrorTracking.track_exception(e)

  forbidden!
end

#with_api_params {|{ api: true, request: request }| ... } ⇒ Object

Yields:

  • ({ api: true, request: request })

562
563
564
# File 'lib/api/helpers.rb', line 562

def with_api_params(&block)
  yield({ api: true, request: request })
end