summaryrefslogtreecommitdiff
path: root/lib/api
diff options
context:
space:
mode:
Diffstat (limited to 'lib/api')
-rw-r--r--lib/api/admin/ci/variables.rb18
-rw-r--r--lib/api/api.rb6
-rw-r--r--lib/api/api_guard.rb11
-rw-r--r--lib/api/branches.rb8
-rw-r--r--lib/api/ci/pipeline_schedules.rb34
-rw-r--r--lib/api/ci/pipelines.rb34
-rw-r--r--lib/api/ci/runners.rb4
-rw-r--r--lib/api/commits.rb38
-rw-r--r--lib/api/composer_packages.rb10
-rw-r--r--lib/api/conan_packages.rb90
-rw-r--r--lib/api/entities/branch.rb2
-rw-r--r--lib/api/entities/bridge.rb9
-rw-r--r--lib/api/entities/ci/bridge.rb11
-rw-r--r--lib/api/entities/ci/job.rb15
-rw-r--r--lib/api/entities/ci/job_artifact.rb11
-rw-r--r--lib/api/entities/ci/job_artifact_file.rb12
-rw-r--r--lib/api/entities/ci/job_basic.rb20
-rw-r--r--lib/api/entities/ci/job_basic_with_project.rb11
-rw-r--r--lib/api/entities/ci/pipeline.rb19
-rw-r--r--lib/api/entities/ci/pipeline_basic.rb16
-rw-r--r--lib/api/entities/ci/pipeline_schedule.rb14
-rw-r--r--lib/api/entities/ci/pipeline_schedule_details.rb12
-rw-r--r--lib/api/entities/ci/variable.rb14
-rw-r--r--lib/api/entities/commit_detail.rb2
-rw-r--r--lib/api/entities/deployment.rb2
-rw-r--r--lib/api/entities/event.rb1
-rw-r--r--lib/api/entities/feature.rb2
-rw-r--r--lib/api/entities/job.rb13
-rw-r--r--lib/api/entities/job_artifact.rb9
-rw-r--r--lib/api/entities/job_artifact_file.rb10
-rw-r--r--lib/api/entities/job_basic.rb18
-rw-r--r--lib/api/entities/job_basic_with_project.rb9
-rw-r--r--lib/api/entities/job_request/dependency.rb2
-rw-r--r--lib/api/entities/job_request/response.rb2
-rw-r--r--lib/api/entities/merge_request.rb4
-rw-r--r--lib/api/entities/package.rb4
-rw-r--r--lib/api/entities/package/pipeline.rb2
-rw-r--r--lib/api/entities/personal_access_token.rb2
-rw-r--r--lib/api/entities/pipeline.rb17
-rw-r--r--lib/api/entities/pipeline_basic.rb14
-rw-r--r--lib/api/entities/pipeline_schedule.rb12
-rw-r--r--lib/api/entities/pipeline_schedule_details.rb10
-rw-r--r--lib/api/entities/project.rb1
-rw-r--r--lib/api/entities/project_hook.rb2
-rw-r--r--lib/api/entities/user_details_with_admin.rb1
-rw-r--r--lib/api/entities/variable.rb12
-rw-r--r--lib/api/group_variables.rb55
-rw-r--r--lib/api/groups.rb22
-rw-r--r--lib/api/helpers.rb12
-rw-r--r--lib/api/helpers/internal_helpers.rb2
-rw-r--r--lib/api/helpers/merge_requests_helpers.rb17
-rw-r--r--lib/api/helpers/notes_helpers.rb5
-rw-r--r--lib/api/helpers/packages/basic_auth_helpers.rb13
-rw-r--r--lib/api/helpers/packages/conan/api_helpers.rb24
-rw-r--r--lib/api/helpers/packages_manager_clients_helpers.rb10
-rw-r--r--lib/api/helpers/pagination_strategies.rb2
-rw-r--r--lib/api/helpers/performance_bar_helpers.rb21
-rw-r--r--lib/api/helpers/projects_helpers.rb2
-rw-r--r--lib/api/helpers/services_helpers.rb6
-rw-r--r--lib/api/helpers/snippets_helpers.rb24
-rw-r--r--lib/api/import_github.rb6
-rw-r--r--lib/api/internal/base.rb62
-rw-r--r--lib/api/internal/kubernetes.rb95
-rw-r--r--lib/api/issues.rb2
-rw-r--r--lib/api/job_artifacts.rb4
-rw-r--r--lib/api/jobs.rb34
-rw-r--r--lib/api/merge_requests.rb42
-rw-r--r--lib/api/milestone_responses.rb48
-rw-r--r--lib/api/notes.rb3
-rw-r--r--lib/api/nuget_packages.rb37
-rw-r--r--lib/api/project_export.rb2
-rw-r--r--lib/api/project_hooks.rb1
-rw-r--r--lib/api/project_snippets.rb10
-rw-r--r--lib/api/project_templates.rb14
-rw-r--r--lib/api/projects.rb2
-rw-r--r--lib/api/pypi_packages.rb12
-rw-r--r--lib/api/release/links.rb2
-rw-r--r--lib/api/releases.rb6
-rw-r--r--lib/api/snippets.rb11
-rw-r--r--lib/api/support/git_access_actor.rb9
-rw-r--r--lib/api/triggers.rb4
-rw-r--r--lib/api/users.rb2
-rw-r--r--lib/api/validations/validators/file_path.rb8
-rw-r--r--lib/api/variables.rb47
-rw-r--r--lib/api/wikis.rb5
85 files changed, 842 insertions, 411 deletions
diff --git a/lib/api/admin/ci/variables.rb b/lib/api/admin/ci/variables.rb
index 6b0ff5e9395..8721d94d642 100644
--- a/lib/api/admin/ci/variables.rb
+++ b/lib/api/admin/ci/variables.rb
@@ -12,7 +12,7 @@ module API
namespace 'ci' do
namespace 'variables' do
desc 'Get instance-level variables' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
use :pagination
@@ -20,11 +20,11 @@ module API
get '/' do
variables = ::Ci::InstanceVariable.all
- present paginate(variables), with: Entities::Variable
+ present paginate(variables), with: Entities::Ci::Variable
end
desc 'Get a specific variable from a group' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key, type: String, desc: 'The key of the variable'
@@ -35,11 +35,11 @@ module API
break not_found!('InstanceVariable') unless variable
- present variable, with: Entities::Variable
+ present variable, with: Entities::Ci::Variable
end
desc 'Create a new instance-level variable' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key,
@@ -69,14 +69,14 @@ module API
variable = ::Ci::InstanceVariable.new(variable_params)
if variable.save
- present variable, with: Entities::Variable
+ present variable, with: Entities::Ci::Variable
else
render_validation_error!(variable)
end
end
desc 'Update an existing instance-variable' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
optional :key,
@@ -108,14 +108,14 @@ module API
variable_params = declared_params(include_missing: false).except(:key)
if variable.update(variable_params)
- present variable, with: Entities::Variable
+ present variable, with: Entities::Ci::Variable
else
render_validation_error!(variable)
end
end
desc 'Delete an existing instance-level variable' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key, type: String, desc: 'The key of the variable'
diff --git a/lib/api/api.rb b/lib/api/api.rb
index a89dc0fa6fa..2be6792af5f 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -56,6 +56,10 @@ module API
)
end
+ before do
+ set_peek_enabled_for_current_request
+ end
+
# The locale is set to the current user's locale when `current_user` is loaded
after { Gitlab::I18n.use_default_locale }
@@ -116,6 +120,7 @@ module API
# Ensure the namespace is right, otherwise we might load Grape::API::Helpers
helpers ::API::Helpers
helpers ::API::Helpers::CommonHelpers
+ helpers ::API::Helpers::PerformanceBarHelpers
namespace do
after do
@@ -237,6 +242,7 @@ module API
mount ::API::Internal::Base
mount ::API::Internal::Pages
+ mount ::API::Internal::Kubernetes
route :any, '*path' do
error!('404 Not Found', 404)
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index 4b87861a3de..59978962b1d 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -7,6 +7,7 @@ require 'rack/oauth2'
module API
module APIGuard
extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
included do |base|
# OAuth2 Resource Server Authentication
@@ -64,10 +65,12 @@ module API
end
def find_user_from_sources
- deploy_token_from_request ||
- find_user_from_bearer_token ||
- find_user_from_job_token ||
- find_user_from_warden
+ strong_memoize(:find_user_from_sources) do
+ deploy_token_from_request ||
+ find_user_from_bearer_token ||
+ find_user_from_job_token ||
+ find_user_from_warden
+ end
end
private
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 5e9c2caf8f5..44f7610384e 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -40,12 +40,8 @@ module API
repository = user_project.repository
- if Feature.enabled?(:branch_list_keyset_pagination, user_project)
- branches = BranchesFinder.new(repository, declared_params(include_missing: false)).execute(gitaly_pagination: true)
- else
- branches = BranchesFinder.new(repository, declared_params(include_missing: false)).execute
- branches = paginate(::Kaminari.paginate_array(branches))
- end
+ branches_finder = BranchesFinder.new(repository, declared_params(include_missing: false))
+ branches = Gitlab::Pagination::GitalyKeysetPager.new(self, user_project).paginate(branches_finder)
merged_branch_names = repository.merged_branch_names(branches.map(&:name))
diff --git a/lib/api/ci/pipeline_schedules.rb b/lib/api/ci/pipeline_schedules.rb
index 80ad8aa04dd..1afdb0ad34c 100644
--- a/lib/api/ci/pipeline_schedules.rb
+++ b/lib/api/ci/pipeline_schedules.rb
@@ -12,7 +12,7 @@ module API
end
resource :projects, requirements: ::API::API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get all pipeline schedules' do
- success Entities::PipelineSchedule
+ success Entities::Ci::PipelineSchedule
end
params do
use :pagination
@@ -25,22 +25,22 @@ module API
schedules = ::Ci::PipelineSchedulesFinder.new(user_project).execute(scope: params[:scope])
.preload([:owner, :last_pipeline])
- present paginate(schedules), with: Entities::PipelineSchedule
+ present paginate(schedules), with: Entities::Ci::PipelineSchedule
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Get a single pipeline schedule' do
- success Entities::PipelineScheduleDetails
+ success Entities::Ci::PipelineScheduleDetails
end
params do
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
end
get ':id/pipeline_schedules/:pipeline_schedule_id' do
- present pipeline_schedule, with: Entities::PipelineScheduleDetails
+ present pipeline_schedule, with: Entities::Ci::PipelineScheduleDetails
end
desc 'Create a new pipeline schedule' do
- success Entities::PipelineScheduleDetails
+ success Entities::Ci::PipelineScheduleDetails
end
params do
requires :description, type: String, desc: 'The description of pipeline schedule'
@@ -57,14 +57,14 @@ module API
.execute
if pipeline_schedule.persisted?
- present pipeline_schedule, with: Entities::PipelineScheduleDetails
+ present pipeline_schedule, with: Entities::Ci::PipelineScheduleDetails
else
render_validation_error!(pipeline_schedule)
end
end
desc 'Edit a pipeline schedule' do
- success Entities::PipelineScheduleDetails
+ success Entities::Ci::PipelineScheduleDetails
end
params do
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
@@ -78,14 +78,14 @@ module API
authorize! :update_pipeline_schedule, pipeline_schedule
if pipeline_schedule.update(declared_params(include_missing: false))
- present pipeline_schedule, with: Entities::PipelineScheduleDetails
+ present pipeline_schedule, with: Entities::Ci::PipelineScheduleDetails
else
render_validation_error!(pipeline_schedule)
end
end
desc 'Take ownership of a pipeline schedule' do
- success Entities::PipelineScheduleDetails
+ success Entities::Ci::PipelineScheduleDetails
end
params do
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
@@ -94,14 +94,14 @@ module API
authorize! :update_pipeline_schedule, pipeline_schedule
if pipeline_schedule.own!(current_user)
- present pipeline_schedule, with: Entities::PipelineScheduleDetails
+ present pipeline_schedule, with: Entities::Ci::PipelineScheduleDetails
else
render_validation_error!(pipeline_schedule)
end
end
desc 'Delete a pipeline schedule' do
- success Entities::PipelineScheduleDetails
+ success Entities::Ci::PipelineScheduleDetails
end
params do
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
@@ -132,7 +132,7 @@ module API
end
desc 'Create a new pipeline schedule variable' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
@@ -146,14 +146,14 @@ module API
variable_params = declared_params(include_missing: false)
variable = pipeline_schedule.variables.create(variable_params)
if variable.persisted?
- present variable, with: Entities::Variable
+ present variable, with: Entities::Ci::Variable
else
render_validation_error!(variable)
end
end
desc 'Edit a pipeline schedule variable' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
@@ -165,14 +165,14 @@ module API
authorize! :update_pipeline_schedule, pipeline_schedule
if pipeline_schedule_variable.update(declared_params(include_missing: false))
- present pipeline_schedule_variable, with: Entities::Variable
+ present pipeline_schedule_variable, with: Entities::Ci::Variable
else
render_validation_error!(pipeline_schedule_variable)
end
end
desc 'Delete a pipeline schedule variable' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
@@ -182,7 +182,7 @@ module API
authorize! :admin_pipeline_schedule, pipeline_schedule
status :accepted
- present pipeline_schedule_variable.destroy, with: Entities::Variable
+ present pipeline_schedule_variable.destroy, with: Entities::Ci::Variable
end
end
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index 33bb8b38d92..a010e0dd761 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -13,7 +13,7 @@ module API
resource :projects, requirements: ::API::API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get all Pipelines of the project' do
detail 'This feature was introduced in GitLab 8.11.'
- success Entities::PipelineBasic
+ success Entities::Ci::PipelineBasic
end
params do
use :pagination
@@ -38,12 +38,12 @@ module API
authorize! :read_build, user_project
pipelines = ::Ci::PipelinesFinder.new(user_project, current_user, params).execute
- present paginate(pipelines), with: Entities::PipelineBasic
+ present paginate(pipelines), with: Entities::Ci::PipelineBasic
end
desc 'Create a new pipeline' do
detail 'This feature was introduced in GitLab 8.14'
- success Entities::Pipeline
+ success Entities::Ci::Pipeline
end
params do
requires :ref, type: String, desc: 'Reference'
@@ -64,7 +64,7 @@ module API
.execute(:api, ignore_skip_ci: true, save_on_errors: false)
if new_pipeline.persisted?
- present new_pipeline, with: Entities::Pipeline
+ present new_pipeline, with: Entities::Ci::Pipeline
else
render_validation_error!(new_pipeline)
end
@@ -72,7 +72,7 @@ module API
desc 'Gets a the latest pipeline for the project branch' do
detail 'This feature was introduced in GitLab 12.3'
- success Entities::Pipeline
+ success Entities::Ci::Pipeline
end
params do
optional :ref, type: String, desc: 'branch ref of pipeline'
@@ -80,12 +80,12 @@ module API
get ':id/pipelines/latest' do
authorize! :read_pipeline, latest_pipeline
- present latest_pipeline, with: Entities::Pipeline
+ present latest_pipeline, with: Entities::Ci::Pipeline
end
desc 'Gets a specific pipeline for the project' do
detail 'This feature was introduced in GitLab 8.11'
- success Entities::Pipeline
+ success Entities::Ci::Pipeline
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
@@ -93,12 +93,12 @@ module API
get ':id/pipelines/:pipeline_id' do
authorize! :read_pipeline, pipeline
- present pipeline, with: Entities::Pipeline
+ present pipeline, with: Entities::Ci::Pipeline
end
desc 'Gets the variables for a given pipeline' do
detail 'This feature was introduced in GitLab 11.11'
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
@@ -106,19 +106,17 @@ module API
get ':id/pipelines/:pipeline_id/variables' do
authorize! :read_pipeline_variable, pipeline
- present pipeline.variables, with: Entities::Variable
+ present pipeline.variables, with: Entities::Ci::Variable
end
desc 'Gets the test report for a given pipeline' do
- detail 'This feature was introduced in GitLab 13.0. Disabled by default behind feature flag `junit_pipeline_view`'
+ detail 'This feature was introduced in GitLab 13.0.'
success TestReportEntity
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end
get ':id/pipelines/:pipeline_id/test_report' do
- not_found! unless Feature.enabled?(:junit_pipeline_view, user_project)
-
authorize! :read_build, pipeline
present pipeline.test_reports, with: TestReportEntity, details: true
@@ -141,7 +139,7 @@ module API
desc 'Retry builds in the pipeline' do
detail 'This feature was introduced in GitLab 8.11.'
- success Entities::Pipeline
+ success Entities::Ci::Pipeline
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
@@ -151,12 +149,12 @@ module API
pipeline.retry_failed(current_user)
- present pipeline, with: Entities::Pipeline
+ present pipeline, with: Entities::Ci::Pipeline
end
desc 'Cancel all builds in the pipeline' do
detail 'This feature was introduced in GitLab 8.11.'
- success Entities::Pipeline
+ success Entities::Ci::Pipeline
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
@@ -167,14 +165,14 @@ module API
pipeline.cancel_running
status 200
- present pipeline.reset, with: Entities::Pipeline
+ present pipeline.reset, with: Entities::Ci::Pipeline
end
end
helpers do
def pipeline
strong_memoize(:pipeline) do
- user_project.ci_pipelines.find(params[:pipeline_id])
+ user_project.all_pipelines.find(params[:pipeline_id])
end
end
diff --git a/lib/api/ci/runners.rb b/lib/api/ci/runners.rb
index 2c156a71160..7bca72f8028 100644
--- a/lib/api/ci/runners.rb
+++ b/lib/api/ci/runners.rb
@@ -111,7 +111,7 @@ module API
end
desc 'List jobs running on a runner' do
- success Entities::JobBasicWithProject
+ success Entities::Ci::JobBasicWithProject
end
params do
requires :id, type: Integer, desc: 'The ID of the runner'
@@ -126,7 +126,7 @@ module API
jobs = ::Ci::RunnerJobsFinder.new(runner, params).execute
- present paginate(jobs), with: Entities::JobBasicWithProject
+ present paginate(jobs), with: Entities::Ci::JobBasicWithProject
end
end
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 1a0fe393753..3c7ed2a25a0 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -13,7 +13,7 @@ module API
helpers do
def user_access
- @user_access ||= Gitlab::UserAccess.new(current_user, project: user_project)
+ @user_access ||= Gitlab::UserAccess.new(current_user, container: user_project)
end
def authorize_push_to_branch!(branch)
@@ -203,6 +203,7 @@ module API
params do
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag to be cherry picked'
requires :branch, type: String, desc: 'The name of the branch', allow_blank: false
+ optional :dry_run, type: Boolean, default: false, desc: "Does not commit any changes"
end
post ':id/repository/commits/:sha/cherry_pick', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
authorize_push_to_branch!(params[:branch])
@@ -215,7 +216,8 @@ module API
commit_params = {
commit: commit,
start_branch: params[:branch],
- branch_name: params[:branch]
+ branch_name: params[:branch],
+ dry_run: params[:dry_run]
}
result = ::Commits::CherryPickService
@@ -223,10 +225,18 @@ module API
.execute
if result[:status] == :success
- present user_project.repository.commit(result[:result]),
- with: Entities::Commit
+ if params[:dry_run]
+ present dry_run: :success
+ status :ok
+ else
+ present user_project.repository.commit(result[:result]),
+ with: Entities::Commit
+ end
else
- error!(result.slice(:message, :error_code), 400, header)
+ response = result.slice(:message, :error_code)
+ response[:dry_run] = :error if params[:dry_run]
+
+ error!(response, 400, header)
end
end
@@ -237,6 +247,7 @@ module API
params do
requires :sha, type: String, desc: 'Commit SHA to revert'
requires :branch, type: String, desc: 'Target branch name', allow_blank: false
+ optional :dry_run, type: Boolean, default: false, desc: "Does not commit any changes"
end
post ':id/repository/commits/:sha/revert', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
authorize_push_to_branch!(params[:branch])
@@ -249,7 +260,8 @@ module API
commit_params = {
commit: commit,
start_branch: params[:branch],
- branch_name: params[:branch]
+ branch_name: params[:branch],
+ dry_run: params[:dry_run]
}
result = ::Commits::RevertService
@@ -257,10 +269,18 @@ module API
.execute
if result[:status] == :success
- present user_project.repository.commit(result[:result]),
- with: Entities::Commit
+ if params[:dry_run]
+ present dry_run: :success
+ status :ok
+ else
+ present user_project.repository.commit(result[:result]),
+ with: Entities::Commit
+ end
else
- error!(result.slice(:message, :error_code), 400, header)
+ response = result.slice(:message, :error_code)
+ response[:dry_run] = :error if params[:dry_run]
+
+ error!(response, 400, header)
end
end
diff --git a/lib/api/composer_packages.rb b/lib/api/composer_packages.rb
index 726dc89271a..05887e58425 100644
--- a/lib/api/composer_packages.rb
+++ b/lib/api/composer_packages.rb
@@ -59,7 +59,7 @@ module API
desc 'Composer packages endpoint at group level'
- route_setting :authentication, job_token_allowed: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
get ':id/-/packages/composer/packages' do
presenter.root
@@ -71,7 +71,7 @@ module API
requires :sha, type: String, desc: 'Shasum of current json'
end
- route_setting :authentication, job_token_allowed: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
get ':id/-/packages/composer/p/:sha' do
presenter.provider
@@ -83,7 +83,7 @@ module API
requires :package_name, type: String, file_path: true, desc: 'The Composer package name'
end
- route_setting :authentication, job_token_allowed: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
get ':id/-/packages/composer/*package_name', requirements: COMPOSER_ENDPOINT_REQUIREMENTS, file_path: true do
not_found! if packages.empty?
@@ -104,7 +104,7 @@ module API
desc 'Composer packages endpoint for registering packages'
namespace ':id/packages/composer' do
- route_setting :authentication, job_token_allowed: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
params do
optional :branch, type: String, desc: 'The name of the branch'
@@ -123,7 +123,7 @@ module API
bad_request!
end
- track_event('register_package')
+ track_event('push_package')
::Packages::Composer::CreatePackageService
.new(authorized_user_project, current_user, declared_params)
diff --git a/lib/api/conan_packages.rb b/lib/api/conan_packages.rb
index 1d941e422a7..6923d252fbd 100644
--- a/lib/api/conan_packages.rb
+++ b/lib/api/conan_packages.rb
@@ -38,7 +38,9 @@ module API
desc 'Ping the Conan API' do
detail 'This feature was introduced in GitLab 12.2'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'ping' do
header 'X-Conan-Server-Capabilities', [].join(',')
end
@@ -46,10 +48,13 @@ module API
desc 'Search for packages' do
detail 'This feature was introduced in GitLab 12.4'
end
+
params do
requires :q, type: String, desc: 'Search query'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'conans/search' do
service = ::Packages::Conan::SearchService.new(current_user, query: params[:q]).execute
service.payload
@@ -61,7 +66,9 @@ module API
desc 'Authenticate user against conan CLI' do
detail 'This feature was introduced in GitLab 12.2'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'authenticate' do
unauthorized! unless token
@@ -71,7 +78,9 @@ module API
desc 'Check for valid user credentials per conan CLI' do
detail 'This feature was introduced in GitLab 12.4'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'check_credentials' do
authenticate!
:ok
@@ -93,10 +102,13 @@ module API
desc 'Package Snapshot' do
detail 'This feature was introduced in GitLab 12.5'
end
+
params do
requires :conan_package_reference, type: String, desc: 'Conan package ID'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'packages/:conan_package_reference' do
authorize!(:read_package, project)
@@ -113,7 +125,9 @@ module API
desc 'Recipe Snapshot' do
detail 'This feature was introduced in GitLab 12.5'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get do
authorize!(:read_package, project)
@@ -133,7 +147,9 @@ module API
params do
requires :conan_package_reference, type: String, desc: 'Conan package ID'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'packages/:conan_package_reference/digest' do
present_package_download_urls
end
@@ -141,7 +157,9 @@ module API
desc 'Recipe Digest' do
detail 'This feature was introduced in GitLab 12.5'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'digest' do
present_recipe_download_urls
end
@@ -155,10 +173,13 @@ module API
desc 'Package Download Urls' do
detail 'This feature was introduced in GitLab 12.5'
end
+
params do
requires :conan_package_reference, type: String, desc: 'Conan package ID'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'packages/:conan_package_reference/download_urls' do
present_package_download_urls
end
@@ -166,7 +187,9 @@ module API
desc 'Recipe Download Urls' do
detail 'This feature was introduced in GitLab 12.5'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get 'download_urls' do
present_recipe_download_urls
end
@@ -181,36 +204,39 @@ module API
desc 'Package Upload Urls' do
detail 'This feature was introduced in GitLab 12.4'
end
+
params do
requires :conan_package_reference, type: String, desc: 'Conan package ID'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
post 'packages/:conan_package_reference/upload_urls' do
authorize!(:read_package, project)
status 200
- upload_urls = package_upload_urls(::Packages::Conan::FileMetadatum::PACKAGE_FILES)
-
- present upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
+ present package_upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
end
desc 'Recipe Upload Urls' do
detail 'This feature was introduced in GitLab 12.4'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
post 'upload_urls' do
authorize!(:read_package, project)
status 200
- upload_urls = recipe_upload_urls(::Packages::Conan::FileMetadatum::RECIPE_FILES)
-
- present upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
+ present recipe_upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
end
desc 'Delete Package' do
detail 'This feature was introduced in GitLab 12.5'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
delete do
authorize!(:destroy_package, project)
@@ -239,7 +265,9 @@ module API
desc 'Download recipe files' do
detail 'This feature was introduced in GitLab 12.6'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get do
download_package_file(:recipe_file)
end
@@ -247,10 +275,13 @@ module API
desc 'Upload recipe package files' do
detail 'This feature was introduced in GitLab 12.6'
end
+
params do
use :workhorse_upload_params
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
put do
upload_package_file(:recipe_file)
end
@@ -258,7 +289,9 @@ module API
desc 'Workhorse authorize the conan recipe file' do
detail 'This feature was introduced in GitLab 12.6'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
put 'authorize' do
authorize_workhorse!(subject: project)
end
@@ -273,7 +306,9 @@ module API
desc 'Download package files' do
detail 'This feature was introduced in GitLab 12.5'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
get do
download_package_file(:package_file)
end
@@ -281,7 +316,9 @@ module API
desc 'Workhorse authorize the conan package file' do
detail 'This feature was introduced in GitLab 12.6'
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
put 'authorize' do
authorize_workhorse!(subject: project)
end
@@ -289,10 +326,13 @@ module API
desc 'Upload package files' do
detail 'This feature was introduced in GitLab 12.6'
end
+
params do
use :workhorse_upload_params
end
- route_setting :authentication, job_token_allowed: true
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
put do
upload_package_file(:package_file)
end
diff --git a/lib/api/entities/branch.rb b/lib/api/entities/branch.rb
index f9d06082ad6..6a75dcddeda 100644
--- a/lib/api/entities/branch.rb
+++ b/lib/api/entities/branch.rb
@@ -32,7 +32,7 @@ module API
end
expose :can_push do |repo_branch, options|
- Gitlab::UserAccess.new(options[:current_user], project: options[:project]).can_push_to_branch?(repo_branch.name)
+ Gitlab::UserAccess.new(options[:current_user], container: options[:project]).can_push_to_branch?(repo_branch.name)
end
expose :default do |repo_branch, options|
diff --git a/lib/api/entities/bridge.rb b/lib/api/entities/bridge.rb
deleted file mode 100644
index 8f0ee69399a..00000000000
--- a/lib/api/entities/bridge.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class Bridge < Entities::JobBasic
- expose :downstream_pipeline, with: Entities::PipelineBasic
- end
- end
-end
diff --git a/lib/api/entities/ci/bridge.rb b/lib/api/entities/ci/bridge.rb
new file mode 100644
index 00000000000..502d97fff90
--- /dev/null
+++ b/lib/api/entities/ci/bridge.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class Bridge < JobBasic
+ expose :downstream_pipeline, with: ::API::Entities::Ci::PipelineBasic
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/job.rb b/lib/api/entities/ci/job.rb
new file mode 100644
index 00000000000..7fe1a802e24
--- /dev/null
+++ b/lib/api/entities/ci/job.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class Job < JobBasic
+ # artifacts_file is included in job_artifacts, but kept for backward compatibility (remove in api/v5)
+ expose :artifacts_file, using: ::API::Entities::Ci::JobArtifactFile, if: -> (job, opts) { job.artifacts? }
+ expose :job_artifacts, as: :artifacts, using: ::API::Entities::Ci::JobArtifact
+ expose :runner, with: ::API::Entities::Runner
+ expose :artifacts_expire_at
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/job_artifact.rb b/lib/api/entities/ci/job_artifact.rb
new file mode 100644
index 00000000000..9e504aee383
--- /dev/null
+++ b/lib/api/entities/ci/job_artifact.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class JobArtifact < Grape::Entity
+ expose :file_type, :size, :filename, :file_format
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/job_artifact_file.rb b/lib/api/entities/ci/job_artifact_file.rb
new file mode 100644
index 00000000000..418eb408ab6
--- /dev/null
+++ b/lib/api/entities/ci/job_artifact_file.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class JobArtifactFile < Grape::Entity
+ expose :filename
+ expose :cached_size, as: :size
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/job_basic.rb b/lib/api/entities/ci/job_basic.rb
new file mode 100644
index 00000000000..a29788c7abf
--- /dev/null
+++ b/lib/api/entities/ci/job_basic.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class JobBasic < Grape::Entity
+ expose :id, :status, :stage, :name, :ref, :tag, :coverage, :allow_failure
+ expose :created_at, :started_at, :finished_at
+ expose :duration
+ expose :user, with: ::API::Entities::User
+ expose :commit, with: ::API::Entities::Commit
+ expose :pipeline, with: ::API::Entities::Ci::PipelineBasic
+
+ expose :web_url do |job, _options|
+ Gitlab::Routing.url_helpers.project_job_url(job.project, job)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/job_basic_with_project.rb b/lib/api/entities/ci/job_basic_with_project.rb
new file mode 100644
index 00000000000..736e611e5b1
--- /dev/null
+++ b/lib/api/entities/ci/job_basic_with_project.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class JobBasicWithProject < Entities::Ci::JobBasic
+ expose :project, with: Entities::ProjectIdentity
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/pipeline.rb b/lib/api/entities/ci/pipeline.rb
new file mode 100644
index 00000000000..3dd3b9c9eff
--- /dev/null
+++ b/lib/api/entities/ci/pipeline.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class Pipeline < PipelineBasic
+ expose :before_sha, :tag, :yaml_errors
+
+ expose :user, with: Entities::UserBasic
+ expose :created_at, :updated_at, :started_at, :finished_at, :committed_at
+ expose :duration
+ expose :coverage
+ expose :detailed_status, using: DetailedStatusEntity do |pipeline, options|
+ pipeline.detailed_status(options[:current_user])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/pipeline_basic.rb b/lib/api/entities/ci/pipeline_basic.rb
new file mode 100644
index 00000000000..dbb9b828757
--- /dev/null
+++ b/lib/api/entities/ci/pipeline_basic.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class PipelineBasic < Grape::Entity
+ expose :id, :sha, :ref, :status
+ expose :created_at, :updated_at
+
+ expose :web_url do |pipeline, _options|
+ Gitlab::Routing.url_helpers.project_pipeline_url(pipeline.project, pipeline)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/pipeline_schedule.rb b/lib/api/entities/ci/pipeline_schedule.rb
new file mode 100644
index 00000000000..f1596b7d285
--- /dev/null
+++ b/lib/api/entities/ci/pipeline_schedule.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class PipelineSchedule < Grape::Entity
+ expose :id
+ expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active
+ expose :created_at, :updated_at
+ expose :owner, using: ::API::Entities::UserBasic
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/pipeline_schedule_details.rb b/lib/api/entities/ci/pipeline_schedule_details.rb
new file mode 100644
index 00000000000..b233728b95b
--- /dev/null
+++ b/lib/api/entities/ci/pipeline_schedule_details.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class PipelineScheduleDetails < PipelineSchedule
+ expose :last_pipeline, using: ::API::Entities::Ci::PipelineBasic
+ expose :variables, using: ::API::Entities::Ci::Variable
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/variable.rb b/lib/api/entities/ci/variable.rb
new file mode 100644
index 00000000000..f4d5248245a
--- /dev/null
+++ b/lib/api/entities/ci/variable.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ci
+ class Variable < Grape::Entity
+ expose :variable_type, :key, :value
+ expose :protected?, as: :protected, if: -> (entity, _) { entity.respond_to?(:protected?) }
+ expose :masked?, as: :masked, if: -> (entity, _) { entity.respond_to?(:masked?) }
+ expose :environment_scope, if: -> (entity, _) { entity.respond_to?(:environment_scope) }
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/commit_detail.rb b/lib/api/entities/commit_detail.rb
index 22424b38bb9..61238102e9d 100644
--- a/lib/api/entities/commit_detail.rb
+++ b/lib/api/entities/commit_detail.rb
@@ -9,7 +9,7 @@ module API
expose :last_pipeline do |commit, options|
pipeline = commit.last_pipeline if can_read_pipeline?
- ::API::Entities::PipelineBasic.represent(pipeline, options)
+ ::API::Entities::Ci::PipelineBasic.represent(pipeline, options)
end
private
diff --git a/lib/api/entities/deployment.rb b/lib/api/entities/deployment.rb
index 3a97d3e3c09..4e3a4c289d9 100644
--- a/lib/api/entities/deployment.rb
+++ b/lib/api/entities/deployment.rb
@@ -6,7 +6,7 @@ module API
expose :id, :iid, :ref, :sha, :created_at, :updated_at
expose :user, using: Entities::UserBasic
expose :environment, using: Entities::EnvironmentBasic
- expose :deployable, using: Entities::Job
+ expose :deployable, using: Entities::Ci::Job
expose :status
end
end
diff --git a/lib/api/entities/event.rb b/lib/api/entities/event.rb
index 8fd0bac13f4..f750d728e03 100644
--- a/lib/api/entities/event.rb
+++ b/lib/api/entities/event.rb
@@ -3,6 +3,7 @@
module API
module Entities
class Event < Grape::Entity
+ expose :id
expose :project_id, :action_name
expose :target_id, :target_iid, :target_type, :author_id
expose :target_title
diff --git a/lib/api/entities/feature.rb b/lib/api/entities/feature.rb
index 3c9182340ea..618a7be9c7b 100644
--- a/lib/api/entities/feature.rb
+++ b/lib/api/entities/feature.rb
@@ -10,7 +10,7 @@ module API
value = model.gate_values[gate.key]
# By default all gate values are populated. Only show relevant ones.
- if (value.is_a?(Integer) && value.zero?) || (value.is_a?(Set) && value.empty?)
+ if (value.is_a?(Integer) && value == 0) || (value.is_a?(Set) && value.empty?)
next
end
diff --git a/lib/api/entities/job.rb b/lib/api/entities/job.rb
deleted file mode 100644
index cbee8794007..00000000000
--- a/lib/api/entities/job.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class Job < Entities::JobBasic
- # artifacts_file is included in job_artifacts, but kept for backward compatibility (remove in api/v5)
- expose :artifacts_file, using: Entities::JobArtifactFile, if: -> (job, opts) { job.artifacts? }
- expose :job_artifacts, as: :artifacts, using: Entities::JobArtifact
- expose :runner, with: Entities::Runner
- expose :artifacts_expire_at
- end
- end
-end
diff --git a/lib/api/entities/job_artifact.rb b/lib/api/entities/job_artifact.rb
deleted file mode 100644
index 94dbdb38fee..00000000000
--- a/lib/api/entities/job_artifact.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class JobArtifact < Grape::Entity
- expose :file_type, :size, :filename, :file_format
- end
- end
-end
diff --git a/lib/api/entities/job_artifact_file.rb b/lib/api/entities/job_artifact_file.rb
deleted file mode 100644
index fa2851a7f0e..00000000000
--- a/lib/api/entities/job_artifact_file.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class JobArtifactFile < Grape::Entity
- expose :filename
- expose :cached_size, as: :size
- end
- end
-end
diff --git a/lib/api/entities/job_basic.rb b/lib/api/entities/job_basic.rb
deleted file mode 100644
index a8541039934..00000000000
--- a/lib/api/entities/job_basic.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class JobBasic < Grape::Entity
- expose :id, :status, :stage, :name, :ref, :tag, :coverage, :allow_failure
- expose :created_at, :started_at, :finished_at
- expose :duration
- expose :user, with: Entities::User
- expose :commit, with: Entities::Commit
- expose :pipeline, with: Entities::PipelineBasic
-
- expose :web_url do |job, _options|
- Gitlab::Routing.url_helpers.project_job_url(job.project, job)
- end
- end
- end
-end
diff --git a/lib/api/entities/job_basic_with_project.rb b/lib/api/entities/job_basic_with_project.rb
deleted file mode 100644
index 09387e045ec..00000000000
--- a/lib/api/entities/job_basic_with_project.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class JobBasicWithProject < Entities::JobBasic
- expose :project, with: Entities::ProjectIdentity
- end
- end
-end
diff --git a/lib/api/entities/job_request/dependency.rb b/lib/api/entities/job_request/dependency.rb
index 64d779f6575..7d6ec832ba1 100644
--- a/lib/api/entities/job_request/dependency.rb
+++ b/lib/api/entities/job_request/dependency.rb
@@ -5,7 +5,7 @@ module API
module JobRequest
class Dependency < Grape::Entity
expose :id, :name, :token
- expose :artifacts_file, using: Entities::JobArtifactFile, if: ->(job, _) { job.artifacts? }
+ expose :artifacts_file, using: Entities::Ci::JobArtifactFile, if: ->(job, _) { job.artifacts? }
end
end
end
diff --git a/lib/api/entities/job_request/response.rb b/lib/api/entities/job_request/response.rb
index fdacd3af2da..8db9aff3dc9 100644
--- a/lib/api/entities/job_request/response.rb
+++ b/lib/api/entities/job_request/response.rb
@@ -33,3 +33,5 @@ module API
end
end
end
+
+API::Entities::JobRequest::Response.prepend_if_ee('EE::API::Entities::JobRequest::Response')
diff --git a/lib/api/entities/merge_request.rb b/lib/api/entities/merge_request.rb
index 7fc76a4071e..05ae041c7a9 100644
--- a/lib/api/entities/merge_request.rb
+++ b/lib/api/entities/merge_request.rb
@@ -23,11 +23,11 @@ module API
merge_request.metrics&.first_deployed_to_production_at
end
- expose :pipeline, using: Entities::PipelineBasic, if: -> (_, options) { build_available?(options) } do |merge_request, _options|
+ expose :pipeline, using: Entities::Ci::PipelineBasic, if: -> (_, options) { build_available?(options) } do |merge_request, _options|
merge_request.metrics&.pipeline
end
- expose :head_pipeline, using: 'API::Entities::Pipeline', if: -> (_, options) do
+ expose :head_pipeline, using: '::API::Entities::Ci::Pipeline', if: -> (_, options) do
Ability.allowed?(options[:current_user], :read_pipeline, options[:project])
end
diff --git a/lib/api/entities/package.rb b/lib/api/entities/package.rb
index 73473f16da9..670965b225c 100644
--- a/lib/api/entities/package.rb
+++ b/lib/api/entities/package.rb
@@ -13,9 +13,7 @@ module API
expose :_links do
expose :web_path do |package|
- if ::Gitlab.ee?
- ::Gitlab::Routing.url_helpers.project_package_path(package.project, package)
- end
+ ::Gitlab::Routing.url_helpers.project_package_path(package.project, package)
end
expose :delete_api_path, if: can_destroy(:package, &:project) do |package|
diff --git a/lib/api/entities/package/pipeline.rb b/lib/api/entities/package/pipeline.rb
index e91a12e47fa..0aa888e30ee 100644
--- a/lib/api/entities/package/pipeline.rb
+++ b/lib/api/entities/package/pipeline.rb
@@ -3,7 +3,7 @@
module API
module Entities
class Package < Grape::Entity
- class Pipeline < ::API::Entities::PipelineBasic
+ class Pipeline < ::API::Entities::Ci::PipelineBasic
expose :user, using: ::API::Entities::UserBasic
end
end
diff --git a/lib/api/entities/personal_access_token.rb b/lib/api/entities/personal_access_token.rb
index d6fb9af6ab3..3846929c903 100644
--- a/lib/api/entities/personal_access_token.rb
+++ b/lib/api/entities/personal_access_token.rb
@@ -3,7 +3,7 @@
module API
module Entities
class PersonalAccessToken < Grape::Entity
- expose :id, :name, :revoked, :created_at, :scopes
+ expose :id, :name, :revoked, :created_at, :scopes, :user_id
expose :active?, as: :active
expose :expires_at do |personal_access_token|
personal_access_token.expires_at ? personal_access_token.expires_at.strftime("%Y-%m-%d") : nil
diff --git a/lib/api/entities/pipeline.rb b/lib/api/entities/pipeline.rb
deleted file mode 100644
index 778efbe4bcc..00000000000
--- a/lib/api/entities/pipeline.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class Pipeline < Entities::PipelineBasic
- expose :before_sha, :tag, :yaml_errors
-
- expose :user, with: Entities::UserBasic
- expose :created_at, :updated_at, :started_at, :finished_at, :committed_at
- expose :duration
- expose :coverage
- expose :detailed_status, using: DetailedStatusEntity do |pipeline, options|
- pipeline.detailed_status(options[:current_user])
- end
- end
- end
-end
diff --git a/lib/api/entities/pipeline_basic.rb b/lib/api/entities/pipeline_basic.rb
deleted file mode 100644
index 359f6a447ab..00000000000
--- a/lib/api/entities/pipeline_basic.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class PipelineBasic < Grape::Entity
- expose :id, :sha, :ref, :status
- expose :created_at, :updated_at
-
- expose :web_url do |pipeline, _options|
- Gitlab::Routing.url_helpers.project_pipeline_url(pipeline.project, pipeline)
- end
- end
- end
-end
diff --git a/lib/api/entities/pipeline_schedule.rb b/lib/api/entities/pipeline_schedule.rb
deleted file mode 100644
index a72fe3f3141..00000000000
--- a/lib/api/entities/pipeline_schedule.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class PipelineSchedule < Grape::Entity
- expose :id
- expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active
- expose :created_at, :updated_at
- expose :owner, using: Entities::UserBasic
- end
- end
-end
diff --git a/lib/api/entities/pipeline_schedule_details.rb b/lib/api/entities/pipeline_schedule_details.rb
deleted file mode 100644
index 5e54489a0f9..00000000000
--- a/lib/api/entities/pipeline_schedule_details.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class PipelineScheduleDetails < Entities::PipelineSchedule
- expose :last_pipeline, using: Entities::PipelineBasic
- expose :variables, using: Entities::Variable
- end
- end
-end
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index e3c5177cd0b..fb599d68d72 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -35,6 +35,7 @@ module API
end
end
+ expose :packages_enabled
expose :empty_repo?, as: :empty_repo
expose :archived?, as: :archived
expose :visibility
diff --git a/lib/api/entities/project_hook.rb b/lib/api/entities/project_hook.rb
index cdd3714ed64..751f9500252 100644
--- a/lib/api/entities/project_hook.rb
+++ b/lib/api/entities/project_hook.rb
@@ -4,7 +4,7 @@ module API
module Entities
class ProjectHook < Hook
expose :project_id, :issues_events, :confidential_issues_events
- expose :note_events, :confidential_note_events, :pipeline_events, :wiki_page_events
+ expose :note_events, :confidential_note_events, :pipeline_events, :wiki_page_events, :deployment_events
expose :job_events
expose :push_events_branch_filter
end
diff --git a/lib/api/entities/user_details_with_admin.rb b/lib/api/entities/user_details_with_admin.rb
index 22a842983e2..e48b1da7859 100644
--- a/lib/api/entities/user_details_with_admin.rb
+++ b/lib/api/entities/user_details_with_admin.rb
@@ -6,6 +6,7 @@ module API
expose :highest_role
expose :current_sign_in_ip
expose :last_sign_in_ip
+ expose :sign_in_count
end
end
end
diff --git a/lib/api/entities/variable.rb b/lib/api/entities/variable.rb
deleted file mode 100644
index 6705df30b2e..00000000000
--- a/lib/api/entities/variable.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module API
- module Entities
- class Variable < Grape::Entity
- expose :variable_type, :key, :value
- expose :protected?, as: :protected, if: -> (entity, _) { entity.respond_to?(:protected?) }
- expose :masked?, as: :masked, if: -> (entity, _) { entity.respond_to?(:masked?) }
- expose :environment_scope, if: -> (entity, _) { entity.respond_to?(:environment_scope) }
- end
- end
-end
diff --git a/lib/api/group_variables.rb b/lib/api/group_variables.rb
index d3ca1c79e73..e7b8cd10197 100644
--- a/lib/api/group_variables.rb
+++ b/lib/api/group_variables.rb
@@ -13,18 +13,18 @@ module API
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get group-level variables' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
use :pagination
end
get ':id/variables' do
variables = user_group.variables
- present paginate(variables), with: Entities::Variable
+ present paginate(variables), with: Entities::Ci::Variable
end
desc 'Get a specific variable from a group' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key, type: String, desc: 'The key of the variable'
@@ -36,12 +36,12 @@ module API
break not_found!('GroupVariable') unless variable
- present variable, with: Entities::Variable
+ present variable, with: Entities::Ci::Variable
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Create a new variable in a group' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key, type: String, desc: 'The key of the variable'
@@ -51,19 +51,21 @@ module API
optional :variable_type, type: String, values: ::Ci::GroupVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file. Defaults to env_var'
end
post ':id/variables' do
- variable_params = declared_params(include_missing: false)
-
- variable = user_group.variables.create(variable_params)
+ variable = ::Ci::ChangeVariableService.new(
+ container: user_group,
+ current_user: current_user,
+ params: { action: :create, variable_params: declared_params(include_missing: false) }
+ ).execute
if variable.valid?
- present variable, with: Entities::Variable
+ present variable, with: Entities::Ci::Variable
else
render_validation_error!(variable)
end
end
desc 'Update an existing variable from a group' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
optional :key, type: String, desc: 'The key of the variable'
@@ -74,32 +76,41 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
put ':id/variables/:key' do
- variable = user_group.variables.find_by(key: params[:key])
-
- break not_found!('GroupVariable') unless variable
-
- variable_params = declared_params(include_missing: false).except(:key)
+ variable = ::Ci::ChangeVariableService.new(
+ container: user_group,
+ current_user: current_user,
+ params: { action: :update, variable_params: declared_params(include_missing: false) }
+ ).execute
- if variable.update(variable_params)
- present variable, with: Entities::Variable
+ if variable.valid?
+ present variable, with: Entities::Ci::Variable
else
render_validation_error!(variable)
end
+ rescue ::ActiveRecord::RecordNotFound
+ not_found!('GroupVariable')
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Delete an existing variable from a group' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key, type: String, desc: 'The key of the variable'
end
# rubocop: disable CodeReuse/ActiveRecord
delete ':id/variables/:key' do
- variable = user_group.variables.find_by(key: params[:key])
- not_found!('GroupVariable') unless variable
-
- destroy_conditionally!(variable)
+ variable = user_group.variables.find_by!(key: params[:key])
+
+ destroy_conditionally!(variable) do |target_variable|
+ ::Ci::ChangeVariableService.new(
+ container: user_group,
+ current_user: current_user,
+ params: { action: :destroy, variable_params: declared_params(include_missing: false) }
+ ).execute
+ end
+ rescue ::ActiveRecord::RecordNotFound
+ not_found!('GroupVariable')
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 9ac3ac818fc..813e41b4d39 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -76,7 +76,7 @@ module API
params: project_finder_params,
options: finder_options
).execute
- projects = reorder_projects(projects)
+ projects = reorder_projects_with_similarity_order_support(group, projects)
paginate(projects)
end
@@ -112,6 +112,24 @@ module API
accepted!
end
+
+ def reorder_projects_with_similarity_order_support(group, projects)
+ return handle_similarity_order(group, projects) if params[:order_by] == 'similarity'
+
+ reorder_projects(projects)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def handle_similarity_order(group, projects)
+ if params[:search].present? && Feature.enabled?(:similarity_search, group, default_enabled: true)
+ projects.sorted_by_similarity_desc(params[:search])
+ else
+ order_options = { name: :asc }
+ order_options['id'] ||= params[:sort] || 'asc'
+ projects.reorder(order_options)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
resource :groups do
@@ -222,7 +240,7 @@ module API
optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values,
desc: 'Limit by visibility'
optional :search, type: String, desc: 'Return list of authorized projects matching the search criteria'
- optional :order_by, type: String, values: %w[id name path created_at updated_at last_activity_at],
+ optional :order_by, type: String, values: %w[id name path created_at updated_at last_activity_at similarity],
default: 'created_at', desc: 'Return projects ordered by field'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return projects sorted in ascending and descending order'
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 01b89959c14..599d5bd0baf 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -404,6 +404,10 @@ module API
render_api_error!(message || '409 Conflict', 409)
end
+ def unprocessable_entity!(message = nil)
+ render_api_error!(message || '422 Unprocessable Entity', :unprocessable_entity)
+ end
+
def file_too_large!
render_api_error!('413 Request Entity Too Large', 413)
end
@@ -555,8 +559,8 @@ module API
finder_params[:search_namespaces] = true if params[:search_namespaces].present?
finder_params[:user] = params.delete(:user) if params[:user]
finder_params[:custom_attributes] = params[:custom_attributes] if params[:custom_attributes]
- finder_params[:id_after] = params[:id_after] if params[:id_after]
- finder_params[:id_before] = params[:id_before] if params[:id_before]
+ finder_params[:id_after] = sanitize_id_param(params[:id_after]) if params[:id_after]
+ finder_params[:id_before] = sanitize_id_param(params[:id_before]) if params[:id_before]
finder_params[:last_activity_after] = params[:last_activity_after] if params[:last_activity_after]
finder_params[:last_activity_before] = params[:last_activity_before] if params[:last_activity_before]
finder_params[:repository_storage] = params[:repository_storage] if params[:repository_storage]
@@ -655,6 +659,10 @@ module API
def ip_address
env["action_dispatch.remote_ip"].to_s || request.ip
end
+
+ def sanitize_id_param(id)
+ id.present? ? id.to_i : nil
+ end
end
end
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index b69930b447c..b7ce1eba3f9 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -117,7 +117,7 @@ module API
return unless %w[git-receive-pack git-upload-pack git-upload-archive].include?(action)
{
- repository: repository.gitaly_repository,
+ repository: repository.gitaly_repository.to_h,
address: Gitlab::GitalyClient.address(repository.shard),
token: Gitlab::GitalyClient.token(repository.shard),
features: Feature::Gitaly.server_feature_flags
diff --git a/lib/api/helpers/merge_requests_helpers.rb b/lib/api/helpers/merge_requests_helpers.rb
index 4d5350498a7..e4163c63575 100644
--- a/lib/api/helpers/merge_requests_helpers.rb
+++ b/lib/api/helpers/merge_requests_helpers.rb
@@ -4,6 +4,9 @@ module API
module Helpers
module MergeRequestsHelpers
extend Grape::API::Helpers
+ extend ActiveSupport::Concern
+
+ UNPROCESSABLE_ERROR_KEYS = [:project_access, :branch_conflict, :validate_fork, :base].freeze
params :merge_requests_negatable_params do
optional :author_id, type: Integer, desc: 'Return merge requests which are authored by the user with the given ID'
@@ -79,6 +82,20 @@ module API
default: 'created_by_me',
desc: 'Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`'
end
+
+ def handle_merge_request_errors!(merge_request)
+ return if merge_request.valid?
+
+ errors = merge_request.errors
+
+ UNPROCESSABLE_ERROR_KEYS.each do |error|
+ unprocessable_entity!(errors[error]) if errors.has_key?(error)
+ end
+
+ conflict!(errors[:validate_branches]) if errors.has_key?(:validate_branches)
+
+ render_validation_error!(merge_request)
+ end
end
end
end
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index f88624ed63e..f61bcfe963e 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -17,8 +17,9 @@ module API
authorize! :admin_note, note
opts = {
- note: params[:body]
- }
+ note: params[:body],
+ confidential: params[:confidential]
+ }.compact
parent = noteable_parent(noteable)
project = parent if parent.is_a?(Project)
diff --git a/lib/api/helpers/packages/basic_auth_helpers.rb b/lib/api/helpers/packages/basic_auth_helpers.rb
index 835b5f4614c..e35a8712131 100644
--- a/lib/api/helpers/packages/basic_auth_helpers.rb
+++ b/lib/api/helpers/packages/basic_auth_helpers.rb
@@ -4,6 +4,8 @@ module API
module Helpers
module Packages
module BasicAuthHelpers
+ extend ::Gitlab::Utils::Override
+
module Constants
AUTHENTICATE_REALM_HEADER = 'Www-Authenticate: Basic realm'
AUTHENTICATE_REALM_NAME = 'GitLab Packages Registry'
@@ -11,10 +13,6 @@ module API
include Constants
- def find_personal_access_token
- find_personal_access_token_from_http_basic_auth
- end
-
def unauthorized_user_project
@unauthorized_user_project ||= find_project(params[:id])
end
@@ -44,12 +42,13 @@ module API
end
def unauthorized_or!
- current_user ? yield : unauthorized_with_header!
+ current_user ? yield : unauthorized!
end
- def unauthorized_with_header!
+ override :unauthorized!
+ def unauthorized!
header(AUTHENTICATE_REALM_HEADER, AUTHENTICATE_REALM_NAME)
- unauthorized!
+ super
end
end
end
diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb
index 30e690a5a1d..a5fde1af41e 100644
--- a/lib/api/helpers/packages/conan/api_helpers.rb
+++ b/lib/api/helpers/packages/conan/api_helpers.rb
@@ -28,22 +28,30 @@ module API
present_download_urls(::API::Entities::ConanPackage::ConanRecipeManifest, &:recipe_urls)
end
- def recipe_upload_urls(file_names)
+ def recipe_upload_urls
{ upload_urls: Hash[
- file_names.collect do |file_name|
+ file_names.select(&method(:recipe_file?)).map do |file_name|
[file_name, recipe_file_upload_url(file_name)]
end
] }
end
- def package_upload_urls(file_names)
+ def package_upload_urls
{ upload_urls: Hash[
- file_names.collect do |file_name|
+ file_names.select(&method(:package_file?)).map do |file_name|
[file_name, package_file_upload_url(file_name)]
end
] }
end
+ def recipe_file?(file_name)
+ file_name.in?(::Packages::Conan::FileMetadatum::RECIPE_FILES)
+ end
+
+ def package_file?(file_name)
+ file_name.in?(::Packages::Conan::FileMetadatum::PACKAGE_FILES)
+ end
+
def package_file_upload_url(file_name)
expose_url(
api_v4_packages_conan_v1_files_package_path(
@@ -130,6 +138,14 @@ module API
end
end
+ def file_names
+ json_payload = Gitlab::Json.parse(request.body.string)
+
+ bad_request!(nil) unless json_payload.is_a?(Hash)
+
+ json_payload.keys
+ end
+
def create_package_file_with_type(file_type, current_package)
unless params['file.size'] == 0
# conan sends two upload requests, the first has no file, so we skip record creation if file.size == 0
diff --git a/lib/api/helpers/packages_manager_clients_helpers.rb b/lib/api/helpers/packages_manager_clients_helpers.rb
index 7b5d0dd708d..ae16b65aaa8 100644
--- a/lib/api/helpers/packages_manager_clients_helpers.rb
+++ b/lib/api/helpers/packages_manager_clients_helpers.rb
@@ -16,16 +16,6 @@ module API
optional 'file.sha256', type: String, desc: 'SHA256 checksum of the file (generated by Workhorse)'
end
- def find_personal_access_token_from_http_basic_auth
- return unless headers
-
- token = decode_token
-
- return unless token
-
- PersonalAccessToken.find_by_token(token)
- end
-
def find_job_from_http_basic_auth
return unless headers
diff --git a/lib/api/helpers/pagination_strategies.rb b/lib/api/helpers/pagination_strategies.rb
index 823891d6fe7..61cff37e4ab 100644
--- a/lib/api/helpers/pagination_strategies.rb
+++ b/lib/api/helpers/pagination_strategies.rb
@@ -48,7 +48,7 @@ module API
end
def offset_limit_exceeded?(offset_limit)
- offset_limit.positive? && params[:page] * params[:per_page] > offset_limit
+ offset_limit > 0 && params[:page] * params[:per_page] > offset_limit
end
end
end
diff --git a/lib/api/helpers/performance_bar_helpers.rb b/lib/api/helpers/performance_bar_helpers.rb
new file mode 100644
index 00000000000..8430e889dff
--- /dev/null
+++ b/lib/api/helpers/performance_bar_helpers.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module PerformanceBarHelpers
+ def set_peek_enabled_for_current_request
+ Gitlab::SafeRequestStore.fetch(:peek_enabled) { perf_bar_cookie_enabled? && perf_bar_enabled_for_user? }
+ end
+
+ def perf_bar_cookie_enabled?
+ cookies[:perf_bar_enabled] == 'true'
+ end
+
+ def perf_bar_enabled_for_user?
+ # We cannot use `current_user` here because that method raises an exception when the user
+ # is unauthorized and some API endpoints require that `current_user` is not called.
+ Gitlab::PerformanceBar.enabled_for_user?(find_user_from_sources)
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 76e5bb95c4d..8c20f5b8fc2 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -61,6 +61,7 @@ module API
optional :auto_devops_deploy_strategy, type: String, values: %w(continuous manual timed_incremental), desc: 'Auto Deploy strategy'
optional :autoclose_referenced_issues, type: Boolean, desc: 'Flag indication if referenced issues auto-closing is enabled'
optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins'
+ optional :packages_enabled, type: Boolean, desc: 'Enable project packages feature'
end
params :optional_project_params_ee do
@@ -137,6 +138,7 @@ module API
:suggestion_commit_message,
:repository_storage,
:compliance_framework_setting,
+ :packages_enabled,
:service_desk_enabled,
# TODO: remove in API v5, replaced by *_access_level
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index d4870b96575..ff938358439 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -247,15 +247,15 @@ module API
required: true,
name: :project_url,
type: String,
- desc: 'The buildkite project URL'
+ desc: 'The Buildkite pipeline URL'
},
{
required: false,
name: :enable_ssl_verification,
type: Boolean,
- desc: 'Enable SSL verification for communication'
+ desc: 'DEPRECATED: This parameter has no effect since SSL verification will always be enabled'
}
- ],
+ ],
'campfire' => [
{
required: true,
diff --git a/lib/api/helpers/snippets_helpers.rb b/lib/api/helpers/snippets_helpers.rb
index f95d066bd7c..79367da8d1f 100644
--- a/lib/api/helpers/snippets_helpers.rb
+++ b/lib/api/helpers/snippets_helpers.rb
@@ -10,6 +10,23 @@ module API
requires :ref, type: String, desc: 'The name of branch, tag or commit'
end
+ params :create_file_params do
+ optional :files, type: Array, desc: 'An array of files' do
+ requires :file_path, type: String, file_path: true, allow_blank: false, desc: 'The path of a snippet file'
+ requires :content, type: String, allow_blank: false, desc: 'The content of a snippet file'
+ end
+
+ optional :content, type: String, allow_blank: false, desc: 'The content of a snippet'
+
+ given :content do
+ requires :file_name, type: String, desc: 'The name of a snippet file'
+ end
+
+ mutually_exclusive :files, :content
+
+ exactly_one_of :files, :content
+ end
+
def content_for(snippet)
if snippet.empty_repo?
env['api.format'] = :txt
@@ -35,5 +52,12 @@ module API
send_git_blob(repo, blob)
end
end
+
+ def process_file_args(args)
+ args[:snippet_actions] = args.delete(:files)&.map do |file|
+ file[:action] = :create
+ file.symbolize_keys
+ end
+ end
end
end
diff --git a/lib/api/import_github.rb b/lib/api/import_github.rb
index 1e839816006..0bab891eada 100644
--- a/lib/api/import_github.rb
+++ b/lib/api/import_github.rb
@@ -10,7 +10,11 @@ module API
helpers do
def client
- @client ||= Gitlab::LegacyGithubImport::Client.new(params[:personal_access_token], client_options)
+ @client ||= if Feature.enabled?(:remove_legacy_github_client)
+ Gitlab::GithubImport::Client.new(params[:personal_access_token])
+ else
+ Gitlab::LegacyGithubImport::Client.new(params[:personal_access_token], client_options)
+ end
end
def access_params
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index 6d4a4fc9c8b..17599c72243 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -18,6 +18,10 @@ module API
UNKNOWN_CHECK_RESULT_ERROR = 'Unknown check result'.freeze
+ VALID_PAT_SCOPES = Set.new(
+ Gitlab::Auth::API_SCOPES + Gitlab::Auth::REPOSITORY_SCOPES + Gitlab::Auth::REGISTRY_SCOPES
+ ).freeze
+
helpers do
def response_with_status(code: 200, success: true, message: nil, **extra_options)
status code
@@ -67,7 +71,7 @@ module API
"uploadpack.allowAnySHA1InWant=true"],
gitaly: gitaly_payload(params[:action]),
gl_console_messages: check_result.console_messages
- }
+ }.merge!(actor.key_details)
# Custom option for git-receive-pack command
@@ -92,7 +96,7 @@ module API
# If we have created a project directly from a git push
# we have to assign its value to both @project and @container
- @project = @container = access_checker.project
+ @project = @container = access_checker.container
end
end
end
@@ -194,6 +198,60 @@ module API
{ success: true, recovery_codes: codes }
end
+ post '/personal_access_token' do
+ status 200
+
+ actor.update_last_used_at!
+ user = actor.user
+
+ if params[:key_id]
+ unless actor.key
+ break { success: false, message: 'Could not find the given key' }
+ end
+
+ if actor.key.is_a?(DeployKey)
+ break { success: false, message: 'Deploy keys cannot be used to create personal access tokens' }
+ end
+
+ unless user
+ break { success: false, message: 'Could not find a user for the given key' }
+ end
+ elsif params[:user_id] && user.nil?
+ break { success: false, message: 'Could not find the given user' }
+ end
+
+ if params[:name].blank?
+ break { success: false, message: "No token name specified" }
+ end
+
+ if params[:scopes].blank?
+ break { success: false, message: "No token scopes specified" }
+ end
+
+ invalid_scope = params[:scopes].find { |scope| VALID_PAT_SCOPES.exclude?(scope.to_sym) }
+
+ if invalid_scope
+ valid_scopes = VALID_PAT_SCOPES.map(&:to_s).sort
+ break { success: false, message: "Invalid scope: '#{invalid_scope}'. Valid scopes are: #{valid_scopes}" }
+ end
+
+ begin
+ expires_at = params[:expires_at].presence && Date.parse(params[:expires_at])
+ rescue ArgumentError
+ break { success: false, message: "Invalid token expiry date: '#{params[:expires_at]}'" }
+ end
+
+ access_token = nil
+
+ ::Users::UpdateService.new(current_user, user: user).execute! do |user|
+ access_token = user.personal_access_tokens.create!(
+ name: params[:name], scopes: params[:scopes], expires_at: expires_at
+ )
+ end
+
+ { success: true, token: access_token.token, scopes: access_token.scopes, expires_at: access_token.expires_at }
+ end
+
post '/pre_receive' do
status 200
diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb
new file mode 100644
index 00000000000..7f64fd7efe3
--- /dev/null
+++ b/lib/api/internal/kubernetes.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module API
+ # Kubernetes Internal API
+ module Internal
+ class Kubernetes < Grape::API::Instance
+ helpers do
+ def agent_token
+ @agent_token ||= cluster_agent_token_from_authorization_token
+ end
+
+ def agent
+ @agent ||= agent_token.agent
+ end
+
+ def repo_type
+ Gitlab::GlRepository::PROJECT
+ end
+
+ def gitaly_info(project)
+ shard = repo_type.repository_for(project).shard
+ {
+ address: Gitlab::GitalyClient.address(shard),
+ token: Gitlab::GitalyClient.token(shard),
+ features: Feature::Gitaly.server_feature_flags
+ }
+ end
+
+ def gitaly_repository(project)
+ {
+ storage_name: project.repository_storage,
+ relative_path: project.disk_path + '.git',
+ gl_repository: repo_type.identifier_for_container(project),
+ gl_project_path: repo_type.repository_for(project).full_path
+ }
+ end
+
+ def check_feature_enabled
+ not_found! unless Feature.enabled?(:kubernetes_agent_internal_api)
+ end
+
+ def check_agent_token
+ forbidden! unless agent_token
+ end
+ end
+
+ namespace 'internal' do
+ namespace 'kubernetes' do
+ before do
+ check_feature_enabled
+ check_agent_token
+ end
+
+ desc 'Gets agent info' do
+ detail 'Retrieves agent info for the given token'
+ end
+ route_setting :authentication, cluster_agent_token_allowed: true
+ get '/agent_info' do
+ project = agent.project
+
+ status 200
+ {
+ project_id: project.id,
+ agent_id: agent.id,
+ agent_name: agent.name,
+ gitaly_info: gitaly_info(project),
+ gitaly_repository: gitaly_repository(project)
+ }
+ end
+
+ desc 'Gets project info' do
+ detail 'Retrieves project info (if authorized)'
+ end
+ route_setting :authentication, cluster_agent_token_allowed: true
+ get '/project_info' do
+ project = find_project(params[:id])
+
+ # TODO sort out authorization for real
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/220912
+ if !project || !project.public?
+ not_found!
+ end
+
+ status 200
+ {
+ project_id: project.id,
+ gitaly_info: gitaly_info(project),
+ gitaly_repository: gitaly_repository(project)
+ }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 455511caabb..1694a967f26 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -55,6 +55,8 @@ module API
desc: 'Return issues ordered by `created_at` 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] << '',
+ 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`'
use :issues_stats_params
use :pagination
diff --git a/lib/api/job_artifacts.rb b/lib/api/job_artifacts.rb
index 61c279a76e9..bc7bc956580 100644
--- a/lib/api/job_artifacts.rb
+++ b/lib/api/job_artifacts.rb
@@ -94,7 +94,7 @@ module API
end
desc 'Keep the artifacts to prevent them from being deleted' do
- success Entities::Job
+ success ::API::Entities::Ci::Job
end
params do
requires :job_id, type: Integer, desc: 'The ID of a job'
@@ -109,7 +109,7 @@ module API
build.keep_artifacts!
status 200
- present build, with: Entities::Job
+ present build, with: ::API::Entities::Ci::Job
end
desc 'Delete the artifacts files from a job' do
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index bcc00429dd6..084c146abe7 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -30,7 +30,7 @@ module API
end
desc 'Get a projects jobs' do
- success Entities::Job
+ success Entities::Ci::Job
end
params do
use :optional_scope
@@ -44,12 +44,12 @@ module API
builds = filter_builds(builds, params[:scope])
builds = builds.preload(:user, :job_artifacts_archive, :job_artifacts, :runner, pipeline: :project)
- present paginate(builds), with: Entities::Job
+ present paginate(builds), with: Entities::Ci::Job
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Get pipeline jobs' do
- success Entities::Job
+ success Entities::Ci::Job
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
@@ -59,19 +59,19 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
get ':id/pipelines/:pipeline_id/jobs' do
authorize!(:read_pipeline, user_project)
- pipeline = user_project.ci_pipelines.find(params[:pipeline_id])
+ pipeline = user_project.all_pipelines.find(params[:pipeline_id])
authorize!(:read_build, pipeline)
builds = pipeline.builds
builds = filter_builds(builds, params[:scope])
builds = builds.preload(:job_artifacts_archive, :job_artifacts, project: [:namespace])
- present paginate(builds), with: Entities::Job
+ present paginate(builds), with: Entities::Ci::Job
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Get pipeline bridge jobs' do
- success Entities::Bridge
+ success ::API::Entities::Ci::Bridge
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
@@ -92,12 +92,12 @@ module API
project: [:namespace]
)
- present paginate(bridges), with: Entities::Bridge
+ present paginate(bridges), with: ::API::Entities::Ci::Bridge
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Get a specific job of a project' do
- success Entities::Job
+ success Entities::Ci::Job
end
params do
requires :job_id, type: Integer, desc: 'The ID of a job'
@@ -107,7 +107,7 @@ module API
build = find_build!(params[:job_id])
- present build, with: Entities::Job
+ present build, with: Entities::Ci::Job
end
# TODO: We should use `present_disk_file!` and leave this implementation for backward compatibility (when build trace
@@ -131,7 +131,7 @@ module API
end
desc 'Cancel a specific job of a project' do
- success Entities::Job
+ success Entities::Ci::Job
end
params do
requires :job_id, type: Integer, desc: 'The ID of a job'
@@ -144,11 +144,11 @@ module API
build.cancel
- present build, with: Entities::Job
+ present build, with: Entities::Ci::Job
end
desc 'Retry a specific build of a project' do
- success Entities::Job
+ success Entities::Ci::Job
end
params do
requires :job_id, type: Integer, desc: 'The ID of a build'
@@ -162,11 +162,11 @@ module API
build = ::Ci::Build.retry(build, current_user)
- present build, with: Entities::Job
+ present build, with: Entities::Ci::Job
end
desc 'Erase job (remove artifacts and the trace)' do
- success Entities::Job
+ success Entities::Ci::Job
end
params do
requires :job_id, type: Integer, desc: 'The ID of a build'
@@ -179,11 +179,11 @@ module API
break forbidden!('Job is not erasable!') unless build.erasable?
build.erase(erased_by: current_user)
- present build, with: Entities::Job
+ present build, with: Entities::Ci::Job
end
desc 'Trigger a actionable job (manual, delayed, etc)' do
- success Entities::Job
+ success Entities::Ci::Job
detail 'This feature was added in GitLab 8.11'
end
params do
@@ -200,7 +200,7 @@ module API
build.play(current_user)
status 200
- present build, with: Entities::Job
+ present build, with: Entities::Ci::Job
end
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 2e6ac40a593..6f25df720c4 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -97,7 +97,7 @@ module API
user_access = Gitlab::UserAccess.new(
current_user,
- project: merge_request.source_project
+ container: merge_request.source_project
)
forbidden!('Cannot push to source branch') unless
@@ -153,22 +153,6 @@ module API
include TimeTrackingEndpoints
helpers do
- def handle_merge_request_errors!(errors)
- if errors[:project_access].any?
- error!(errors[:project_access], 422)
- elsif errors[:branch_conflict].any?
- error!(errors[:branch_conflict], 422)
- elsif errors[:validate_fork].any?
- error!(errors[:validate_fork], 422)
- elsif errors[:validate_branches].any?
- conflict!(errors[:validate_branches])
- elsif errors[:base].any?
- error!(errors[:base], 422)
- end
-
- render_api_error!(errors, 400)
- end
-
params :optional_params do
optional :description, type: String, desc: 'The description of the merge request'
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
@@ -226,11 +210,9 @@ module API
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, mr_params).execute
- if merge_request.valid?
- present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
- else
- handle_merge_request_errors! merge_request.errors
- end
+ handle_merge_request_errors!(merge_request)
+
+ present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
end
desc 'Delete a merge request'
@@ -370,16 +352,16 @@ module API
end
desc 'Get the merge request pipelines' do
- success Entities::PipelineBasic
+ success Entities::Ci::PipelineBasic
end
get ':id/merge_requests/:merge_request_iid/pipelines' do
pipelines = merge_request_pipelines_with_access
- present paginate(pipelines), with: Entities::PipelineBasic
+ present paginate(pipelines), with: Entities::Ci::PipelineBasic
end
desc 'Create a pipeline for merge request' do
- success Entities::Pipeline
+ success ::API::Entities::Ci::Pipeline
end
post ':id/merge_requests/:merge_request_iid/pipelines' do
pipeline = ::MergeRequests::CreatePipelineService
@@ -390,7 +372,7 @@ module API
not_allowed!
elsif pipeline.persisted?
status :ok
- present pipeline, with: Entities::Pipeline
+ present pipeline, with: ::API::Entities::Ci::Pipeline
else
render_validation_error!(pipeline)
end
@@ -420,11 +402,9 @@ module API
merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, mr_params).execute(merge_request)
- if merge_request.valid?
- present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
- else
- handle_merge_request_errors! merge_request.errors
- end
+ handle_merge_request_errors!(merge_request)
+
+ present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
end
desc 'Merge a merge request' do
diff --git a/lib/api/milestone_responses.rb b/lib/api/milestone_responses.rb
index 8ff885983bc..b337b992841 100644
--- a/lib/api/milestone_responses.rb
+++ b/lib/api/milestone_responses.rb
@@ -14,10 +14,12 @@ module API
params :list_params do
optional :state, type: String, values: %w[active closed all], default: 'all',
- desc: 'Return "active", "closed", or "all" milestones'
+ desc: 'Return "active", "closed", or "all" milestones'
optional :iids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The IIDs of the milestones'
optional :title, type: String, desc: 'The title of the milestones'
optional :search, type: String, desc: 'The search criteria for the title or description of the milestone'
+ optional :include_parent_milestones, type: Grape::API::Boolean, default: false,
+ desc: 'Include group milestones from parent and its ancestors'
use :pagination
end
@@ -25,15 +27,18 @@ module API
requires :milestone_id, type: Integer, desc: 'The milestone ID number'
optional :title, type: String, desc: 'The title of the milestone'
optional :state_event, type: String, values: %w[close activate],
- desc: 'The state event of the milestone '
+ desc: 'The state event of the milestone '
use :optional_params
at_least_one_of :title, :description, :start_date, :due_date, :state_event
end
def list_milestones_for(parent)
- milestones = parent.milestones.order_id_desc
+ milestones = init_milestones_collection(parent)
milestones = Milestone.filter_by_state(milestones, params[:state])
- milestones = filter_by_iid(milestones, params[:iids]) if params[:iids].present?
+ if params[:iids].present? && !params[:include_parent_milestones]
+ milestones = filter_by_iid(milestones, params[:iids])
+ end
+
milestones = filter_by_title(milestones, params[:title]) if params[:title]
milestones = filter_by_search(milestones, params[:search]) if params[:search]
@@ -96,6 +101,41 @@ module API
[MergeRequestsFinder, Entities::MergeRequestBasic]
end
end
+
+ def init_milestones_collection(parent)
+ milestones = if params[:include_parent_milestones].present?
+ parent_and_ancestors_milestones(parent)
+ else
+ parent.milestones
+ end
+
+ milestones.order_id_desc
+ end
+
+ def parent_and_ancestors_milestones(parent)
+ project_id, group_ids = if parent.is_a?(Project)
+ [parent.id, project_group_ids(parent)]
+ else
+ [nil, parent_group_ids(parent)]
+ end
+
+ Milestone.for_projects_and_groups(project_id, group_ids)
+ end
+
+ def project_group_ids(parent)
+ group = parent.group
+ return unless group.present?
+
+ group.self_and_ancestors.select(:id)
+ end
+
+ def parent_group_ids(group)
+ return unless group.present?
+
+ group.self_and_ancestors
+ .public_or_visible_to_user(current_user)
+ .select(:id)
+ end
end
end
end
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index bfd09dcd496..e4989243f3d 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -101,7 +101,8 @@ module API
params do
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
requires :note_id, type: Integer, desc: 'The ID of a note'
- requires :body, type: String, desc: 'The content of a note'
+ optional :body, type: String, allow_blank: false, desc: 'The content of a note'
+ optional :confidential, type: Boolean, desc: 'Confidentiality note flag'
end
put ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
noteable = find_noteable(noteable_type, params[:noteable_id])
diff --git a/lib/api/nuget_packages.rb b/lib/api/nuget_packages.rb
index eb7d320a0f5..56c4de2071d 100644
--- a/lib/api/nuget_packages.rb
+++ b/lib/api/nuget_packages.rb
@@ -54,7 +54,9 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project', regexp: POSITIVE_INTEGER_REGEX
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
authorized_user_project
@@ -65,7 +67,9 @@ module API
desc 'The NuGet Service Index' do
detail 'This feature was introduced in GitLab 12.6'
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
get 'index', format: :json do
authorize_read_package!(authorized_user_project)
@@ -79,10 +83,13 @@ module API
desc 'The NuGet Package Publish endpoint' do
detail 'This feature was introduced in GitLab 12.6'
end
+
params do
requires :package, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
put do
authorize_upload!(authorized_user_project)
@@ -107,7 +114,9 @@ module API
forbidden!
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
put 'authorize' do
authorize_workhorse!(subject: authorized_user_project, has_length: false)
end
@@ -124,7 +133,9 @@ module API
desc 'The NuGet Metadata Service - Package name level' do
detail 'This feature was introduced in GitLab 12.8'
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
get 'index', format: :json do
present ::Packages::Nuget::PackagesMetadataPresenter.new(find_packages),
with: ::API::Entities::Nuget::PackagesMetadata
@@ -136,7 +147,9 @@ module API
params do
requires :package_version, type: String, desc: 'The NuGet package version', regexp: API::NO_SLASH_URL_PART_REGEX
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
get '*package_version', format: :json do
present ::Packages::Nuget::PackageMetadataPresenter.new(find_package),
with: ::API::Entities::Nuget::PackageMetadata
@@ -155,7 +168,9 @@ module API
desc 'The NuGet Content Service - index request' do
detail 'This feature was introduced in GitLab 12.8'
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
get 'index', format: :json do
present ::Packages::Nuget::PackagesVersionsPresenter.new(find_packages),
with: ::API::Entities::Nuget::PackagesVersions
@@ -168,7 +183,9 @@ module API
requires :package_version, type: String, desc: 'The NuGet package version', regexp: API::NO_SLASH_URL_PART_REGEX
requires :package_filename, type: String, desc: 'The NuGet package filename', regexp: API::NO_SLASH_URL_PART_REGEX
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
get '*package_version/*package_filename', format: :nupkg do
filename = "#{params[:package_filename]}.#{params[:format]}"
package_file = ::Packages::PackageFileFinder.new(find_package, filename, with_file_name_like: true)
@@ -198,7 +215,9 @@ module API
desc 'The NuGet Search Service' do
detail 'This feature was introduced in GitLab 12.8'
end
- route_setting :authentication, deploy_token_allowed: true
+
+ route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
+
get format: :json do
search_options = {
include_prerelease_versions: params[:prerelease],
diff --git a/lib/api/project_export.rb b/lib/api/project_export.rb
index d11c47f8d78..377d61689b3 100644
--- a/lib/api/project_export.rb
+++ b/lib/api/project_export.rb
@@ -47,6 +47,8 @@ module API
post ':id/export' do
check_rate_limit! :project_export, [current_user]
+ user_project.remove_exports
+
project_export_params = declared_params(include_missing: false)
after_export_params = project_export_params.delete(:upload) || {}
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 7cea44e6304..e68a3b106b1 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -20,6 +20,7 @@ module API
optional :job_events, type: Boolean, desc: "Trigger hook on job events"
optional :pipeline_events, type: Boolean, desc: "Trigger hook on pipeline events"
optional :wiki_page_events, type: Boolean, desc: "Trigger hook on wiki events"
+ optional :deployment_events, type: Boolean, desc: "Trigger hook on deployment events"
optional :enable_ssl_verification, type: Boolean, desc: "Do SSL verification when triggering the hook"
optional :token, type: String, desc: "Secret token to validate received payloads; this will not be returned in the response"
optional :push_events_branch_filter, type: String, desc: "Trigger hook on specified branch only"
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index 09934502e85..fba4c60504f 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -56,16 +56,20 @@ module API
end
params do
requires :title, type: String, allow_blank: false, desc: 'The title of the snippet'
- requires :file_name, type: String, desc: 'The file name of the snippet'
- requires :content, type: String, allow_blank: false, desc: 'The content of the snippet'
optional :description, type: String, desc: 'The description of a snippet'
requires :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values,
desc: 'The visibility of the snippet'
+ use :create_file_params
end
post ":id/snippets" do
authorize! :create_snippet, user_project
- snippet_params = declared_params(include_missing: false).merge(request: request, api: true)
+ snippet_params = declared_params(include_missing: false).tap do |create_args|
+ create_args[:request] = request
+ create_args[:api] = true
+
+ process_file_args(create_args)
+ end
service_response = ::Snippets::CreateService.new(user_project, current_user, snippet_params).execute
snippet = service_response.payload[:snippet]
diff --git a/lib/api/project_templates.rb b/lib/api/project_templates.rb
index f0fe4d85c8f..48c3dbed3b0 100644
--- a/lib/api/project_templates.rb
+++ b/lib/api/project_templates.rb
@@ -4,7 +4,7 @@ module API
class ProjectTemplates < Grape::API::Instance
include PaginationParams
- TEMPLATE_TYPES = %w[dockerfiles gitignores gitlab_ci_ymls licenses].freeze
+ TEMPLATE_TYPES = %w[dockerfiles gitignores gitlab_ci_ymls licenses metrics_dashboard_ymls issues merge_requests].freeze
# The regex is needed to ensure a period (e.g. agpl-3.0)
# isn't confused with a format type. We also need to allow encoded
# values (e.g. C%2B%2B for C++), so allow % and + as well.
@@ -14,7 +14,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
- requires :type, type: String, values: TEMPLATE_TYPES, desc: 'The type (dockerfiles|gitignores|gitlab_ci_ymls|licenses) of the template'
+ requires :type, type: String, values: TEMPLATE_TYPES, desc: 'The type (dockerfiles|gitignores|gitlab_ci_ymls|licenses|metrics_dashboard_ymls|issues|merge_requests) of the template'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of templates available to this project' do
@@ -42,9 +42,13 @@ module API
end
get ':id/templates/:type/:name', requirements: TEMPLATE_NAMES_ENDPOINT_REQUIREMENTS do
- template = TemplateFinder
- .build(params[:type], user_project, name: params[:name])
- .execute
+ begin
+ template = TemplateFinder
+ .build(params[:type], user_project, name: params[:name])
+ .execute
+ rescue ::Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
+ not_found!('Template')
+ end
not_found!('Template') unless template.present?
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index d24dab63bd9..abbdb11a3f7 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -448,7 +448,7 @@ module API
.execute.map { |lang| [lang.name, lang.share] }.to_h
end
- desc 'Remove a project'
+ desc 'Delete a project'
delete ":id" do
authorize! :remove_project, user_project
diff --git a/lib/api/pypi_packages.rb b/lib/api/pypi_packages.rb
index a6caacd7df8..739928a61ed 100644
--- a/lib/api/pypi_packages.rb
+++ b/lib/api/pypi_packages.rb
@@ -22,10 +22,6 @@ module API
render_api_error!(e.message, 400)
end
- rescue_from ActiveRecord::RecordInvalid do |e|
- render_api_error!(e.message, 400)
- end
-
helpers do
def packages_finder(project = authorized_user_project)
project
@@ -68,7 +64,7 @@ module API
requires :sha256, type: String, desc: 'The PyPi package sha256 check sum'
end
- route_setting :authentication, deploy_token_allowed: true
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true
get 'files/:sha256/*file_identifier' do
project = unauthorized_user_project!
@@ -91,7 +87,7 @@ module API
# An Api entry point but returns an HTML file instead of JSON.
# PyPi simple API returns the package descriptor as a simple HTML file.
- route_setting :authentication, deploy_token_allowed: true
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true
get 'simple/*package_name', format: :txt do
authorize_read_package!(authorized_user_project)
@@ -121,7 +117,7 @@ module API
optional :sha256_digest, type: String
end
- route_setting :authentication, deploy_token_allowed: true
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true
post do
authorize_upload!(authorized_user_project)
@@ -138,7 +134,7 @@ module API
forbidden!
end
- route_setting :authentication, deploy_token_allowed: true
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true
post 'authorize' do
authorize_workhorse!(subject: authorized_user_project, has_length: false)
end
diff --git a/lib/api/release/links.rb b/lib/api/release/links.rb
index 7e1815480a5..9624b8924e5 100644
--- a/lib/api/release/links.rb
+++ b/lib/api/release/links.rb
@@ -40,7 +40,7 @@ module API
requires :name, type: String, desc: 'The name of the link'
requires :url, type: String, desc: 'The URL of the link'
optional :filepath, type: String, desc: 'The filepath of the link'
- optional :link_type, type: String, desc: 'The link type'
+ optional :link_type, type: String, desc: 'The link type, one of: "runbook", "image", "package" or "other"'
end
post 'links' do
authorize! :create_release, release
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index 30c5e06053e..3c38721129f 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -50,8 +50,10 @@ module API
optional :ref, type: String, desc: 'The commit sha or branch name'
optional :assets, type: Hash do
optional :links, type: Array do
- requires :name, type: String
- requires :url, type: String
+ requires :name, type: String, desc: 'The name of the link'
+ requires :url, type: String, desc: 'The URL of the link'
+ optional :filepath, type: String, desc: 'The filepath of the link'
+ optional :link_type, type: String, desc: 'The link type, one of: "runbook", "image", "package" or "other"'
end
end
optional :milestones, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The titles of the related milestones', default: []
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 118045e3af2..1a3283aed98 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -66,18 +66,23 @@ module API
end
params do
requires :title, type: String, allow_blank: false, desc: 'The title of a snippet'
- requires :file_name, type: String, desc: 'The name of a snippet file'
- requires :content, type: String, allow_blank: false, desc: 'The content of a snippet'
optional :description, type: String, desc: 'The description of a snippet'
optional :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values,
default: 'internal',
desc: 'The visibility of the snippet'
+ use :create_file_params
end
post do
authorize! :create_snippet
- attrs = declared_params(include_missing: false).merge(request: request, api: true)
+ attrs = declared_params(include_missing: false).tap do |create_args|
+ create_args[:request] = request
+ create_args[:api] = true
+
+ process_file_args(create_args)
+ end
+
service_response = ::Snippets::CreateService.new(nil, current_user, attrs).execute
snippet = service_response.payload[:snippet]
diff --git a/lib/api/support/git_access_actor.rb b/lib/api/support/git_access_actor.rb
index cb9bf4472eb..39730da1251 100644
--- a/lib/api/support/git_access_actor.rb
+++ b/lib/api/support/git_access_actor.rb
@@ -39,6 +39,15 @@ module API
def update_last_used_at!
key&.update_last_used_at
end
+
+ def key_details
+ return {} unless key
+
+ {
+ gl_key_type: key.model_name.singular,
+ gl_key_id: key.id
+ }
+ end
end
end
end
diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb
index de67a149274..f398bbf3e32 100644
--- a/lib/api/triggers.rb
+++ b/lib/api/triggers.rb
@@ -11,7 +11,7 @@ module API
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Trigger a GitLab project pipeline' do
- success Entities::Pipeline
+ success Entities::Ci::Pipeline
end
params do
requires :ref, type: String, desc: 'The commit sha or name of a branch or tag', allow_blank: false
@@ -38,7 +38,7 @@ module API
if result[:http_status]
render_api_error!(result[:message], result[:http_status])
else
- present result[:pipeline], with: Entities::Pipeline
+ present result[:pipeline], with: Entities::Ci::Pipeline
end
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 7942777287b..335624963aa 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -218,7 +218,7 @@ module API
user_params = declared_params(include_missing: false)
- user_params[:password_expires_at] = Time.now if user_params[:password].present?
+ user_params[:password_expires_at] = Time.current if user_params[:password].present?
result = ::Users::UpdateService.new(current_user, user_params.merge(user: user)).execute
if result[:status] == :success
diff --git a/lib/api/validations/validators/file_path.rb b/lib/api/validations/validators/file_path.rb
index fee71373170..8a815c3b2b8 100644
--- a/lib/api/validations/validators/file_path.rb
+++ b/lib/api/validations/validators/file_path.rb
@@ -5,10 +5,12 @@ module API
module Validators
class FilePath < Grape::Validations::Base
def validate_param!(attr_name, params)
+ options = @option.is_a?(Hash) ? @option : {}
+ path_allowlist = options.fetch(:allowlist, [])
path = params[attr_name]
-
- Gitlab::Utils.check_path_traversal!(path)
- rescue ::Gitlab::Utils::PathTraversalAttackError
+ path = Gitlab::Utils.check_path_traversal!(path)
+ Gitlab::Utils.check_allowed_absolute_path!(path, path_allowlist)
+ rescue
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)],
message: "should be a valid file path"
end
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index 50d137ec7c1..cea0cb3a19c 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -30,18 +30,18 @@ module API
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get project variables' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
use :pagination
end
get ':id/variables' do
variables = user_project.variables
- present paginate(variables), with: Entities::Variable
+ present paginate(variables), with: Entities::Ci::Variable
end
desc 'Get a specific variable from a project' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key, type: String, desc: 'The key of the variable'
@@ -51,12 +51,12 @@ module API
variable = find_variable(params)
not_found!('Variable') unless variable
- present variable, with: Entities::Variable
+ present variable, with: Entities::Ci::Variable
end
# rubocop: enable CodeReuse/ActiveRecord
desc 'Create a new variable in a project' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key, type: String, desc: 'The key of the variable'
@@ -67,20 +67,21 @@ module API
optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
end
post ':id/variables' do
- variable_params = declared_params(include_missing: false)
- variable_params = filter_variable_parameters(variable_params)
-
- variable = user_project.variables.create(variable_params)
+ variable = ::Ci::ChangeVariableService.new(
+ container: user_project,
+ current_user: current_user,
+ params: { action: :create, variable_params: filter_variable_parameters(declared_params(include_missing: false)) }
+ ).execute
if variable.valid?
- present variable, with: Entities::Variable
+ present variable, with: Entities::Ci::Variable
else
render_validation_error!(variable)
end
end
desc 'Update an existing variable from a project' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
optional :key, type: String, desc: 'The key of the variable'
@@ -96,11 +97,18 @@ module API
variable = find_variable(params)
not_found!('Variable') unless variable
- variable_params = declared_params(include_missing: false).except(:key, :filter)
- variable_params = filter_variable_parameters(variable_params)
+ variable_params = filter_variable_parameters(
+ declared_params(include_missing: false)
+ .except(:key, :filter)
+ )
+ variable = ::Ci::ChangeVariableService.new(
+ container: user_project,
+ current_user: current_user,
+ params: { action: :update, variable: variable, variable_params: variable_params }
+ ).execute
- if variable.update(variable_params)
- present variable, with: Entities::Variable
+ if variable.valid?
+ present variable, with: Entities::Ci::Variable
else
render_validation_error!(variable)
end
@@ -108,7 +116,7 @@ module API
# rubocop: enable CodeReuse/ActiveRecord
desc 'Delete an existing variable from a project' do
- success Entities::Variable
+ success Entities::Ci::Variable
end
params do
requires :key, type: String, desc: 'The key of the variable'
@@ -119,8 +127,11 @@ module API
variable = find_variable(params)
not_found!('Variable') unless variable
- # Variables don't have a timestamp. Therefore, destroy unconditionally.
- variable.destroy
+ ::Ci::ChangeVariableService.new(
+ container: user_project,
+ current_user: current_user,
+ params: { action: :destroy, variable: variable }
+ ).execute
no_content!
end
diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb
index 713136e0887..95afa36113c 100644
--- a/lib/api/wikis.rb
+++ b/lib/api/wikis.rb
@@ -61,9 +61,10 @@ module API
post ':id/wikis' do
authorize! :create_wiki, container
- page = WikiPages::CreateService.new(container: container, current_user: current_user, params: params).execute
+ response = WikiPages::CreateService.new(container: container, current_user: current_user, params: params).execute
+ page = response.payload[:page]
- if page.valid?
+ if response.success?
present page, with: Entities::WikiPage
else
render_validation_error!(page)