summaryrefslogtreecommitdiff
path: root/lib/api
diff options
context:
space:
mode:
Diffstat (limited to 'lib/api')
-rw-r--r--lib/api/api.rb3
-rw-r--r--lib/api/api_guard.rb15
-rw-r--r--lib/api/appearance.rb12
-rw-r--r--lib/api/avatar.rb2
-rw-r--r--lib/api/bulk_imports.rb2
-rw-r--r--lib/api/ci/helpers/runner.rb23
-rw-r--r--lib/api/ci/jobs.rb6
-rw-r--r--lib/api/ci/runner.rb10
-rw-r--r--lib/api/ci/runners.rb10
-rw-r--r--lib/api/ci/secure_files.rb2
-rw-r--r--lib/api/concerns/packages/debian_distribution_endpoints.rb12
-rw-r--r--lib/api/concerns/packages/debian_package_endpoints.rb2
-rw-r--r--lib/api/debian_group_packages.rb4
-rw-r--r--lib/api/debian_project_packages.rb33
-rw-r--r--lib/api/draft_notes.rb126
-rw-r--r--lib/api/entities/appearance.rb4
-rw-r--r--lib/api/entities/ci/job_basic.rb1
-rw-r--r--lib/api/entities/ci/secure_file.rb1
-rw-r--r--lib/api/entities/draft_note.rb45
-rw-r--r--lib/api/entities/issue.rb4
-rw-r--r--lib/api/entities/merge_request_basic.rb1
-rw-r--r--lib/api/entities/packages/debian/distribution.rb2
-rw-r--r--lib/api/entities/project.rb1
-rw-r--r--lib/api/entities/project_with_access.rb24
-rw-r--r--lib/api/entities/release.rb7
-rw-r--r--lib/api/entities/releases/link.rb2
-rw-r--r--lib/api/entities/user.rb2
-rw-r--r--lib/api/entities/wiki_page.rb2
-rw-r--r--lib/api/events.rb2
-rw-r--r--lib/api/group_debian_distributions.rb4
-rw-r--r--lib/api/helpers.rb29
-rw-r--r--lib/api/helpers/internal_helpers.rb4
-rw-r--r--lib/api/helpers/members_helpers.rb7
-rw-r--r--lib/api/helpers/packages_helpers.rb32
-rw-r--r--lib/api/helpers/projects_helpers.rb4
-rw-r--r--lib/api/helpers/users_helpers.rb10
-rw-r--r--lib/api/internal/kubernetes.rb4
-rw-r--r--lib/api/invitations.rb4
-rw-r--r--lib/api/issue_links.rb6
-rw-r--r--lib/api/issues.rb25
-rw-r--r--lib/api/members.rb1
-rw-r--r--lib/api/merge_requests.rb10
-rw-r--r--lib/api/namespaces.rb6
-rw-r--r--lib/api/pages_domains.rb4
-rw-r--r--lib/api/project_container_repositories.rb2
-rw-r--r--lib/api/project_debian_distributions.rb4
-rw-r--r--lib/api/project_events.rb2
-rw-r--r--lib/api/projects.rb34
-rw-r--r--lib/api/releases.rb19
-rw-r--r--lib/api/settings.rb4
-rw-r--r--lib/api/time_tracking_endpoints.rb4
-rw-r--r--lib/api/users.rb53
-rw-r--r--lib/api/validations/validators/bulk_imports.rb4
53 files changed, 448 insertions, 188 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 5e449022676..4b7fe6bdc7a 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -164,7 +164,7 @@ module API
namespace do
after do
- ::Users::ActivityService.new(@current_user).execute
+ ::Users::ActivityService.new(author: @current_user, project: @project, namespace: @group).execute
end
# Mount endpoints to include in the OpenAPI V2 documentation here
@@ -209,6 +209,7 @@ module API
mount ::API::DeployKeys
mount ::API::DeployTokens
mount ::API::Deployments
+ mount ::API::DraftNotes
mount ::API::Environments
mount ::API::ErrorTracking::ClientKeys
mount ::API::ErrorTracking::ProjectSettings
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index df550f12c0d..81a640d9a93 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -57,10 +57,7 @@ module API
user = find_user_from_sources
return unless user
- if user.is_a?(User) && Gitlab::CurrentSettings.admin_mode
- # Sessions are enforced to be unavailable for API calls, so ignore them for admin mode
- Gitlab::Auth::CurrentUserMode.bypass_session!(user.id)
- end
+ Gitlab::Auth::CurrentUserMode.bypass_session!(user.id) if bypass_session_for_admin_mode?(user)
unless api_access_allowed?(user)
forbidden!(api_access_denied_message(user))
@@ -85,6 +82,16 @@ module API
private
+ def bypass_session_for_admin_mode?(user)
+ return user.is_a?(User) && Gitlab::CurrentSettings.admin_mode if Feature.disabled?(:admin_mode_for_api)
+
+ return false unless Gitlab::CurrentSettings.admin_mode
+ return false unless user.is_a?(User)
+
+ Gitlab::Session.with_session(current_request.session) { Gitlab::Auth::CurrentUserMode.new(user).admin_mode? } ||
+ Gitlab::Auth::RequestAuthenticator.new(current_request).valid_access_token?(scopes: [:admin_mode])
+ end
+
# An array of scopes that were registered (using `allow_access_with_scope`)
# for the current endpoint class. It also returns scopes registered on
# `API::API`, since these are meant to apply to all API routes.
diff --git a/lib/api/appearance.rb b/lib/api/appearance.rb
index 99278bdf8b0..f8e4f5d2ab2 100644
--- a/lib/api/appearance.rb
+++ b/lib/api/appearance.rb
@@ -26,13 +26,15 @@ module API
end
params do
optional :title, type: String, desc: 'Instance title on the sign in / sign up page'
- optional :pwa_short_name, type: String, desc: 'Optional, short name for Progressive Web App'
optional :description, type: String, desc: 'Markdown text shown on the sign in / sign up page'
+ optional :pwa_name, type: String, desc: 'Name of the Progressive Web App'
+ optional :pwa_short_name, type: String, desc: 'Optional, short name for Progressive Web App'
+ optional :pwa_description, type: String, desc: 'An explanation of what the Progressive Web App does'
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
- optional :logo, type: File, desc: 'Instance image used on the sign in / sign up page' # rubocop:disable Scalability/FileUploads
- optional :pwa_icon, type: File, desc: 'Icon used for Progressive Web App' # rubocop:disable Scalability/FileUploads
- optional :header_logo, type: File, desc: 'Instance image used for the main navigation bar' # rubocop:disable Scalability/FileUploads
- optional :favicon, type: File, desc: 'Instance favicon in .ico/.png format' # rubocop:disable Scalability/FileUploads
+ optional :logo, type: File, desc: 'Instance image used on the sign in / sign up page' # rubocop:todo Scalability/FileUploads
+ optional :pwa_icon, type: File, desc: 'Icon used for Progressive Web App' # rubocop:todo Scalability/FileUploads
+ optional :header_logo, type: File, desc: 'Instance image used for the main navigation bar' # rubocop:todo Scalability/FileUploads
+ optional :favicon, type: File, desc: 'Instance favicon in .ico/.png format' # rubocop:todo Scalability/FileUploads
optional :new_project_guidelines, type: String, desc: 'Markdown text shown on the new project page'
optional :profile_image_guidelines, type: String, desc: 'Markdown text shown on the profile page below Public Avatar'
optional :header_message, type: String, desc: 'Message within the system header bar'
diff --git a/lib/api/avatar.rb b/lib/api/avatar.rb
index 0fb7a4cd435..addea780eb0 100644
--- a/lib/api/avatar.rb
+++ b/lib/api/avatar.rb
@@ -2,7 +2,7 @@
module API
class Avatar < ::API::Base
- feature_category :users
+ feature_category :user_profile
urgency :medium
resource :avatar do
diff --git a/lib/api/bulk_imports.rb b/lib/api/bulk_imports.rb
index 6c07b15329e..e3dc9ea52cb 100644
--- a/lib/api/bulk_imports.rb
+++ b/lib/api/bulk_imports.rb
@@ -91,6 +91,8 @@ module API
end
end
post do
+ check_rate_limit!(:bulk_import, scope: current_user)
+
params[:entities].each do |entity|
if entity[:destination_name]
entity[:destination_slug] ||= entity[:destination_name]
diff --git a/lib/api/ci/helpers/runner.rb b/lib/api/ci/helpers/runner.rb
index be4d82bc500..96f5265ce23 100644
--- a/lib/api/ci/helpers/runner.rb
+++ b/lib/api/ci/helpers/runner.rb
@@ -10,23 +10,32 @@ module API
JOB_TOKEN_HEADER = 'HTTP_JOB_TOKEN'
JOB_TOKEN_PARAM = :token
+ LEGACY_SYSTEM_XID = '<legacy>'
def authenticate_runner!
track_runner_authentication
forbidden! unless current_runner
- current_runner
- .heartbeat(get_runner_details_from_request)
+ runner_details = get_runner_details_from_request
+ current_runner.heartbeat(runner_details)
+ current_runner_machine&.heartbeat(runner_details)
end
def get_runner_details_from_request
return get_runner_ip unless params['info'].present?
attributes_for_keys(%w(name version revision platform architecture executor), params['info'])
+ .merge(get_system_id_from_request)
.merge(get_runner_config_from_request)
.merge(get_runner_ip)
end
+ def get_system_id_from_request
+ return { system_id: params[:system_id] } if params.include?(:system_id)
+
+ {}
+ end
+
def get_runner_ip
{ ip_address: ip_address }
end
@@ -43,6 +52,15 @@ module API
end
end
+ def current_runner_machine
+ return if Feature.disabled?(:create_runner_machine)
+
+ strong_memoize(:current_runner_machine) do
+ system_xid = params.fetch(:system_id, LEGACY_SYSTEM_XID)
+ current_runner&.ensure_machine(system_xid) { |m| m.contacted_at = Time.current }
+ end
+ end
+
def track_runner_authentication
if current_runner
metrics.increment_runner_authentication_success_counter(runner_type: current_runner.runner_type)
@@ -78,6 +96,7 @@ module API
# the heartbeat should be triggered.
if heartbeat_runner
job.runner&.heartbeat(get_runner_ip)
+ job.runner_machine&.heartbeat(get_runner_ip)
end
job
diff --git a/lib/api/ci/jobs.rb b/lib/api/ci/jobs.rb
index ed1c7dfbfa2..30d12864bf8 100644
--- a/lib/api/ci/jobs.rb
+++ b/lib/api/ci/jobs.rb
@@ -57,11 +57,7 @@ module API
builds = filter_builds(builds, params[:scope])
builds = builds.preload(:user, :job_artifacts_archive, :job_artifacts, :runner, :tags, pipeline: :project)
- if Feature.enabled?(:jobs_api_keyset_pagination, user_project)
- present paginate_with_strategies(builds, paginator_params: { without_count: true }), with: Entities::Ci::Job
- else
- present paginate(builds, without_count: true), with: Entities::Ci::Job
- end
+ present paginate_with_strategies(builds, paginator_params: { without_count: true }), with: Entities::Ci::Job
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 6b4394114df..1c81db39bb1 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -77,15 +77,18 @@ module API
desc 'Validate authentication credentials' do
summary "Verify authentication for a registered runner"
+ success Entities::Ci::RunnerRegistrationDetails
http_codes [[200, 'Credentials are valid'], [403, 'Forbidden']]
end
params do
requires :token, type: String, desc: %q(The runner's authentication token)
+ optional :system_id, type: String, desc: %q(The runner's system identifier)
end
post '/verify', urgency: :low, feature_category: :runner do
authenticate_runner!
status 200
- body "200"
+
+ present current_runner, with: Entities::Ci::RunnerRegistrationDetails
end
desc 'Reset runner authentication token with current token' do
@@ -115,6 +118,7 @@ module API
end
params do
requires :token, type: String, desc: %q(Runner's authentication token)
+ optional :system_id, type: String, desc: %q(Runner's system identifier)
optional :last_update, type: String, desc: %q(Runner's queue last_update token)
optional :info, type: Hash, desc: %q(Runner's metadata) do
optional :name, type: String, desc: %q(Runner's name)
@@ -166,7 +170,7 @@ module API
end
new_update = current_runner.ensure_runner_queue_value
- result = ::Ci::RegisterJobService.new(current_runner).execute(runner_params)
+ result = ::Ci::RegisterJobService.new(current_runner, current_runner_machine).execute(runner_params)
if result.valid?
if result.build_json
@@ -192,7 +196,7 @@ module API
[403, 'Forbidden']]
end
params do
- requires :token, type: String, desc: %q(Runner's authentication token)
+ requires :token, type: String, desc: %q(Job token)
requires :id, type: Integer, desc: %q(Job's ID)
optional :state, type: String, desc: %q(Job's status: success, failed)
optional :checksum, type: String, desc: %q(Job's trace CRC32 checksum)
diff --git a/lib/api/ci/runners.rb b/lib/api/ci/runners.rb
index 4a6c58b4987..f2f0f32261a 100644
--- a/lib/api/ci/runners.rb
+++ b/lib/api/ci/runners.rb
@@ -13,7 +13,7 @@ module API
helpers do
params :deprecated_filter_params do
optional :scope, type: String, values: ::Ci::Runner::AVAILABLE_SCOPES,
- desc: 'Deprecated: Use `type` or `status` instead. The scope of specific runners to return'
+ desc: 'Deprecated: Use `type` or `status` instead. The scope of runners to return'
end
params :filter_params do
@@ -111,9 +111,9 @@ module API
present paginate(runners), with: Entities::Ci::Runner
end
- desc 'Get all runners - shared and specific' do
+ desc 'Get all runners - shared and project' do
summary 'List all runners'
- detail 'Get a list of all runners in the GitLab instance (specific and shared). ' \
+ detail 'Get a list of all runners in the GitLab instance (shared and project). ' \
'Access is restricted to users with administrator access.'
success Entities::Ci::Runner
failure [[400, 'Scope contains invalid value'], [401, 'Unauthorized']]
@@ -286,7 +286,7 @@ module API
end
desc 'Enable a runner in project' do
- detail "Enable an available specific runner in the project."
+ detail "Enable an available project runner in the project."
success Entities::Ci::Runner
failure [[400, 'Bad Request'],
[403, 'No access granted'], [403, 'Runner is a group runner'], [403, 'Runner is locked'],
@@ -308,7 +308,7 @@ module API
end
desc "Disable project's runner" do
- summary "Disable a specific runner from the project"
+ summary "Disable a project runner from the project"
detail "It works only if the project isn't the only project associated with the specified runner. " \
"If so, an error is returned. Use the call to delete a runner instead."
success Entities::Ci::Runner
diff --git a/lib/api/ci/secure_files.rb b/lib/api/ci/secure_files.rb
index 6483abcc74e..41faaf80c82 100644
--- a/lib/api/ci/secure_files.rb
+++ b/lib/api/ci/secure_files.rb
@@ -10,7 +10,7 @@ module API
authorize! :read_secure_files, user_project
end
- feature_category :pipeline_authoring
+ feature_category :mobile_devops
default_format :json
diff --git a/lib/api/concerns/packages/debian_distribution_endpoints.rb b/lib/api/concerns/packages/debian_distribution_endpoints.rb
index 6fe3f432edb..7aad3a56422 100644
--- a/lib/api/concerns/packages/debian_distribution_endpoints.rb
+++ b/lib/api/concerns/packages/debian_distribution_endpoints.rb
@@ -76,7 +76,7 @@ module API
end
params do
- requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'unstable' }
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'sid' }
use :optional_distribution_params
end
post '/' do
@@ -107,7 +107,7 @@ module API
params do
use :pagination
- optional :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'unstable' }
+ optional :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'sid' }
use :optional_distribution_params
end
get '/' do
@@ -132,7 +132,7 @@ module API
end
params do
- requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'unstable' }
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'sid' }
end
get '/:codename' do
authorize_read_package!(project_or_group)
@@ -153,7 +153,7 @@ module API
end
params do
- requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'unstable' }
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'sid' }
end
get '/:codename/key.asc' do
authorize_read_package!(project_or_group)
@@ -179,7 +179,7 @@ module API
end
params do
- requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'unstable' }
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'sid' }
use :optional_distribution_params
end
put '/:codename' do
@@ -210,7 +210,7 @@ module API
end
params do
- requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'unstable' }
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename', documentation: { example: 'sid' }
use :optional_distribution_params
end
delete '/:codename' do
diff --git a/lib/api/concerns/packages/debian_package_endpoints.rb b/lib/api/concerns/packages/debian_package_endpoints.rb
index 181759a7f38..db31f2e35f1 100644
--- a/lib/api/concerns/packages/debian_package_endpoints.rb
+++ b/lib/api/concerns/packages/debian_package_endpoints.rb
@@ -44,6 +44,8 @@ module API
end
def present_index_file!(file_type)
+ not_found!("Format #{params[:format]} is not supported") unless params[:format].nil?
+
relation = "::Packages::Debian::#{project_or_group.class.name}ComponentFile".constantize
relation = relation
diff --git a/lib/api/debian_group_packages.rb b/lib/api/debian_group_packages.rb
index 483d0dd9c90..67416e62f7d 100644
--- a/lib/api/debian_group_packages.rb
+++ b/lib/api/debian_group_packages.rb
@@ -6,10 +6,6 @@ module API
project_id: %r{[0-9]+}.freeze
).freeze
- before do
- not_found! if Gitlab::FIPS.enabled?
- end
-
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
helpers do
def project_or_group
diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb
index 353f64b8dd1..21c0c219046 100644
--- a/lib/api/debian_project_packages.rb
+++ b/lib/api/debian_project_packages.rb
@@ -14,10 +14,6 @@ module API
file_name: API::NO_SLASH_URL_PART_REGEX
}.freeze
- before do
- not_found! if Gitlab::FIPS.enabled?
- end
-
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
helpers do
def project_or_group
@@ -69,6 +65,7 @@ module API
format :txt
content_type :json, Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
+ # PUT {projects|groups}/:id/packages/debian/:file_name
desc 'Upload Debian package' do
detail 'This feature was introduced in GitLab 14.0'
success code: 201
@@ -80,12 +77,14 @@ module API
]
tags %w[debian_packages]
end
-
- # PUT {projects|groups}/:id/packages/debian/:file_name
params do
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' }
+ optional :distribution, type: String, desc: 'The Debian Codename or Suite', regexp: Gitlab::Regex.debian_distribution_regex
+ given :distribution do
+ requires :component, type: String, desc: 'The Debian Component', regexp: Gitlab::Regex.debian_component_regex
+ requires :file_name, type: String, desc: 'The filename', regexp: { value: Gitlab::Regex.debian_direct_upload_filename_regex, message: 'Only debs and udebs can be directly added to a distribution' }
+ end
end
-
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put do
authorize_upload!(authorized_user_project)
@@ -95,10 +94,18 @@ module API
file: params['file'],
file_name: params['file_name'],
file_sha1: params['file.sha1'],
- file_md5: params['file.md5']
+ file_md5: params['file.md5'],
+ distribution: params['distribution'],
+ component: params['component']
}
- package = ::Packages::Debian::FindOrCreateIncomingService.new(authorized_user_project, current_user).execute
+ package = if params[:distribution].present?
+ ::Packages::CreateTemporaryPackageService.new(
+ authorized_user_project, current_user, declared_params.merge(build: current_authenticated_job)
+ ).execute(:debian, name: ::Packages::Debian::TEMPORARY_PACKAGE_NAME)
+ else
+ ::Packages::Debian::FindOrCreateIncomingService.new(authorized_user_project, current_user).execute
+ end
::Packages::Debian::CreatePackageFileService.new(package: package, current_user: current_user, params: file_params).execute
@@ -114,12 +121,20 @@ module API
detail 'This feature was introduced in GitLab 13.5'
success code: 200
failure [
+ { code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
+ params do
+ optional :distribution, type: String, desc: 'The Debian Codename or Suite', regexp: Gitlab::Regex.debian_distribution_regex
+ given :distribution do
+ requires :component, type: String, desc: 'The Debian Component', regexp: Gitlab::Regex.debian_component_regex
+ requires :file_name, type: String, desc: 'The filename', regexp: { value: Gitlab::Regex.debian_direct_upload_filename_regex, message: 'Only debs and udebs can be directly added to a distribution' }
+ end
+ end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put 'authorize' do
authorize_workhorse!(
diff --git a/lib/api/draft_notes.rb b/lib/api/draft_notes.rb
new file mode 100644
index 00000000000..842180652c4
--- /dev/null
+++ b/lib/api/draft_notes.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+module API
+ class DraftNotes < ::API::Base
+ before { authenticate! }
+
+ urgency :low
+
+ helpers do
+ def merge_request(params:)
+ strong_memoize(:merge_request) do
+ find_project_merge_request(params[:merge_request_iid])
+ end
+ end
+
+ def load_draft_notes(params:)
+ merge_request(params: params).draft_notes.authored_by(current_user)
+ end
+
+ def get_draft_note(params:)
+ load_draft_notes(params: params).find(params[:draft_note_id])
+ end
+
+ def delete_draft_note(draft_note)
+ ::DraftNotes::DestroyService.new(user_project, current_user).execute(draft_note)
+ end
+
+ def publish_draft_note(params:)
+ ::DraftNotes::PublishService
+ .new(merge_request(params: params), current_user)
+ .execute(get_draft_note(params: params))
+ end
+ end
+
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc "Get a list of merge request draft notes" do
+ success Entities::DraftNote
+ is_array true
+ failure [
+ { code: 401, message: 'Unauthorized' },
+ { code: 404, message: 'Not found' }
+ ]
+ end
+ params do
+ requires :id, type: String, desc: "The ID of a project"
+ requires :merge_request_iid, type: Integer, desc: "The ID of a merge request"
+ end
+ get ":id/merge_requests/:merge_request_iid/draft_notes", feature_category: :code_review_workflow do
+ present load_draft_notes(params: params), with: Entities::DraftNote
+ end
+
+ desc "Get a single draft note" do
+ success Entities::DraftNote
+ failure [
+ { code: 401, message: 'Unauthorized' },
+ { code: 404, message: 'Not found' }
+ ]
+ end
+ params do
+ requires :id, type: String, desc: "The ID of a project"
+ requires :merge_request_iid, type: Integer, desc: "The ID of a merge request"
+ requires :draft_note_id, type: Integer, desc: "The ID of a draft note"
+ end
+ get ":id/merge_requests/:merge_request_iid/draft_notes/:draft_note_id", feature_category: :code_review_workflow do
+ draft_note = get_draft_note(params: params)
+
+ if draft_note
+ present draft_note, with: Entities::DraftNote
+ else
+ not_found!("Draft Note")
+ end
+ end
+
+ desc "Delete a draft note" do
+ success Entities::DraftNote
+ failure [
+ { code: 401, message: 'Unauthorized' },
+ { code: 404, message: 'Not found' }
+ ]
+ end
+ params do
+ requires :id, type: String, desc: "The ID of a project"
+ requires :merge_request_iid, type: Integer, desc: "The ID of a merge request"
+ requires :draft_note_id, type: Integer, desc: "The ID of a draft note"
+ end
+ delete(
+ ":id/merge_requests/:merge_request_iid/draft_notes/:draft_note_id",
+ feature_category: :code_review_workflow) do
+ draft_note = get_draft_note(params: params)
+
+ if draft_note
+ delete_draft_note(draft_note)
+ status 204
+ body false
+ else
+ not_found!("Draft Note")
+ end
+ end
+
+ desc "Publish a pending draft note" do
+ success code: 204
+ failure [
+ { code: 401, message: 'Unauthorized' },
+ { code: 404, message: 'Not found' }
+ ]
+ end
+ params do
+ requires :id, type: String, desc: "The ID of a project"
+ requires :merge_request_iid, type: Integer, desc: "The ID of a merge request"
+ requires :draft_note_id, type: Integer, desc: "The ID of a draft note"
+ end
+ put(
+ ":id/merge_requests/:merge_request_iid/draft_notes/:draft_note_id/publish",
+ feature_category: :code_review_workflow) do
+ result = publish_draft_note(params: params)
+
+ if result[:status] == :success
+ status 204
+ body false
+ else
+ status 500
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/appearance.rb b/lib/api/entities/appearance.rb
index cabdf68c23a..2825c84e01d 100644
--- a/lib/api/entities/appearance.rb
+++ b/lib/api/entities/appearance.rb
@@ -4,8 +4,10 @@ module API
module Entities
class Appearance < Grape::Entity
expose :title
- expose :pwa_short_name
expose :description
+ expose :pwa_name
+ expose :pwa_short_name
+ expose :pwa_description
expose :logo do |appearance, options|
appearance.logo.url
diff --git a/lib/api/entities/ci/job_basic.rb b/lib/api/entities/ci/job_basic.rb
index 3cbb8aad313..526dfba05f2 100644
--- a/lib/api/entities/ci/job_basic.rb
+++ b/lib/api/entities/ci/job_basic.rb
@@ -15,6 +15,7 @@ module API
expose :created_at, documentation: { type: 'dateTime', example: '2015-12-24T15:51:21.880Z' }
expose :started_at, documentation: { type: 'dateTime', example: '2015-12-24T17:54:30.733Z' }
expose :finished_at, documentation: { type: 'dateTime', example: '2015-12-24T17:54:31.198Z' }
+ expose :erased_at, documentation: { type: 'dateTime', example: '2015-12-24T18:00:29.728Z' }
expose :duration,
documentation: { type: 'number', format: 'float', desc: 'Time spent running', example: 0.465 }
expose :queued_duration,
diff --git a/lib/api/entities/ci/secure_file.rb b/lib/api/entities/ci/secure_file.rb
index a234ada6f82..bf8d2776db1 100644
--- a/lib/api/entities/ci/secure_file.rb
+++ b/lib/api/entities/ci/secure_file.rb
@@ -12,6 +12,7 @@ documentation: { type: 'string', example: '16630b189ab34b2e3504f4758e1054d2e478d
expose :created_at, documentation: { type: 'dateTime', example: '2022-02-22T22:22:22.222Z' }
expose :expires_at, documentation: { type: 'dateTime', example: '2022-09-21T14:56:00.000Z' }
expose :metadata, documentation: { type: 'Hash', example: { "id" => "75949910542696343243264405377658443914" } }
+ expose :file_extension, documentation: { type: 'string', example: 'jks' }
end
end
end
diff --git a/lib/api/entities/draft_note.rb b/lib/api/entities/draft_note.rb
new file mode 100644
index 00000000000..70b32bac502
--- /dev/null
+++ b/lib/api/entities/draft_note.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class DraftNote < Grape::Entity
+ expose :id, documentation: { type: 'integer', example: 2 }
+ expose :author_id, documentation: { type: 'integer', example: 4 }
+ expose :merge_request_id, documentation: { type: 'integer', example: 52 }
+ expose :resolve_discussion, documentation: { type: 'boolean', example: true }
+ expose :discussion_id, documentation: { type: 'integer', example: 613 }
+ expose :note, documentation: { type: 'string', example: 'This is a note' }
+ expose :commit_id, documentation: { type: 'integer', example: 4 }
+ expose :line_code, documentation: { type: 'string', example: '1c497fbb3a46b78edf0_2_4' }
+ expose :position, documentation: {
+ type: 'Hash',
+ example: {
+ base_sha: "aa149113",
+ start_sha: "b3a0a8c4",
+ head_sha: "be3020c7",
+ old_path: "example.md",
+ new_path: "example.md",
+ position_type: "text",
+ old_line: 2,
+ new_line: 4,
+ line_range: {
+ start: {
+ line_code: "1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4",
+ type: nil,
+ old_line: 2,
+ new_line: 4
+ },
+ end: {
+ line_code: "1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4",
+ type: nil,
+ old_line: 2,
+ new_line: 4
+ }
+ }
+ }
+ } do |note|
+ note.position.to_h
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/issue.rb b/lib/api/entities/issue.rb
index 7630fd1e94e..56e942a0383 100644
--- a/lib/api/entities/issue.rb
+++ b/lib/api/entities/issue.rb
@@ -6,11 +6,11 @@ module API
include ::API::Helpers::RelatedResourcesHelpers
expose(:has_tasks) do |issue, _|
- !issue.task_list_items.empty?
+ !issue.tasks?
end
expose :task_status, if: -> (issue, _) do
- !issue.task_list_items.empty?
+ !issue.tasks?
end
expose :_links do
diff --git a/lib/api/entities/merge_request_basic.rb b/lib/api/entities/merge_request_basic.rb
index 27f6e6ade06..16afc6c1f6a 100644
--- a/lib/api/entities/merge_request_basic.rb
+++ b/lib/api/entities/merge_request_basic.rb
@@ -91,6 +91,7 @@ module API
end
expose :squash
+ expose :squash_on_merge?, as: :squash_on_merge
expose :task_completion_status
expose :cannot_be_merged?, as: :has_conflicts
expose :mergeable_discussions_state?, as: :blocking_discussions_resolved
diff --git a/lib/api/entities/packages/debian/distribution.rb b/lib/api/entities/packages/debian/distribution.rb
index a11f4337f38..82ee95c198b 100644
--- a/lib/api/entities/packages/debian/distribution.rb
+++ b/lib/api/entities/packages/debian/distribution.rb
@@ -6,7 +6,7 @@ module API
module Debian
class Distribution < Grape::Entity
expose :id, documentation: { type: 'integer', example: 1 }
- expose :codename, documentation: { type: 'string', example: 'unstable' }
+ expose :codename, documentation: { type: 'string', example: 'sid' }
expose :suite, documentation: { type: 'string', example: 'unstable' }
expose :origin, documentation: { type: 'string', example: 'Grep' }
expose :label, documentation: { type: 'string', example: 'grep.be' }
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index 37be6903d8b..fcb7ddb9567 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -88,6 +88,7 @@ module API
expose :emails_disabled, documentation: { type: 'boolean' }
expose :shared_runners_enabled, documentation: { type: 'boolean' }
+ expose :group_runners_enabled, documentation: { type: 'boolean' }
expose :lfs_enabled?, as: :lfs_enabled, documentation: { type: 'boolean' }
expose :creator_id, documentation: { type: 'integer', example: 1 }
expose :forked_from_project, using: Entities::BasicProjectDetails, if: ->(project, options) do
diff --git a/lib/api/entities/project_with_access.rb b/lib/api/entities/project_with_access.rb
index 9722b8806d4..47706165806 100644
--- a/lib/api/entities/project_with_access.rb
+++ b/lib/api/entities/project_with_access.rb
@@ -25,32 +25,10 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def self.preload_relation(projects_relation, options = {})
- if ::Feature.enabled?(:projects_preloader_fix)
- super(projects_relation, options)
- else
- relation = super(projects_relation, options)
- # use reselect to override the existing select and
- # prevent an error `subquery has too many columns`
- project_ids = relation.reselect('projects.id')
- namespace_ids = relation.reselect(:namespace_id)
-
- options[:project_members] = options[:current_user]
- .project_members
- .where(source_id: project_ids)
- .preload(:source, user: [notification_settings: :source])
-
- options[:group_members] = options[:current_user]
- .group_members
- .where(source_id: namespace_ids)
- .preload(:source, user: [notification_settings: :source])
-
- relation
- end
+ super(projects_relation, options)
end
def self.postload_relation(projects_relation, options = {})
- return unless ::Feature.enabled?(:projects_preloader_fix)
-
options[:project_members] = options[:current_user]
.project_members
.where(source_id: projects_relation.subquery(:id))
diff --git a/lib/api/entities/release.rb b/lib/api/entities/release.rb
index c1a48a46d64..4e4a500718f 100644
--- a/lib/api/entities/release.rb
+++ b/lib/api/entities/release.rb
@@ -28,8 +28,13 @@ module API
end
expose :evidences, using: Entities::Releases::Evidence, expose_nil: false, if: ->(_, _) { can_read_code? }
expose :_links do
- expose :self_url, as: :self, expose_nil: false
+ expose :closed_issues_url, expose_nil: false
+ expose :closed_merge_requests_url, expose_nil: false
expose :edit_url, expose_nil: false
+ expose :merged_merge_requests_url, expose_nil: false
+ expose :opened_issues_url, expose_nil: false
+ expose :opened_merge_requests_url, expose_nil: false
+ expose :self_url, as: :self, expose_nil: false
end
private
diff --git a/lib/api/entities/releases/link.rb b/lib/api/entities/releases/link.rb
index abf380e11d5..534510ec7e6 100644
--- a/lib/api/entities/releases/link.rb
+++ b/lib/api/entities/releases/link.rb
@@ -18,7 +18,7 @@ module API
} do |link|
::Releases::LinkPresenter.new(link).direct_asset_url
end
- expose :external?, documentation: { type: 'boolean' }, as: :external
+ expose :external?, documentation: { type: 'boolean' }, as: :external # @deprecated
expose :link_type, documentation: { type: 'string', example: 'other' }
end
end
diff --git a/lib/api/entities/user.rb b/lib/api/entities/user.rb
index a86039b856a..884f0f75d7a 100644
--- a/lib/api/entities/user.rb
+++ b/lib/api/entities/user.rb
@@ -7,7 +7,7 @@ module API
include TimeZoneHelper
expose :created_at, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) }
- expose :bio, :location, :public_email, :skype, :linkedin, :twitter, :website_url, :organization, :job_title, :pronouns
+ expose :bio, :location, :public_email, :skype, :linkedin, :twitter, :discord, :website_url, :organization, :job_title, :pronouns
expose :bot?, as: :bot
expose :work_information do |user|
work_information(user)
diff --git a/lib/api/entities/wiki_page.rb b/lib/api/entities/wiki_page.rb
index 07ef4a4a156..9d2a031cee8 100644
--- a/lib/api/entities/wiki_page.rb
+++ b/lib/api/entities/wiki_page.rb
@@ -25,3 +25,5 @@ module API
end
end
end
+
+API::Entities::WikiPage.prepend_mod
diff --git a/lib/api/events.rb b/lib/api/events.rb
index d3e8892f3bc..5428692e3ec 100644
--- a/lib/api/events.rb
+++ b/lib/api/events.rb
@@ -8,7 +8,7 @@ module API
allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
- feature_category :users
+ feature_category :user_profile
urgency :low
resource :events do
diff --git a/lib/api/group_debian_distributions.rb b/lib/api/group_debian_distributions.rb
index 8b6d4b8c4b2..9946199f7a8 100644
--- a/lib/api/group_debian_distributions.rb
+++ b/lib/api/group_debian_distributions.rb
@@ -6,10 +6,6 @@ module API
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the group'
end
- before do
- not_found! if Gitlab::FIPS.enabled?
- end
-
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
after_validation do
require_packages_enabled!
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 38430aac455..aadcbe38b15 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -504,12 +504,12 @@ module API
def render_validation_error!(model, status = 400)
if model.errors.any?
- render_api_error!(model_error_messages(model) || '400 Bad Request', status)
+ render_api_error!(model_errors(model).messages || '400 Bad Request', status)
end
end
- def model_error_messages(model)
- model.errors.messages
+ def model_errors(model)
+ model.errors
end
def render_api_error_with_reason!(status, message, reason)
@@ -608,7 +608,7 @@ module API
if file.file_storage?
present_disk_file!(file.path, file.filename)
elsif supports_direct_download && file.class.direct_download_enabled?
- return redirect(signed_head_url(file)) if head_request_on_aws_file?(file)
+ return redirect(ObjectStorage::S3.signed_head_url(file)) if request.head? && file.fog_credentials[:provider] == 'AWS'
redirect(cdn_fronted_url(file))
else
@@ -691,15 +691,7 @@ module API
{}
end
- def validate_anonymous_search_access!
- return if current_user.present? || Feature.disabled?(:disable_anonymous_search, type: :ops)
-
- unprocessable_entity!('User must be authenticated to use search')
- end
-
def validate_search_rate_limit!
- return unless Feature.enabled?(:rate_limit_issuable_searches)
-
if current_user
check_rate_limit!(:search_rate_limit, scope: [current_user])
else
@@ -709,19 +701,6 @@ module API
private
- def head_request_on_aws_file?(file)
- request.head? && file.fog_credentials[:provider] == 'AWS'
- end
-
- def signed_head_url(file)
- fog_storage = ::Fog::Storage.new(file.fog_credentials)
- fog_dir = fog_storage.directories.new(key: file.fog_directory)
- fog_file = fog_dir.files.new(key: file.path)
- expire_at = ::Fog::Time.now + file.fog_authenticated_url_expiration
-
- fog_file.collection.head_url(fog_file.key, expire_at)
- end
-
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def initial_current_user
return @initial_current_user if defined?(@initial_current_user)
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index 56db6ee4c5c..816b8deb461 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -58,7 +58,9 @@ module API
def log_user_activity(actor)
commands = Gitlab::GitAccess::DOWNLOAD_COMMANDS
- ::Users::ActivityService.new(actor).execute if commands.include?(params[:action])
+ return unless commands.include?(params[:action])
+
+ ::Users::ActivityService.new(author: actor, namespace: project&.namespace, project: project).execute
end
def redis_ping
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index b0ea4388d9b..4b34a2bbe79 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -11,6 +11,9 @@ module API
params :optional_state_filter_ee do
end
+ params :optional_put_params_ee do
+ end
+
def find_source(source_type, id)
public_send("find_#{source_type}!", id) # rubocop:disable GitlabSecurity/PublicSend
end
@@ -98,6 +101,10 @@ module API
user_id.present?
end
+ def self.member_access_levels
+ Gitlab::Access.all_values
+ end
+
private
def member_already_exists?(source, user_id)
diff --git a/lib/api/helpers/packages_helpers.rb b/lib/api/helpers/packages_helpers.rb
index 1d35c316913..0fb3a19b8fd 100644
--- a/lib/api/helpers/packages_helpers.rb
+++ b/lib/api/helpers/packages_helpers.rb
@@ -86,7 +86,9 @@ module API
end
def track_package_event(action, scope, **args)
- ::Packages::CreateEventService.new(nil, current_user, event_name: action, scope: scope).execute
+ service = ::Packages::CreateEventService.new(nil, current_user, event_name: action, scope: scope)
+ service.execute
+
category = args.delete(:category) || self.options[:for].name
event_name = "i_package_#{scope}_user"
::Gitlab::Tracking.event(
@@ -97,12 +99,40 @@ module API
context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event_name).to_context],
**args
)
+
+ return unless Feature.enabled?(:route_hll_to_snowplow_phase3)
+
+ if action.to_s == 'push_package' && service.originator_type == :deploy_token
+ track_snowplow_event("push_package_by_deploy_token", category, args)
+ elsif action.to_s == 'pull_package' && service.originator_type == :guest
+ track_snowplow_event("pull_package_by_guest", category, args)
+ end
end
def present_package_file!(package_file, supports_direct_download: true)
package_file.package.touch_last_downloaded_at
present_carrierwave_file!(package_file.file, supports_direct_download: supports_direct_download)
end
+
+ private
+
+ def track_snowplow_event(action_name, category, args)
+ event_name = "i_package_#{action_name}"
+ key_path = "counts.package_events_i_package_#{action_name}"
+ service_ping_context = Gitlab::Tracking::ServicePingContext.new(
+ data_source: :redis,
+ key_path: key_path
+ ).to_context
+
+ Gitlab::Tracking.event(
+ category,
+ action_name,
+ property: event_name,
+ label: key_path,
+ context: [service_ping_context],
+ **args
+ )
+ end
end
end
end
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index c5636fa06de..2700ea90d59 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -32,7 +32,7 @@ module API
optional :builds_access_level, type: String, values: %w(disabled private enabled), desc: 'Builds access level. One of `disabled`, `private` or `enabled`'
optional :snippets_access_level, type: String, values: %w(disabled private enabled), desc: 'Snippets access level. One of `disabled`, `private` or `enabled`'
optional :pages_access_level, type: String, values: %w(disabled private enabled public), desc: 'Pages access level. One of `disabled`, `private`, `enabled` or `public`'
- optional :operations_access_level, type: String, values: %w(disabled private enabled), desc: 'Operations access level. One of `disabled`, `private` or `enabled`'
+ optional :operations_access_level, type: String, values: %w(disabled private enabled), desc: 'Operations access level. One of `disabled`, `private` or `enabled`. Deprecated in GitLab 15.8, see https://gitlab.com/gitlab-org/gitlab/-/issues/385798.'
optional :analytics_access_level, type: String, values: %w(disabled private enabled), desc: 'Analytics access level. One of `disabled`, `private` or `enabled`'
optional :container_registry_access_level, type: String, values: %w(disabled private enabled), desc: 'Controls visibility of the container registry. One of `disabled`, `private` or `enabled`. `private` will make the container registry accessible only to project members (reporter role and above). `enabled` will make the container registry accessible to everyone who has access to the project. `disabled` will disable the container registry'
optional :security_and_compliance_access_level, type: String, values: %w(disabled private enabled), desc: 'Security and compliance access level. One of `disabled`, `private` or `enabled`'
@@ -48,6 +48,7 @@ module API
optional :warn_about_potentially_unwanted_characters, type: Boolean, desc: 'Warn about Potentially Unwanted Characters'
optional :enforce_auth_checks_on_uploads, type: Boolean, desc: 'Enforce auth check on uploads'
optional :shared_runners_enabled, type: Boolean, desc: 'Flag indication if shared runners are enabled for that project'
+ optional :group_runners_enabled, type: Boolean, desc: 'Flag indication if group runners are enabled for that project'
optional :resolve_outdated_diff_discussions, type: Boolean, desc: 'Automatically resolve merge request diff threads on lines changed with a push'
optional :remove_source_branch_after_merge, type: Boolean, desc: 'Remove the source branch by default after merge'
optional :container_registry_enabled, type: Boolean, desc: 'Deprecated: Use :container_registry_access_level instead. Flag indication if the container registry is enabled for that project'
@@ -170,6 +171,7 @@ module API
:security_and_compliance_access_level,
:squash_option,
:shared_runners_enabled,
+ :group_runners_enabled,
:snippets_access_level,
:tag_list,
:topics,
diff --git a/lib/api/helpers/users_helpers.rb b/lib/api/helpers/users_helpers.rb
index e80b89488a2..f97071d9a97 100644
--- a/lib/api/helpers/users_helpers.rb
+++ b/lib/api/helpers/users_helpers.rb
@@ -12,10 +12,14 @@ module API
params :optional_index_params_ee do
end
- def model_error_messages(model)
- super.tap do |error_messages|
+ def model_errors(model)
+ super.tap do |errors|
# Remapping errors from nested associations.
- error_messages[:bio] = error_messages.delete(:"user_detail.bio") if error_messages.has_key?(:"user_detail.bio")
+ next unless errors.has_key?(:"user_detail.bio")
+
+ errors.delete(:"user_detail.bio").each do |message|
+ errors.add(:bio, message)
+ end
end
end
diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb
index 777d5019a29..5f12275b7a0 100644
--- a/lib/api/internal/kubernetes.rb
+++ b/lib/api/internal/kubernetes.rb
@@ -118,7 +118,7 @@ module API
end
end
- namespace 'kubernetes/agent_configuration', urgency: :low do
+ namespace 'kubernetes/agent_configuration' do
desc 'POST agent configuration' do
detail 'Store configuration for an agent'
end
@@ -126,7 +126,7 @@ module API
requires :agent_id, type: Integer, desc: 'ID of the configured Agent'
requires :agent_config, type: JSON, desc: 'Configuration for the Agent'
end
- post '/', feature_category: :kubernetes_management do
+ post '/', feature_category: :kubernetes_management, urgency: :low do
agent = ::Clusters::Agent.find(params[:agent_id])
::Clusters::Agents::RefreshAuthorizationService.new(agent, config: params[:agent_config]).execute
diff --git a/lib/api/invitations.rb b/lib/api/invitations.rb
index 872dab26469..828f4b419ef 100644
--- a/lib/api/invitations.rb
+++ b/lib/api/invitations.rb
@@ -4,7 +4,7 @@ module API
class Invitations < ::API::Base
include PaginationParams
- feature_category :users
+ feature_category :user_profile
before { authenticate! }
@@ -21,7 +21,7 @@ module API
tags %w[invitations]
end
params do
- requires :access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'A valid access level (defaults: `30`, developer access level)'
+ requires :access_level, type: Integer, values: ::API::Helpers::MembersHelpers.member_access_levels, desc: 'A valid access level (defaults: `30`, developer access level)'
optional :email, type: Array[String], email_or_email_list: true, coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The email address to invite, or multiple emails separated by comma'
optional :user_id, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The user ID of the new member or multiple IDs separated by commas.'
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
diff --git a/lib/api/issue_links.rb b/lib/api/issue_links.rb
index 020b02248a0..4c79aa2587f 100644
--- a/lib/api/issue_links.rb
+++ b/lib/api/issue_links.rb
@@ -55,7 +55,7 @@ module API
requires :target_project_id, types: [String, Integer],
desc: 'The ID or URL-encoded path of a target project'
requires :target_issue_iid, types: [String, Integer], desc: 'The internal ID of a target project’s issue'
- optional :link_type, type: String, values: IssueLink.link_types.keys,
+ optional :link_type, type: String, values: IssueLink.available_link_types,
desc: 'The type of the relation (“relates_to”, “blocks”, “is_blocked_by”),'\
'defaults to “relates_to”)'
end
@@ -72,9 +72,7 @@ module API
.execute
if result[:status] == :success
- issue_link = IssueLink.find_by!(source: source_issue, target: target_issue)
-
- present issue_link, with: Entities::IssueLink
+ present result[:created_references].first, with: Entities::IssueLink
else
render_api_error!(result[:message], result[:http_status])
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 7b6306938cf..88e99b29587 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -115,7 +115,6 @@ module API
end
get '/issues_statistics' do
authenticate! unless params[:scope] == 'all'
- validate_anonymous_search_access! if params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
present issues_statistics, with: Grape::Presenters::Presenter
@@ -134,7 +133,6 @@ module API
end
get do
authenticate! unless params[:scope] == 'all'
- validate_anonymous_search_access! if params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
issues = paginate(find_issues)
@@ -174,7 +172,6 @@ module API
optional :non_archived, type: Boolean, desc: 'Return issues from non archived projects', default: true
end
get ":id/issues" do
- validate_anonymous_search_access! if declared_params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
issues = paginate(find_issues(group_id: user_group.id, include_subgroups: true))
@@ -194,7 +191,6 @@ module API
use :issues_stats_params
end
get ":id/issues_statistics" do
- validate_anonymous_search_access! if declared_params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
present issues_statistics(group_id: user_group.id, include_subgroups: true), with: Grape::Presenters::Presenter
@@ -214,7 +210,6 @@ module API
use :issues_params
end
get ":id/issues" do
- validate_anonymous_search_access! if declared_params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
issues = paginate(find_issues(project_id: user_project.id))
@@ -234,7 +229,6 @@ module API
use :issues_stats_params
end
get ":id/issues_statistics" do
- validate_anonymous_search_access! if declared_params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
present issues_statistics(project_id: user_project.id), with: Grape::Presenters::Presenter
@@ -278,7 +272,7 @@ module API
begin
spam_params = ::Spam::SpamParams.new_from_request(request: request)
- result = ::Issues::CreateService.new(project: user_project,
+ result = ::Issues::CreateService.new(container: user_project,
current_user: current_user,
params: issue_params,
spam_params: spam_params).execute
@@ -325,7 +319,7 @@ module API
update_params = convert_parameters_from_legacy_format(update_params)
spam_params = ::Spam::SpamParams.new_from_request(request: request)
- issue = ::Issues::UpdateService.new(project: user_project,
+ issue = ::Issues::UpdateService.new(container: user_project,
current_user: current_user,
params: update_params,
spam_params: spam_params).execute(issue)
@@ -356,7 +350,7 @@ module API
authorize! :update_issue, issue
- if ::Issues::ReorderService.new(project: user_project, current_user: current_user, params: params).execute(issue)
+ if ::Issues::ReorderService.new(container: user_project, current_user: current_user, params: params).execute(issue)
present issue, with: Entities::Issue, current_user: current_user, project: user_project
else
render_api_error!({ error: 'Unprocessable Entity' }, 422)
@@ -382,7 +376,7 @@ module API
not_found!('Project') unless new_project
begin
- issue = ::Issues::MoveService.new(project: user_project, current_user: current_user).execute(issue, new_project)
+ issue = ::Issues::MoveService.new(container: user_project, current_user: current_user).execute(issue, new_project)
present issue, with: Entities::Issue, current_user: current_user, project: user_project
rescue ::Issues::MoveService::MoveError => error
render_api_error!(error.message, 400)
@@ -409,7 +403,7 @@ module API
not_found!('Project') unless target_project
begin
- issue = ::Issues::CloneService.new(project: user_project, current_user: current_user)
+ issue = ::Issues::CloneService.new(container: user_project, current_user: current_user)
.execute(issue, target_project, with_notes: params[:with_notes])
present issue, with: Entities::Issue, current_user: current_user, project: target_project
rescue ::Issues::CloneService::CloneError => error
@@ -430,7 +424,7 @@ module API
authorize!(:destroy_issue, issue)
destroy_conditionally!(issue) do |issue|
- Issuable::DestroyService.new(project: user_project, current_user: current_user).execute(issue)
+ Issuable::DestroyService.new(container: user_project, current_user: current_user).execute(issue)
end
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -444,9 +438,10 @@ module API
get ':id/issues/:issue_iid/related_merge_requests' do
issue = find_project_issue(params[:issue_iid])
- merge_requests = ::Issues::ReferencedMergeRequestsService.new(project: user_project, current_user: current_user)
- .execute(issue)
- .first
+ merge_requests = ::Issues::ReferencedMergeRequestsService
+ .new(container: user_project, current_user: current_user)
+ .execute(issue)
+ .first
present paginate(::Kaminari.paginate_array(merge_requests)),
with: Entities::MergeRequest,
diff --git a/lib/api/members.rb b/lib/api/members.rb
index 32c5227a939..1e640a6542a 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -139,6 +139,7 @@ module API
requires :user_id, type: Integer, desc: 'The user ID of the new member'
requires :access_level, type: Integer, desc: 'A valid access level'
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
+ use :optional_put_params_ee
end
# rubocop: disable CodeReuse/ActiveRecord
put ":id/members/:user_id", feature_category: feature_category do
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 25fbeca01dc..cd46b442b68 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -140,7 +140,6 @@ module API
end
get feature_category: :code_review_workflow, urgency: :low do
authenticate! unless params[:scope] == 'all'
- validate_anonymous_search_access! if params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
merge_requests = find_merge_requests
@@ -169,7 +168,6 @@ module API
desc: 'Returns merge requests from non archived projects only.'
end
get ":id/merge_requests", feature_category: :code_review_workflow, urgency: :low do
- validate_anonymous_search_access! if declared_params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
merge_requests = find_merge_requests(group_id: user_group.id, include_subgroups: true)
@@ -237,7 +235,6 @@ module API
end
get ":id/merge_requests", feature_category: :code_review_workflow, urgency: :low do
authorize! :read_merge_request, user_project
- validate_anonymous_search_access! if declared_params[:search].present?
validate_search_rate_limit! if declared_params[:search].present?
merge_requests = find_merge_requests(project_id: user_project.id)
@@ -315,7 +312,7 @@ module API
authorize!(:destroy_merge_request, merge_request)
destroy_conditionally!(merge_request) do |merge_request|
- Issuable::DestroyService.new(project: user_project, current_user: current_user).execute(merge_request)
+ Issuable::DestroyService.new(container: user_project, current_user: current_user).execute(merge_request)
end
end
@@ -627,8 +624,9 @@ module API
merge_request = find_project_merge_request(params[:merge_request_iid])
- # Merge request can not be merged
- # because user dont have permissions to push into target branch
+ # Merge request can not be merged because the user doesn't have
+ # permissions to push into target branch
+ #
unauthorized! unless merge_request.can_be_merged_by?(current_user)
merge_when_pipeline_succeeds = to_boolean(params[:merge_when_pipeline_succeeds])
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
index 2b1007e715a..c971f73ccbb 100644
--- a/lib/api/namespaces.rb
+++ b/lib/api/namespaces.rb
@@ -81,13 +81,13 @@ module API
tags NAMESPACES_TAGS
end
params do
- requires :namespace, type: String, desc: "Namespace’s path"
+ requires :id, type: String, desc: "Namespace’s path"
optional :parent_id, type: Integer, desc: 'The ID of the parent namespace. If no ID is specified, only top-level namespaces are considered.'
end
- get ':namespace/exists', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS, feature_category: :subgroups, urgency: :low do
+ get ':id/exists', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS, feature_category: :subgroups, urgency: :low do
check_rate_limit!(:namespace_exists, scope: current_user)
- namespace_path = params[:namespace]
+ namespace_path = params[:id]
existing_namespaces_within_the_parent = Namespace.without_project_namespaces.by_parent(params[:parent_id])
exists = existing_namespaces_within_the_parent.filter_by_path(namespace_path).exists?
diff --git a/lib/api/pages_domains.rb b/lib/api/pages_domains.rb
index 15c1a78839f..db156186458 100644
--- a/lib/api/pages_domains.rb
+++ b/lib/api/pages_domains.rb
@@ -94,7 +94,7 @@ module API
end
params do
requires :domain, type: String, desc: 'The domain'
- # rubocop:disable Scalability/FileUploads
+ # rubocop:todo Scalability/FileUploads
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
optional :certificate, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
optional :key, types: [File, String], desc: 'The key', as: :user_provided_key
@@ -122,7 +122,7 @@ module API
desc 'Updates a pages domain'
params do
requires :domain, type: String, desc: 'The domain'
- # rubocop:disable Scalability/FileUploads
+ # rubocop:todo Scalability/FileUploads
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
optional :certificate, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
optional :key, types: [File, String], desc: 'The key', as: :user_provided_key
diff --git a/lib/api/project_container_repositories.rb b/lib/api/project_container_repositories.rb
index e5e6ccdf025..0f4f1dc7fa6 100644
--- a/lib/api/project_container_repositories.rb
+++ b/lib/api/project_container_repositories.rb
@@ -12,7 +12,7 @@ module API
before { authorize_read_container_images! }
- feature_category :package_registry
+ feature_category :container_registry
urgency :low
params do
diff --git a/lib/api/project_debian_distributions.rb b/lib/api/project_debian_distributions.rb
index 856b4097b5a..fc94107f88d 100644
--- a/lib/api/project_debian_distributions.rb
+++ b/lib/api/project_debian_distributions.rb
@@ -6,10 +6,6 @@ module API
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
end
- before do
- not_found! if Gitlab::FIPS.enabled?
- end
-
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
after_validation do
require_packages_enabled!
diff --git a/lib/api/project_events.rb b/lib/api/project_events.rb
index d90ce32c354..3e651cdda44 100644
--- a/lib/api/project_events.rb
+++ b/lib/api/project_events.rb
@@ -6,7 +6,7 @@ module API
include APIGuard
helpers ::API::Helpers::EventsHelpers
- feature_category :users
+ feature_category :user_profile
# TODO: Set higher urgency after resolving https://gitlab.com/gitlab-org/gitlab/-/issues/357839
urgency :low
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 5077f02fcc1..6eea56ea117 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -9,7 +9,11 @@ module API
before { authenticate_non_get! }
- feature_category :projects, ['/projects/:id/custom_attributes', '/projects/:id/custom_attributes/:key']
+ feature_category :projects, %w[
+ /projects/:id/custom_attributes
+ /projects/:id/custom_attributes/:key
+ /projects/:id/share_locations
+ ]
PROJECT_ATTACHMENT_SIZE_EXEMPT = 1.gigabyte
@@ -351,6 +355,20 @@ module API
render_validation_error!(project)
end
end
+
+ desc 'Returns group that can be shared with the given project' do
+ success Entities::Group
+ end
+ params do
+ requires :id, type: Integer, desc: 'The id of the project'
+ optional :search, type: String, desc: 'Return list of groups matching the search criteria'
+ end
+ get ':id/share_locations' do
+ groups = ::Groups::AcceptingProjectSharesFinder.new(current_user, user_project, declared_params(include_missing: false)).execute
+
+ present_groups groups
+ end
+
# rubocop: enable CodeReuse/ActiveRecord
end
@@ -850,11 +868,23 @@ module API
]
tags %w[projects]
end
+ params do
+ optional :task, type: Symbol, default: :eager, values: %i[eager prune], desc: '`prune` to trigger manual prune of unreachable objects or `eager` to trigger eager housekeeping.'
+ end
post ':id/housekeeping', feature_category: :source_code_management do
authorize_admin_project
begin
- ::Repositories::HousekeepingService.new(user_project, :gc).execute
+ ::Repositories::HousekeepingService.new(user_project, params[:task]).execute do
+ ::Gitlab::Audit::Auditor.audit(
+ name: 'manually_trigger_housekeeping',
+ author: current_user,
+ scope: user_project,
+ target: user_project,
+ message: "Housekeeping task: #{params[:task]}",
+ created_at: DateTime.current
+ )
+ end
rescue ::Repositories::HousekeepingService::LeaseTaken => error
conflict!(error.message)
end
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index e69dc756551..ebf1c03e86b 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -246,8 +246,14 @@ module API
optional :milestones,
type: Array[String],
coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
- desc: 'The title of each milestone the release is associated with. GitLab Premium customers can specify group milestones',
- default: []
+ desc: 'The title of each milestone the release is associated with. GitLab Premium customers can specify group milestones. Cannot be combined with `milestone_ids` parameter.'
+
+ optional :milestone_ids,
+ type: Array[String, Integer],
+ coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce,
+ desc: 'The ID of each milestone the release is associated with. GitLab Premium customers can specify group milestones. Cannot be combined with `milestones` parameter.'
+
+ mutually_exclusive :milestones, :milestone_ids, message: 'Cannot specify milestones and milestone_ids at the same time'
optional :released_at,
type: DateTime,
@@ -292,7 +298,14 @@ module API
optional :milestones,
type: Array[String],
coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
- desc: 'The title of each milestone to associate with the release. GitLab Premium customers can specify group milestones. To remove all milestones from the release, specify `[]`'
+ desc: 'The title of each milestone to associate with the release. GitLab Premium customers can specify group milestones. Cannot be combined with `milestone_ids` parameter. To remove all milestones from the release, specify `[]`'
+
+ optional :milestone_ids,
+ type: Array[String, Integer],
+ coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce,
+ desc: 'The ID of each milestone the release is associated with. GitLab Premium customers can specify group milestones. Cannot be combined with `milestones` parameter. To remove all milestones from the release, specify `[]`'
+
+ mutually_exclusive :milestones, :milestone_ids, message: 'Cannot specify milestones and milestone_ids at the same time'
end
route_setting :authentication, job_token_allowed: true
put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index 06b576a982b..8efb848eb57 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -191,8 +191,8 @@ module API
optional :group_runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for group runners, in seconds'
optional :project_runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for project runners, in seconds'
optional :pipeline_limit_per_project_user_sha, type: Integer, desc: "Maximum number of pipeline creation requests allowed per minute per user and commit. Set to 0 for unlimited requests per minute."
- optional :jira_connect_application_key, type: String, desc: "Application ID of the OAuth application that should be used to authenticate with the GitLab.com for Jira Cloud app"
- optional :jira_connect_proxy_url, type: String, desc: "URL of the GitLab instance that should be used as a proxy for the GitLab.com for Jira Cloud app"
+ optional :jira_connect_application_key, type: String, desc: "Application ID of the OAuth application that should be used to authenticate with the GitLab for Jira Cloud app"
+ optional :jira_connect_proxy_url, type: String, desc: "URL of the GitLab instance that should be used as a proxy for the GitLab for Jira Cloud app"
optional :bulk_import_enabled, type: Boolean, desc: 'Enable migrating GitLab groups and projects by direct transfer'
optional :allow_runner_registration_token, type: Boolean, desc: 'Allow registering runners using a registration token'
diff --git a/lib/api/time_tracking_endpoints.rb b/lib/api/time_tracking_endpoints.rb
index dd8ad2cc144..3534edc3831 100644
--- a/lib/api/time_tracking_endpoints.rb
+++ b/lib/api/time_tracking_endpoints.rb
@@ -35,7 +35,9 @@ module API
custom_params = declared_params(include_missing: false)
custom_params.merge!(attrs)
- issuable = update_service.new(project: user_project, current_user: current_user, params: custom_params).execute(load_issuable)
+ issuable = update_service.new(**update_service.constructor_container_arg(user_project),
+ current_user: current_user, params: custom_params).execute(load_issuable)
+
if issuable.valid?
present issuable, with: Entities::IssuableTimeStats
else
diff --git a/lib/api/users.rb b/lib/api/users.rb
index a9b09596728..cc7eb63798a 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -8,7 +8,7 @@ module API
allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
- feature_category :users,
+ feature_category :user_profile,
%w[
/users/:id/custom_attributes
/users/:id/custom_attributes/:key
@@ -46,6 +46,7 @@ module API
optional :skype, type: String, desc: 'The Skype username'
optional :linkedin, type: String, desc: 'The LinkedIn username'
optional :twitter, type: String, desc: 'The Twitter username'
+ optional :discord, type: String, desc: 'The Discord user ID'
optional :website_url, type: String, desc: 'The website of the user'
optional :organization, type: String, desc: 'The organization of the user'
optional :projects_limit, type: Integer, desc: 'The number of projects a user can create'
@@ -131,7 +132,7 @@ module API
use :optional_index_params_ee
end
# rubocop: disable CodeReuse/ActiveRecord
- get feature_category: :users, urgency: :low do
+ get feature_category: :user_profile, urgency: :low do
authenticated_as_admin! if params[:extern_uid].present? && params[:provider].present?
unless current_user&.can_read_all_resources?
@@ -175,7 +176,7 @@ module API
use :with_custom_attributes
end
# rubocop: disable CodeReuse/ActiveRecord
- get ":id", feature_category: :users, urgency: :low do
+ get ":id", feature_category: :user_profile, urgency: :low do
forbidden!('Not authorized!') unless current_user
unless current_user.can_read_all_resources?
@@ -200,7 +201,7 @@ module API
params do
requires :user_id, type: String, desc: 'The ID or username of the user'
end
- get ":user_id/status", requirements: API::USER_REQUIREMENTS, feature_category: :users, urgency: :default do
+ get ":user_id/status", requirements: API::USER_REQUIREMENTS, feature_category: :user_profile, urgency: :default do
user = find_user(params[:user_id])
not_found!('User') unless user && can?(current_user, :read_user, user)
@@ -214,7 +215,7 @@ module API
params do
requires :id, type: Integer, desc: 'The ID of the user'
end
- post ':id/follow', feature_category: :users do
+ post ':id/follow', feature_category: :user_profile do
user = find_user(params[:id])
not_found!('User') unless user
@@ -234,7 +235,7 @@ module API
params do
requires :id, type: Integer, desc: 'The ID of the user'
end
- post ':id/unfollow', feature_category: :users do
+ post ':id/unfollow', feature_category: :user_profile do
user = find_user(params[:id])
not_found!('User') unless user
@@ -252,7 +253,7 @@ module API
requires :id, type: Integer, desc: 'The ID of the user'
use :pagination
end
- get ':id/following', feature_category: :users do
+ get ':id/following', feature_category: :user_profile do
forbidden!('Not authorized!') unless current_user
user = find_user(params[:id])
@@ -268,7 +269,7 @@ module API
requires :id, type: Integer, desc: 'The ID of the user'
use :pagination
end
- get ':id/followers', feature_category: :users do
+ get ':id/followers', feature_category: :user_profile do
forbidden!('Not authorized!') unless current_user
user = find_user(params[:id])
@@ -291,7 +292,7 @@ module API
optional :force_random_password, type: Boolean, desc: 'Flag indicating a random password will be set'
use :optional_attributes
end
- post feature_category: :users do
+ post feature_category: :user_profile do
authenticated_as_admin!
params = declared_params(include_missing: false)
@@ -333,7 +334,7 @@ module API
use :optional_attributes
end
# rubocop: disable CodeReuse/ActiveRecord
- put ":id", feature_category: :users do
+ put ":id", feature_category: :user_profile do
authenticated_as_admin!
user = User.find_by(id: params.delete(:id))
@@ -644,7 +645,7 @@ module API
optional :skip_confirmation, type: Boolean, desc: 'Skip confirmation of email and assume it is verified'
end
# rubocop: disable CodeReuse/ActiveRecord
- post ":id/emails", feature_category: :users do
+ post ":id/emails", feature_category: :user_profile do
authenticated_as_admin!
user = User.find_by(id: params.delete(:id))
@@ -668,7 +669,7 @@ module API
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
- get ':id/emails', feature_category: :users do
+ get ':id/emails', feature_category: :user_profile do
authenticated_as_admin!
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -685,7 +686,7 @@ module API
requires :email_id, type: Integer, desc: 'The ID of the email'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ':id/emails/:email_id', feature_category: :users do
+ delete ':id/emails/:email_id', feature_category: :user_profile do
authenticated_as_admin!
user = User.find_by(id: params[:id])
not_found!('User') unless user
@@ -707,7 +708,7 @@ module API
optional :hard_delete, type: Boolean, desc: "Whether to remove a user's contributions"
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ":id", feature_category: :users do
+ delete ":id", feature_category: :user_profile do
authenticated_as_admin!
user = User.find_by(id: params[:id])
@@ -883,7 +884,7 @@ module API
optional :type, type: String, values: %w[Project Namespace]
use :pagination
end
- get ":user_id/memberships", feature_category: :users, urgency: :high do
+ get ":user_id/memberships", feature_category: :user_profile, urgency: :high do
authenticated_as_admin!
user = find_user_by_id(params)
@@ -1021,7 +1022,7 @@ module API
desc 'Get the currently authenticated user' do
success Entities::UserPublic
end
- get feature_category: :users, urgency: :low do
+ get feature_category: :user_profile, urgency: :low do
entity =
# We're disabling Cop/UserAdmin because it checks if the given user is an admin.
if current_user.admin? # rubocop:disable Cop/UserAdmin
@@ -1202,7 +1203,7 @@ module API
params do
use :pagination
end
- get "emails", feature_category: :users, urgency: :high do
+ get "emails", feature_category: :user_profile, urgency: :high do
present paginate(current_user.emails), with: Entities::Email
end
@@ -1244,7 +1245,7 @@ module API
optional :show_whitespace_in_diffs, type: Boolean, desc: 'Flag indicating the user sees whitespace changes in diffs'
at_least_one_of :view_diffs_file_by_file, :show_whitespace_in_diffs
end
- put "preferences", feature_category: :users, urgency: :high do
+ put "preferences", feature_category: :user_profile, urgency: :high do
authenticate!
preferences = current_user.user_preference
@@ -1263,7 +1264,7 @@ module API
success Entities::UserPreferences
detail 'This feature was introduced in GitLab 14.0.'
end
- get "preferences", feature_category: :users do
+ get "preferences", feature_category: :user_profile do
present current_user.user_preference, with: Entities::UserPreferences
end
@@ -1274,7 +1275,7 @@ module API
requires :email_id, type: Integer, desc: 'The ID of the email'
end
# rubocop: disable CodeReuse/ActiveRecord
- get "emails/:email_id", feature_category: :users do
+ get "emails/:email_id", feature_category: :user_profile do
email = current_user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
@@ -1288,7 +1289,7 @@ module API
params do
requires :email, type: String, desc: 'The new email'
end
- post "emails", feature_category: :users do
+ post "emails", feature_category: :user_profile do
email = Emails::CreateService.new(current_user, declared_params.merge(user: current_user)).execute
if email.errors.blank?
@@ -1303,7 +1304,7 @@ module API
requires :email_id, type: Integer, desc: 'The ID of the email'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete "emails/:email_id", feature_category: :users do
+ delete "emails/:email_id", feature_category: :user_profile do
email = current_user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
@@ -1319,7 +1320,7 @@ module API
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
- get "activities", feature_category: :users do
+ get "activities", feature_category: :user_profile do
authenticated_as_admin!
activities = User
@@ -1337,7 +1338,7 @@ module API
params do
use :set_user_status_params
end
- put "status", feature_category: :users do
+ put "status", feature_category: :user_profile do
set_user_status(include_missing_params: true)
end
@@ -1348,7 +1349,7 @@ module API
params do
use :set_user_status_params
end
- patch "status", feature_category: :users do
+ patch "status", feature_category: :user_profile do
if declared_params(include_missing: false).empty?
status :ok
@@ -1361,7 +1362,7 @@ module API
desc 'get the status of the current user' do
success Entities::UserStatus
end
- get 'status', feature_category: :users do
+ get 'status', feature_category: :user_profile do
present current_user.status || {}, with: Entities::UserStatus
end
end
diff --git a/lib/api/validations/validators/bulk_imports.rb b/lib/api/validations/validators/bulk_imports.rb
index 8d49607f64c..4625f2f39cd 100644
--- a/lib/api/validations/validators/bulk_imports.rb
+++ b/lib/api/validations/validators/bulk_imports.rb
@@ -21,7 +21,7 @@ module API
def validate_param!(attr_name, params)
return if params[attr_name].blank?
- unless params[attr_name] =~ Gitlab::Regex.bulk_import_namespace_path_regex # rubocop: disable Style/GuardClause
+ unless params[attr_name] =~ Gitlab::Regex.bulk_import_destination_namespace_path_regex # rubocop: disable Style/GuardClause
raise Grape::Exceptions::Validation.new(
params: [@scope.full_name(attr_name)],
message: "cannot start with a dash or forward slash, or end with a period or forward slash. " \
@@ -34,7 +34,7 @@ module API
class SourceFullPath < Grape::Validations::Base
def validate_param!(attr_name, params)
- unless params[attr_name] =~ Gitlab::Regex.bulk_import_namespace_path_regex # rubocop: disable Style/GuardClause
+ unless params[attr_name] =~ Gitlab::Regex.bulk_import_source_full_path_regex # rubocop: disable Style/GuardClause
raise Grape::Exceptions::Validation.new(
params: [@scope.full_name(attr_name)],
message: "must be a relative path and not include protocol, sub-domain, or domain information. " \