Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib/api
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-02-18 12:45:46 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-18 12:45:46 +0300
commita7b3560714b4d9cc4ab32dffcd1f74a284b93580 (patch)
tree7452bd5c3545c2fa67a28aa013835fb4fa071baf /lib/api
parentee9173579ae56a3dbfe5afe9f9410c65bb327ca7 (diff)
Add latest changes from gitlab-org/gitlab@14-8-stable-eev14.8.0-rc42
Diffstat (limited to 'lib/api')
-rw-r--r--lib/api/api.rb6
-rw-r--r--lib/api/branches.rb6
-rw-r--r--lib/api/ci/job_artifacts.rb4
-rw-r--r--lib/api/ci/pipelines.rb2
-rw-r--r--lib/api/ci/runner.rb29
-rw-r--r--lib/api/ci/runners.rb39
-rw-r--r--lib/api/ci/secure_files.rb98
-rw-r--r--lib/api/deployments.rb12
-rw-r--r--lib/api/discussions.rb2
-rw-r--r--lib/api/entities/ci/reset_token_result.rb3
-rw-r--r--lib/api/entities/ci/runner.rb5
-rw-r--r--lib/api/entities/ci/runner_details.rb8
-rw-r--r--lib/api/entities/ci/runner_registration_details.rb2
-rw-r--r--lib/api/entities/ci/secure_file.rb15
-rw-r--r--lib/api/entities/deployment_extended.rb10
-rw-r--r--lib/api/entities/user_safe.rb2
-rw-r--r--lib/api/groups.rb11
-rw-r--r--lib/api/helpers.rb4
-rw-r--r--lib/api/helpers/container_registry_helpers.rb2
-rw-r--r--lib/api/helpers/integrations_helpers.rb8
-rw-r--r--lib/api/helpers/internal_helpers.rb3
-rw-r--r--lib/api/helpers/members_helpers.rb2
-rw-r--r--lib/api/helpers/merge_requests_helpers.rb20
-rw-r--r--lib/api/helpers/rate_limiter.rb2
-rw-r--r--lib/api/internal/container_registry/migration.rb63
-rw-r--r--lib/api/issues.rb2
-rw-r--r--lib/api/lint.rb11
-rw-r--r--lib/api/merge_requests.rb9
-rw-r--r--lib/api/package_files.rb18
-rw-r--r--lib/api/pagination_params.rb2
-rw-r--r--lib/api/project_import.rb2
-rw-r--r--lib/api/projects_relation_builder.rb1
-rw-r--r--lib/api/repositories.rb3
-rw-r--r--lib/api/rubygem_packages.rb4
-rw-r--r--lib/api/scope.rb1
-rw-r--r--lib/api/settings.rb4
-rw-r--r--lib/api/support/token_with_expiration.rb24
-rw-r--r--lib/api/tags.rb6
-rw-r--r--lib/api/terraform/modules/v1/packages.rb8
-rw-r--r--lib/api/usage_data_non_sql_metrics.rb2
-rw-r--r--lib/api/usage_data_queries.rb2
-rw-r--r--lib/api/users.rb7
42 files changed, 356 insertions, 108 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 5984879413f..5100ec9ec9d 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -76,6 +76,10 @@ module API
Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
end
+ after do
+ Gitlab::UsageDataCounters::JetBrainsPluginActivityUniqueCounter.track_api_request_when_trackable(user_agent: request&.user_agent, user: @current_user)
+ end
+
# The locale is set to the current user's locale when `current_user` is loaded
after { Gitlab::I18n.use_default_locale }
@@ -171,6 +175,7 @@ module API
mount ::API::Ci::ResourceGroups
mount ::API::Ci::Runner
mount ::API::Ci::Runners
+ mount ::API::Ci::SecureFiles
mount ::API::Ci::Triggers
mount ::API::Ci::Variables
mount ::API::Commits
@@ -300,6 +305,7 @@ module API
mount ::API::Internal::Pages
mount ::API::Internal::Kubernetes
mount ::API::Internal::MailRoom
+ mount ::API::Internal::ContainerRegistry::Migration
version 'v3', using: :path do
# Although the following endpoints are kept behind V3 namespace,
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 462c4a3de4c..a2c9020ac84 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -24,7 +24,7 @@ module API
helpers do
params :filter_params do
optional :search, type: String, desc: 'Return list of branches matching the search criteria'
- optional :sort, type: String, desc: 'Return list of branches sorted by the given field'
+ optional :sort, type: String, desc: 'Return list of branches sorted by the given field', values: %w[name_asc updated_asc updated_desc]
end
end
@@ -42,9 +42,7 @@ module API
optional :page_token, type: String, desc: 'Name of branch to start the paginaition from'
end
get ':id/repository/branches', urgency: :low do
- ff_enabled = Feature.enabled?(:api_caching_rate_limit_branches, user_project, default_enabled: :yaml)
-
- cache_action_if(ff_enabled, [user_project, :branches, current_user, declared_params], expires_in: 30.seconds) do
+ cache_action([user_project, :branches, current_user, declared_params], expires_in: 30.seconds) do
user_project.preload_protected_branches
repository = user_project.repository
diff --git a/lib/api/ci/job_artifacts.rb b/lib/api/ci/job_artifacts.rb
index ca76d2664f8..9f59eea5013 100644
--- a/lib/api/ci/job_artifacts.rb
+++ b/lib/api/ci/job_artifacts.rb
@@ -47,7 +47,7 @@ module API
requires :artifact_path, type: String, desc: 'Artifact path'
end
route_setting :authentication, job_token_allowed: true
- get ':id/jobs/artifacts/:ref_name/raw/*artifact_path',
+ get ':id/jobs/artifacts/:ref_name/raw/*artifact_path', urgency: :low,
format: false,
requirements: { ref_name: /.+/ } do
authorize_download_artifacts!
@@ -70,7 +70,7 @@ module API
requires :job_id, type: Integer, desc: 'The ID of a job'
end
route_setting :authentication, job_token_allowed: true
- get ':id/jobs/:job_id/artifacts' do
+ get ':id/jobs/:job_id/artifacts', urgency: :low do
authorize_download_artifacts!
build = find_build!(params[:job_id])
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index 4e5d6c264bf..e0086f624a8 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -179,7 +179,7 @@ module API
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end
- get ':id/pipelines/:pipeline_id/test_report', feature_category: :code_testing do
+ get ':id/pipelines/:pipeline_id/test_report', feature_category: :code_testing, urgency: :low do
authorize! :read_build, pipeline
present pipeline.test_reports, with: TestReportEntity, details: true
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index fef6a7891c2..4df9600322c 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -15,20 +15,29 @@ module API
params do
requires :token, type: String, desc: 'Registration token'
optional :description, type: String, desc: %q(Runner's description)
- optional :maintainer_note, type: String, desc: %q(Runner's maintainer notes)
+ optional :maintainer_note, type: String, desc: %q(Deprecated: Use :maintenance_note instead. Runner's maintenance notes)
+ optional :maintenance_note, type: String, desc: %q(Runner's maintenance notes)
optional :info, type: Hash, desc: %q(Runner's metadata)
- optional :active, type: Boolean, desc: 'Should Runner be active'
- optional :locked, type: Boolean, desc: 'Should Runner be locked for current project'
+ optional :active, type: Boolean, desc: 'Deprecated: Use `:paused` instead. Should runner be active'
+ optional :paused, type: Boolean, desc: 'Whether the runner should ignore new jobs'
+ optional :locked, type: Boolean, desc: 'Whether the runner should be locked for current project'
optional :access_level, type: String, values: ::Ci::Runner.access_levels.keys,
- desc: 'The access_level of the runner'
- optional :run_untagged, type: Boolean, desc: 'Should Runner handle untagged jobs'
+ desc: 'The access_level of the runner; `not_protected` or `ref_protected`'
+ optional :run_untagged, type: Boolean, desc: 'Whether the runner should handle untagged jobs'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: %q(List of Runner's tags)
- optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job'
+ optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this runner handles the job'
+ mutually_exclusive :maintainer_note, :maintainer_note
+ mutually_exclusive :active, :paused
end
post '/', feature_category: :runner do
- attributes = attributes_for_keys(%i[description maintainer_note active locked run_untagged tag_list access_level maximum_timeout])
+ attributes = attributes_for_keys(%i[description maintainer_note maintenance_note active paused locked run_untagged tag_list access_level maximum_timeout])
.merge(get_runner_details_from_request)
+ # Pull in deprecated maintainer_note if that's the only note value available
+ deprecated_note = attributes.delete(:maintainer_note)
+ attributes[:maintenance_note] ||= deprecated_note if deprecated_note
+ attributes[:active] = !attributes.delete(:paused) if attributes.include?(:paused)
+
@runner = ::Ci::RegisterRunnerService.new.execute(params[:token], attributes)
forbidden! unless @runner
@@ -48,7 +57,7 @@ module API
delete '/', feature_category: :runner do
authenticate_runner!
- destroy_conditionally!(current_runner)
+ destroy_conditionally!(current_runner) { ::Ci::UnregisterRunnerService.new(current_runner).execute }
end
desc 'Validates authentication credentials' do
@@ -235,7 +244,7 @@ module API
optional :artifact_type, type: String, desc: %q(The type of artifact),
default: 'archive', values: ::Ci::JobArtifact.file_types.keys
end
- post '/:id/artifacts/authorize', feature_category: :build_artifacts do
+ post '/:id/artifacts/authorize', feature_category: :build_artifacts, urgency: :low do
not_allowed! unless Gitlab.config.artifacts.enabled
require_gitlab_workhorse!
@@ -271,7 +280,7 @@ module API
default: 'zip', values: ::Ci::JobArtifact.file_formats.keys
optional :metadata, type: ::API::Validations::Types::WorkhorseFile, desc: %(The artifact metadata to store (generated by Multipart middleware))
end
- post '/:id/artifacts', feature_category: :build_artifacts do
+ post '/:id/artifacts', feature_category: :build_artifacts, urgency: :low do
not_allowed! unless Gitlab.config.artifacts.enabled
require_gitlab_workhorse!
diff --git a/lib/api/ci/runners.rb b/lib/api/ci/runners.rb
index f21782a698f..8a7ffab97dd 100644
--- a/lib/api/ci/runners.rb
+++ b/lib/api/ci/runners.rb
@@ -18,6 +18,7 @@ module API
desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
+ optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
@@ -26,9 +27,7 @@ module API
get do
runners = current_user.ci_owned_runners
runners = filter_runners(runners, params[:scope], allowed_scopes: ::Ci::Runner::AVAILABLE_STATUSES)
- runners = filter_runners(runners, params[:type], allowed_scopes: ::Ci::Runner::AVAILABLE_TYPES)
- runners = filter_runners(runners, params[:status], allowed_scopes: ::Ci::Runner::AVAILABLE_STATUSES)
- runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
+ runners = apply_filter(runners, params)
present paginate(runners), with: Entities::Ci::Runner
end
@@ -41,6 +40,7 @@ module API
desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
+ optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
@@ -51,9 +51,7 @@ module API
runners = ::Ci::Runner.all
runners = filter_runners(runners, params[:scope])
- runners = filter_runners(runners, params[:type], allowed_scopes: ::Ci::Runner::AVAILABLE_TYPES)
- runners = filter_runners(runners, params[:status], allowed_scopes: ::Ci::Runner::AVAILABLE_STATUSES)
- runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
+ runners = apply_filter(runners, params)
present paginate(runners), with: Entities::Ci::Runner
end
@@ -77,18 +75,21 @@ module API
params do
requires :id, type: Integer, desc: 'The ID of the runner'
optional :description, type: String, desc: 'The description of the runner'
- optional :active, type: Boolean, desc: 'The state of a runner'
+ optional :active, type: Boolean, desc: 'Deprecated: Use `:paused` instead. Flag indicating whether the runner is allowed to receive jobs'
+ optional :paused, type: Boolean, desc: 'Flag indicating whether the runner should ignore new jobs'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The list of tags for a runner'
- optional :run_untagged, type: Boolean, desc: 'Flag indicating the runner can execute untagged jobs'
+ optional :run_untagged, type: Boolean, desc: 'Flag indicating whether the runner can execute untagged jobs'
optional :locked, type: Boolean, desc: 'Flag indicating the runner is locked'
optional :access_level, type: String, values: ::Ci::Runner.access_levels.keys,
desc: 'The access_level of the runner'
optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job'
- at_least_one_of :description, :active, :tag_list, :run_untagged, :locked, :access_level, :maximum_timeout
+ at_least_one_of :description, :active, :paused, :tag_list, :run_untagged, :locked, :access_level, :maximum_timeout
+ mutually_exclusive :active, :paused
end
put ':id' do
runner = get_runner(params.delete(:id))
authenticate_update_runner!(runner)
+ params[:active] = !params.delete(:paused) if params.include?(:paused)
update_service = ::Ci::UpdateRunnerService.new(runner)
if update_service.update(declared_params(include_missing: false))
@@ -109,7 +110,7 @@ module API
authenticate_delete_runner!(runner)
- destroy_conditionally!(runner)
+ destroy_conditionally!(runner) { ::Ci::UnregisterRunnerService.new(runner).execute }
end
desc 'List jobs running on a runner' do
@@ -142,7 +143,7 @@ module API
authenticate_update_runner!(runner)
runner.reset_token!
- present runner.token, with: Entities::Ci::ResetTokenResult
+ present runner.token_with_expiration, with: Entities::Ci::ResetTokenResult
end
end
@@ -160,6 +161,7 @@ module API
desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
+ optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
@@ -223,18 +225,14 @@ module API
params do
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
+ optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
use :pagination
end
get ':id/runners' do
- runners = if ::Feature.enabled?(:ci_find_runners_by_ci_mirrors, user_group, default_enabled: :yaml)
- ::Ci::Runner.belonging_to_group_and_ancestors(user_group.id)
- else
- ::Ci::Runner.legacy_belonging_to_group(user_group.id, include_ancestors: true)
- end
-
+ runners = ::Ci::Runner.group_or_instance_wide(user_group)
runners = apply_filter(runners, params)
present paginate(runners), with: Entities::Ci::Runner
@@ -251,7 +249,7 @@ module API
authorize! :update_runners_registration_token
ApplicationSetting.current.reset_runners_registration_token!
- present ApplicationSetting.current_without_cache.runners_registration_token, with: Entities::Ci::ResetTokenResult
+ present ApplicationSetting.current_without_cache.runners_registration_token_with_expiration, with: Entities::Ci::ResetTokenResult
end
end
@@ -269,7 +267,7 @@ module API
authorize! :update_runners_registration_token, project
project.reset_runners_token!
- present project.runners_token, with: Entities::Ci::ResetTokenResult
+ present project.runners_token_with_expiration, with: Entities::Ci::ResetTokenResult
end
end
@@ -287,7 +285,7 @@ module API
authorize! :update_runners_registration_token, group
group.reset_runners_token!
- present group.runners_token, with: Entities::Ci::ResetTokenResult
+ present group.runners_token_with_expiration, with: Entities::Ci::ResetTokenResult
end
end
@@ -310,6 +308,7 @@ module API
def apply_filter(runners, params)
runners = filter_runners(runners, params[:type], allowed_scopes: ::Ci::Runner::AVAILABLE_TYPES)
runners = filter_runners(runners, params[:status], allowed_scopes: ::Ci::Runner::AVAILABLE_STATUSES)
+ runners = filter_runners(runners, params[:paused] ? 'paused' : 'active', allowed_scopes: %w[paused active]) if params.include?(:paused)
runners = runners.tagged_with(params[:tag_list]) if params[:tag_list]
runners
diff --git a/lib/api/ci/secure_files.rb b/lib/api/ci/secure_files.rb
new file mode 100644
index 00000000000..715a8b37fae
--- /dev/null
+++ b/lib/api/ci/secure_files.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+module API
+ module Ci
+ class SecureFiles < ::API::Base
+ include PaginationParams
+
+ before do
+ authenticate!
+ authorize! :admin_build, user_project
+ feature_flag_enabled?
+ end
+
+ feature_category :pipeline_authoring
+
+ default_format :json
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'List all Secure Files for a Project'
+ params do
+ use :pagination
+ end
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ get ':id/secure_files' do
+ secure_files = user_project.secure_files
+ present paginate(secure_files), with: Entities::Ci::SecureFile
+ end
+
+ desc 'Get an individual Secure File'
+ params do
+ requires :id, type: Integer, desc: 'The Secure File ID'
+ end
+
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ get ':id/secure_files/:secure_file_id' do
+ secure_file = user_project.secure_files.find(params[:secure_file_id])
+ present secure_file, with: Entities::Ci::SecureFile
+ end
+
+ desc 'Download a Secure File'
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ get ':id/secure_files/:secure_file_id/download' do
+ secure_file = user_project.secure_files.find(params[:secure_file_id])
+
+ content_type 'application/octet-stream'
+ env['api.format'] = :binary
+ header['Content-Disposition'] = "attachment; filename=#{secure_file.name}"
+ body secure_file.file.read
+ end
+
+ desc 'Upload a Secure File'
+ params do
+ requires :name, type: String, desc: 'The name of the file'
+ requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The secure file to be uploaded'
+ optional :permissions, type: String, desc: 'The file permissions', default: 'read_only', values: %w[read_only read_write execute]
+ end
+
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ post ':id/secure_files' do
+ secure_file = user_project.secure_files.new(
+ name: params[:name],
+ permissions: params[:permissions] || :read_only
+ )
+
+ secure_file.file = params[:file]
+
+ file_too_large! unless secure_file.file.size < ::Ci::SecureFile::FILE_SIZE_LIMIT.to_i
+
+ if secure_file.save
+ present secure_file, with: Entities::Ci::SecureFile
+ else
+ render_validation_error!(secure_file)
+ end
+ end
+
+ desc 'Delete an individual Secure File'
+ route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true
+ delete ':id/secure_files/:secure_file_id' do
+ secure_file = user_project.secure_files.find(params[:secure_file_id])
+
+ secure_file.destroy!
+
+ no_content!
+ end
+ end
+
+ helpers do
+ def feature_flag_enabled?
+ service_unavailable! unless Feature.enabled?(:ci_secure_files, user_project, default_enabled: :yaml)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index 486ff5d89bc..6939853c06b 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -47,7 +47,7 @@ module API
desc 'Gets a specific deployment' do
detail 'This feature was introduced in GitLab 8.11.'
- success Entities::Deployment
+ success Entities::DeploymentExtended
end
params do
requires :deployment_id, type: Integer, desc: 'The deployment ID'
@@ -57,12 +57,12 @@ module API
deployment = user_project.deployments.find(params[:deployment_id])
- present deployment, with: Entities::Deployment
+ present deployment, with: Entities::DeploymentExtended
end
desc 'Creates a new deployment' do
detail 'This feature was introduced in GitLab 12.4'
- success Entities::Deployment
+ success Entities::DeploymentExtended
end
params do
requires :environment,
@@ -106,7 +106,7 @@ module API
deployment = service.execute
if deployment.persisted?
- present(deployment, with: Entities::Deployment, current_user: current_user)
+ present(deployment, with: Entities::DeploymentExtended, current_user: current_user)
else
render_validation_error!(deployment)
end
@@ -114,7 +114,7 @@ module API
desc 'Updates an existing deployment' do
detail 'This feature was introduced in GitLab 12.4'
- success Entities::Deployment
+ success Entities::DeploymentExtended
end
params do
requires :status,
@@ -136,7 +136,7 @@ module API
service = ::Deployments::UpdateService.new(deployment, declared_params)
if service.execute
- present(deployment, with: Entities::Deployment, current_user: current_user)
+ present(deployment, with: Entities::DeploymentExtended, current_user: current_user)
else
render_validation_error!(deployment)
end
diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb
index 0709a8c2036..f73e4b621ab 100644
--- a/lib/api/discussions.rb
+++ b/lib/api/discussions.rb
@@ -252,7 +252,7 @@ module API
.fresh
# Without RendersActions#prepare_notes_for_rendering,
- # Note#system_note_with_references_visible_for? will attempt to render
+ # Note#system_note_visible_for? will attempt to render
# Markdown references mentioned in the note to see whether they
# should be redacted. For notes that reference a commit, this
# would also incur a Gitaly call to verify the commit exists.
diff --git a/lib/api/entities/ci/reset_token_result.rb b/lib/api/entities/ci/reset_token_result.rb
index 4dbf831582b..f0b1de6a5a7 100644
--- a/lib/api/entities/ci/reset_token_result.rb
+++ b/lib/api/entities/ci/reset_token_result.rb
@@ -4,7 +4,8 @@ module API
module Entities
module Ci
class ResetTokenResult < Grape::Entity
- expose(:token) {|object| object}
+ expose(:token)
+ expose(:token_expires_at, if: -> (object, options) { object.expirable? })
end
end
end
diff --git a/lib/api/entities/ci/runner.rb b/lib/api/entities/ci/runner.rb
index c17ff513479..a6944b8c925 100644
--- a/lib/api/entities/ci/runner.rb
+++ b/lib/api/entities/ci/runner.rb
@@ -7,7 +7,10 @@ module API
expose :id
expose :description
expose :ip_address
- expose :active
+ expose :active # TODO Remove in %15.0 in favor of `paused` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/351109
+ expose :paused do |runner|
+ !runner.active
+ end
expose :instance_type?, as: :is_shared
expose :runner_type
expose :name
diff --git a/lib/api/entities/ci/runner_details.rb b/lib/api/entities/ci/runner_details.rb
index 6ded1296f2a..9b1decca274 100644
--- a/lib/api/entities/ci/runner_details.rb
+++ b/lib/api/entities/ci/runner_details.rb
@@ -15,18 +15,18 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
expose :projects, with: Entities::BasicProjectDetails do |runner, options|
if options[:current_user].admin? # rubocop: disable Cop/UserAdmin
- runner.projects.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ runner.projects
else
- options[:current_user].authorized_projects.where(id: runner.projects).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ options[:current_user].authorized_projects.where(id: runner.runner_projects.pluck(:project_id))
end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
expose :groups, with: Entities::BasicGroupDetails do |runner, options|
if options[:current_user].admin? # rubocop: disable Cop/UserAdmin
- runner.groups.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ runner.groups
else
- options[:current_user].authorized_groups.where(id: runner.groups).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ options[:current_user].authorized_groups.where(id: runner.runner_namespaces.pluck(:namespace_id))
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/api/entities/ci/runner_registration_details.rb b/lib/api/entities/ci/runner_registration_details.rb
index fa7e44c9e40..53be918406f 100644
--- a/lib/api/entities/ci/runner_registration_details.rb
+++ b/lib/api/entities/ci/runner_registration_details.rb
@@ -4,7 +4,7 @@ module API
module Entities
module Ci
class RunnerRegistrationDetails < Grape::Entity
- expose :id, :token
+ expose :id, :token, :token_expires_at
end
end
end
diff --git a/lib/api/entities/ci/secure_file.rb b/lib/api/entities/ci/secure_file.rb
new file mode 100644
index 00000000000..041c864156b
--- /dev/null
+++ b/lib/api/entities/ci/secure_file.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class SecureFile < Grape::Entity
+ expose :id
+ expose :name
+ expose :permissions
+ expose :checksum
+ expose :checksum_algorithm
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/deployment_extended.rb b/lib/api/entities/deployment_extended.rb
new file mode 100644
index 00000000000..74cfb61388b
--- /dev/null
+++ b/lib/api/entities/deployment_extended.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class DeploymentExtended < Deployment
+ end
+ end
+end
+
+API::Entities::DeploymentExtended.prepend_mod
diff --git a/lib/api/entities/user_safe.rb b/lib/api/entities/user_safe.rb
index 6006a076020..c7349026a88 100644
--- a/lib/api/entities/user_safe.rb
+++ b/lib/api/entities/user_safe.rb
@@ -7,7 +7,7 @@ module API
expose :name do |user|
next user.name unless user.project_bot?
- next user.name if options[:current_user]&.can?(:read_resource_access_tokens, user.projects.first)
+ next user.name if options[:current_user]&.can?(:read_project, user.projects.first)
# If the requester does not have permission to read the project bot name,
# the API returns an arbitrary string. UI changes will be addressed in a follow up issue:
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index d3d1f03585b..5fbf222be5d 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -84,10 +84,11 @@ module API
paginate(projects)
end
- def present_projects(params, projects)
+ def present_projects(params, projects, single_hierarchy: false)
options = {
with: params[:simple] ? Entities::BasicProjectDetails : Entities::Project,
- current_user: current_user
+ current_user: current_user,
+ single_hierarchy: single_hierarchy
}
projects, options = with_custom_attributes(projects, options)
@@ -292,6 +293,7 @@ module API
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
optional :with_shared, type: Boolean, default: true, desc: 'Include projects shared to this group'
optional :include_subgroups, type: Boolean, default: false, desc: 'Includes projects in subgroups of this group'
+ optional :include_ancestor_groups, type: Boolean, default: false, desc: 'Includes projects in ancestors of this group'
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user on projects'
use :pagination
@@ -301,12 +303,13 @@ module API
get ":id/projects" do
finder_options = {
only_owned: !params[:with_shared],
- include_subgroups: params[:include_subgroups]
+ include_subgroups: params[:include_subgroups],
+ include_ancestor_groups: params[:include_ancestor_groups]
}
projects = find_group_projects(params, finder_options)
- present_projects(params, projects)
+ present_projects(params, projects, single_hierarchy: true)
end
desc 'Get a list of shared projects in this group' do
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 76840091112..184fe7868a5 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -117,6 +117,8 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def find_project(id)
+ return unless id
+
projects = Project.without_deleted
if id.is_a?(Integer) || id =~ /^\d+$/
@@ -561,7 +563,7 @@ module API
def increment_counter(event_name)
feature_name = "usage_data_#{event_name}"
- return unless Feature.enabled?(feature_name)
+ return unless Feature.enabled?(feature_name, default_enabled: :yaml)
Gitlab::UsageDataCounters.count(event_name)
rescue StandardError => error
diff --git a/lib/api/helpers/container_registry_helpers.rb b/lib/api/helpers/container_registry_helpers.rb
index 9c844e364eb..78daf2c8cb1 100644
--- a/lib/api/helpers/container_registry_helpers.rb
+++ b/lib/api/helpers/container_registry_helpers.rb
@@ -6,7 +6,7 @@ module API
extend ActiveSupport::Concern
included do
- rescue_from Faraday::Error, ContainerRegistry::Path::InvalidRegistryPathError do |e|
+ rescue_from Faraday::Error, ::ContainerRegistry::Path::InvalidRegistryPathError do |e|
service_unavailable!('We are having trouble connecting to the Container Registry. If this error persists, please review the troubleshooting documentation.')
end
end
diff --git a/lib/api/helpers/integrations_helpers.rb b/lib/api/helpers/integrations_helpers.rb
index 72b16a23dd6..86dedc12fca 100644
--- a/lib/api/helpers/integrations_helpers.rb
+++ b/lib/api/helpers/integrations_helpers.rb
@@ -346,7 +346,13 @@ module API
required: false,
name: :datadog_env,
type: String,
- desc: 'For self-managed deployments, set the env tag for all the data sent to Datadog. How do I use tags?'
+ desc: 'For self-managed deployments, set the env tag for all the data sent to Datadog'
+ },
+ {
+ required: false,
+ name: :datadog_tags,
+ type: String,
+ desc: 'Custom tags in Datadog. Specify one tag per line in the format: "key:value\nkey2:value2"'
}
],
'discord' => [
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index e03f029a6ef..46685df0989 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -124,7 +124,8 @@ module API
repository: repository.gitaly_repository.to_h,
address: Gitlab::GitalyClient.address(repository.shard),
token: Gitlab::GitalyClient.token(repository.shard),
- features: Feature::Gitaly.server_feature_flags(repository.project)
+ features: Feature::Gitaly.server_feature_flags(repository.project),
+ use_sidechannel: Feature.enabled?(:gitlab_shell_upload_pack_sidechannel, repository.project, default_enabled: :yaml)
}
end
end
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index 6c20993431d..f26ac1318b1 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -23,7 +23,7 @@ module API
def retrieve_members(source, params:, deep: false)
members = deep ? find_all_members(source) : source_members(source).connected_to_user
members = members.includes(:user)
- members = members.references(:user).merge(User.search(params[:query])) if params[:query].present?
+ members = members.references(:user).merge(User.search(params[:query], use_minimum_char_limit: false)) if params[:query].present?
members = members.where(user_id: params[:user_ids]) if params[:user_ids].present?
members
end
diff --git a/lib/api/helpers/merge_requests_helpers.rb b/lib/api/helpers/merge_requests_helpers.rb
index f8fe40f7135..00d9f49adf0 100644
--- a/lib/api/helpers/merge_requests_helpers.rb
+++ b/lib/api/helpers/merge_requests_helpers.rb
@@ -47,9 +47,9 @@ module API
desc: 'Return opened, closed, locked, merged, or all merge requests'
optional :order_by,
type: String,
- values: %w[created_at updated_at],
+ values: Helpers::MergeRequestsHelpers.sort_options,
default: 'created_at',
- desc: 'Return merge requests ordered by `created_at` or `updated_at` fields.'
+ desc: "Return merge requests ordered by #{Helpers::MergeRequestsHelpers.sort_options_help} fields."
optional :sort,
type: String,
values: %w[asc desc],
@@ -115,6 +115,22 @@ module API
render_validation_error!(merge_request)
end
+
+ def self.sort_options
+ %w[
+ created_at
+ label_priority
+ milestone_due
+ popularity
+ priority
+ title
+ updated_at
+ ]
+ end
+
+ def self.sort_options_help
+ sort_options.map {|y| "`#{y}`" }.to_sentence(last_word_connector: ' or ')
+ end
end
end
end
diff --git a/lib/api/helpers/rate_limiter.rb b/lib/api/helpers/rate_limiter.rb
index 0ad4f089907..03f3cd649b1 100644
--- a/lib/api/helpers/rate_limiter.rb
+++ b/lib/api/helpers/rate_limiter.rb
@@ -5,7 +5,7 @@ module API
# == RateLimiter
#
# Helper that checks if the rate limit for a given endpoint is throttled by calling the
- # Gitlab::ApplicationRateLimiter class. If the action is throttled for the current user, the request
+ # Gitlab::ApplicationRateLimiter module. If the action is throttled for the current user, the request
# will be logged and an error message will be rendered with a Too Many Requests response status.
# See app/controllers/concerns/check_rate_limit.rb for Rails controllers version
module RateLimiter
diff --git a/lib/api/internal/container_registry/migration.rb b/lib/api/internal/container_registry/migration.rb
new file mode 100644
index 00000000000..b84e14c6f31
--- /dev/null
+++ b/lib/api/internal/container_registry/migration.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module API
+ module Internal
+ module ContainerRegistry
+ class Migration < ::API::Base
+ feature_category :container_registry
+
+ STATUS_PRE_IMPORT_COMPLETE = 'pre_import_complete'
+ STATUS_PRE_IMPORT_FAILED = 'pre_import_failed'
+ STATUS_IMPORT_COMPLETE = 'import_complete'
+ STATUS_IMPORT_FAILED = 'import_failed'
+ POSSIBLE_VALUES = [
+ STATUS_PRE_IMPORT_COMPLETE,
+ STATUS_PRE_IMPORT_FAILED,
+ STATUS_IMPORT_COMPLETE,
+ STATUS_IMPORT_FAILED
+ ].freeze
+
+ before { authenticate! }
+
+ helpers do
+ def authenticate!
+ secret_token = Gitlab.config.registry.notification_secret
+
+ unauthorized! unless Devise.secure_compare(secret_token, headers['Authorization'])
+ end
+
+ def find_repository!(path)
+ ::ContainerRepository.find_by_path!(::ContainerRegistry::Path.new(path))
+ end
+ end
+
+ params do
+ requires :repository_path, type: String, desc: 'The container repository path'
+ requires :status, type: String, values: POSSIBLE_VALUES, desc: 'The migration step status'
+ end
+ put 'internal/registry/repositories/*repository_path/migration/status' do
+ repository = find_repository!(declared_params[:repository_path])
+
+ unless repository.migration_in_active_state?
+ bad_request!("Wrong migration state (#{repository.migration_state})")
+ end
+
+ case declared_params[:status]
+ when STATUS_PRE_IMPORT_COMPLETE
+ unless repository.finish_pre_import_and_start_import
+ bad_request!("Couldn't transition from pre_importing to importing")
+ end
+ when STATUS_IMPORT_COMPLETE
+ unless repository.finish_import
+ bad_request!("Couldn't transition from importing to import_done")
+ end
+ when STATUS_IMPORT_FAILED, STATUS_PRE_IMPORT_FAILED
+ repository.abort_import
+ end
+
+ status 200
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 46124a74e9d..a5d6a6d7cf3 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -80,7 +80,7 @@ module API
desc: 'Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, or `updated_at` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return issues sorted in `asc` or `desc` order.'
- optional :due_date, type: String, values: %w[0 overdue week month next_month_and_previous_two_weeks] << '',
+ optional :due_date, type: String, values: %w[0 any today tomorrow overdue week month next_month_and_previous_two_weeks] << '',
desc: 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`'
optional :issue_type, type: String, values: WorkItems::Type.allowed_types_for_issues, desc: "The type of the issue. Accepts: #{WorkItems::Type.allowed_types_for_issues.join(', ')}"
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index bfd457a3092..6de78c81cac 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -42,14 +42,18 @@ module API
params do
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
+ optional :ref, type: String, desc: 'Branch or tag used to execute a dry run. Defaults to the default branch of the project. Only used when dry_run is true'
end
get ':id/ci/lint', urgency: :low do
authorize! :download_code, user_project
- content = user_project.repository.gitlab_ci_yml_for(user_project.commit.id, user_project.ci_config_path_or_default)
+ if user_project.commit.present?
+ content = user_project.repository.gitlab_ci_yml_for(user_project.commit.id, user_project.ci_config_path_or_default)
+ end
+
result = Gitlab::Ci::Lint
.new(project: user_project, current_user: current_user)
- .validate(content, dry_run: params[:dry_run])
+ .validate(content, dry_run: params[:dry_run], ref: params[:ref] || user_project.default_branch)
present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs]
end
@@ -63,13 +67,14 @@ module API
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
+ optional :ref, type: String, desc: 'Branch or tag used to execute a dry run. Defaults to the default branch of the project. Only used when dry_run is true'
end
post ':id/ci/lint', urgency: :low do
authorize! :create_pipeline, user_project
result = Gitlab::Ci::Lint
.new(project: user_project, current_user: current_user)
- .validate(params[:content], dry_run: params[:dry_run])
+ .validate(params[:content], dry_run: params[:dry_run], ref: params[:ref] || user_project.default_branch)
status 200
present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs]
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 3f39af7f909..f7df8d33418 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -117,6 +117,9 @@ module API
forbidden!('Cannot push to source branch') unless
user_access.can_push_to_branch?(merge_request.source_branch)
+
+ forbidden!('Source branch is protected from force push') unless
+ merge_request.permits_force_push?
end
params :merge_requests_params do
@@ -204,11 +207,7 @@ module API
options = serializer_options_for(merge_requests).merge(project: user_project)
options[:project] = user_project
- if Feature.enabled?(:api_caching_merge_requests, user_project, type: :development, default_enabled: :yaml)
- present_cached merge_requests, expires_in: 2.days, **options
- else
- present merge_requests, options
- end
+ present_cached merge_requests, expires_in: 2.days, **options
end
desc 'Create a merge request' do
diff --git a/lib/api/package_files.rb b/lib/api/package_files.rb
index 3bf47fe1e8b..e80355e80c7 100644
--- a/lib/api/package_files.rb
+++ b/lib/api/package_files.rb
@@ -28,13 +28,8 @@ module API
package = ::Packages::PackageFinder
.new(user_project, params[:package_id]).execute
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files
- else
- package.package_files
- end
-
- package_files = package_files.preload_pipelines
+ package_files = package.installable_package_files
+ .preload_pipelines
present paginate(package_files), with: ::API::Entities::PackageFile
end
@@ -55,13 +50,8 @@ module API
not_found! unless package
- package_files = if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files
- else
- package.package_files
- end
-
- package_file = package_files.find_by_id(params[:package_file_id])
+ package_file = package.installable_package_files
+ .find_by_id(params[:package_file_id])
not_found! unless package_file
diff --git a/lib/api/pagination_params.rb b/lib/api/pagination_params.rb
index a232b58d3f7..85ac50d5bec 100644
--- a/lib/api/pagination_params.rb
+++ b/lib/api/pagination_params.rb
@@ -18,7 +18,7 @@ module API
helpers do
params :pagination do
optional :page, type: Integer, default: 1, desc: 'Current page number'
- optional :per_page, type: Integer, default: 20, desc: 'Number of items per page'
+ optional :per_page, type: Integer, default: 20, desc: 'Number of items per page', except_values: [0]
end
end
end
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index 7bdcaa5a26f..a3d76e571a9 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -133,7 +133,7 @@ module API
success Entities::ProjectImportStatus
end
post 'remote-import' do
- not_found! unless ::Feature.enabled?(:import_project_from_remote_file)
+ not_found! unless ::Feature.enabled?(:import_project_from_remote_file, default_enabled: :yaml)
check_rate_limit! :project_import, scope: [current_user, :project_import]
diff --git a/lib/api/projects_relation_builder.rb b/lib/api/projects_relation_builder.rb
index a4bd06aec10..aabecb43653 100644
--- a/lib/api/projects_relation_builder.rb
+++ b/lib/api/projects_relation_builder.rb
@@ -13,6 +13,7 @@ module API
preload_repository_cache(projects_relation)
Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects_relation, options[:current_user]).execute if options[:current_user]
+ Preloaders::SingleHierarchyProjectGroupPlansPreloader.new(projects_relation).execute if options[:single_hierarchy]
projects_relation
end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index fc976c23726..c3632c812f3 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -171,7 +171,6 @@ module API
optional :straight, type: Boolean, desc: 'Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)', default: false
end
get ':id/repository/compare', urgency: :low do
- ff_enabled = Feature.enabled?(:api_caching_rate_limit_repository_compare, user_project, default_enabled: :yaml)
target_project = fetch_target_project(current_user, user_project, params)
if target_project.blank?
@@ -180,7 +179,7 @@ module API
cache_key = compare_cache_key(current_user, user_project, target_project, declared_params)
- cache_action_if(ff_enabled, cache_key, expires_in: 1.minute) do
+ cache_action(cache_key, expires_in: 1.minute) do
compare = CompareService.new(user_project, params[:to]).execute(target_project, params[:from], straight: params[:straight])
if compare
diff --git a/lib/api/rubygem_packages.rb b/lib/api/rubygem_packages.rb
index 3effa370e84..6ac5ad0518b 100644
--- a/lib/api/rubygem_packages.rb
+++ b/lib/api/rubygem_packages.rb
@@ -69,9 +69,7 @@ module API
package_files = ::Packages::PackageFile
.for_rubygem_with_file_name(user_project, params[:file_name])
- package_files = package_files.installable if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
-
- package_file = package_files.last!
+ package_file = package_files.installable.last!
track_package_event('pull_package', :rubygems, project: user_project, namespace: user_project.namespace)
diff --git a/lib/api/scope.rb b/lib/api/scope.rb
index 707775e5d15..62aefcceb4b 100644
--- a/lib/api/scope.rb
+++ b/lib/api/scope.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
# Encapsulate a scope used for authorization, such as `api`, or `read_user`
+# See Gitlab::Auth for the set of available scopes, and their purposes.
module API
class Scope
attr_reader :name, :if
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index 508ccdb4b33..b256432fbf1 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -177,6 +177,10 @@ module API
optional :floc_enabled, type: Grape::API::Boolean, desc: 'Enable FloC (Federated Learning of Cohorts)'
optional :user_deactivation_emails_enabled, type: Boolean, desc: 'Send emails to users upon account deactivation'
optional :suggest_pipeline_enabled, type: Boolean, desc: 'Enable pipeline suggestion banner'
+ optional :users_get_by_id_limit, type: Integer, desc: "Maximum number of calls to the /users/:id API per 10 minutes per user. Set to 0 for unlimited requests."
+ optional :runner_token_expiration_interval, type: Integer, desc: 'Token expiration interval for shared runners, in seconds'
+ 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'
ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
optional :"#{type}_key_restriction",
diff --git a/lib/api/support/token_with_expiration.rb b/lib/api/support/token_with_expiration.rb
new file mode 100644
index 00000000000..2cbd562c608
--- /dev/null
+++ b/lib/api/support/token_with_expiration.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module API
+ module Support
+ class TokenWithExpiration
+ def initialize(strategy, instance)
+ @strategy = strategy
+ @instance = instance
+ end
+
+ def token
+ @strategy.get_token(@instance)
+ end
+
+ def token_expires_at
+ @strategy.expires_at(@instance)
+ end
+
+ def expirable?
+ @strategy.expirable?
+ end
+ end
+ end
+end
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index 1b37d38ef06..0fa8c21f8d7 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -33,11 +33,7 @@ module API
paginated_tags = Gitlab::Pagination::GitalyKeysetPager.new(self, user_project).paginate(tags_finder)
- if Feature.enabled?(:api_caching_tags, user_project, type: :development)
- present_cached paginated_tags, with: Entities::Tag, project: user_project, cache_context: -> (_tag) { user_project.cache_key }
- else
- present paginated_tags, with: Entities::Tag, project: user_project
- end
+ present_cached paginated_tags, with: Entities::Tag, project: user_project, cache_context: -> (_tag) { user_project.cache_key }
rescue Gitlab::Git::InvalidPageToken => e
unprocessable_entity!(e.message)
diff --git a/lib/api/terraform/modules/v1/packages.rb b/lib/api/terraform/modules/v1/packages.rb
index 970fdeba734..797b4aad033 100644
--- a/lib/api/terraform/modules/v1/packages.rb
+++ b/lib/api/terraform/modules/v1/packages.rb
@@ -21,7 +21,7 @@ module API
module_version: SEMVER_REGEX
}.freeze
- feature_category :package_registry
+ feature_category :infrastructure_as_code
after_validation do
require_packages_enabled!
@@ -71,11 +71,7 @@ module API
def package_file
strong_memoize(:package_file) do
- if Feature.enabled?(:packages_installable_package_files, default_enabled: :yaml)
- package.installable_package_files.first
- else
- package.package_files.first
- end
+ package.installable_package_files.first
end
end
end
diff --git a/lib/api/usage_data_non_sql_metrics.rb b/lib/api/usage_data_non_sql_metrics.rb
index d9e0d153e58..983038e0263 100644
--- a/lib/api/usage_data_non_sql_metrics.rb
+++ b/lib/api/usage_data_non_sql_metrics.rb
@@ -18,7 +18,7 @@ module API
get 'non_sql_metrics' do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/325534')
- data = Gitlab::UsageDataNonSqlMetrics.uncached_data
+ data = Gitlab::Usage::ServicePingReport.for(output: :non_sql_metrics_values)
present data
end
diff --git a/lib/api/usage_data_queries.rb b/lib/api/usage_data_queries.rb
index 22e83fe0294..3432e71eb28 100644
--- a/lib/api/usage_data_queries.rb
+++ b/lib/api/usage_data_queries.rb
@@ -18,7 +18,7 @@ module API
get 'queries' do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/325534')
- queries = Gitlab::UsageDataQueries.uncached_data
+ queries = Gitlab::Usage::ServicePingReport.for(output: :metrics_queries)
present queries
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index eeb5244466a..d540978931e 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -143,7 +143,12 @@ module API
forbidden!('Not authorized!') unless current_user
if Feature.enabled?(:rate_limit_user_by_id_endpoint, type: :development)
- check_rate_limit! :users_get_by_id, scope: current_user unless current_user.admin?
+ unless current_user.admin?
+ check_rate_limit!(:users_get_by_id,
+ scope: current_user,
+ users_allowlist: Gitlab::CurrentSettings.current_application_settings.users_get_by_id_limit_allowlist
+ )
+ end
end
user = User.find_by(id: params[:id])