summaryrefslogtreecommitdiff
path: root/lib/api
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-05 16:20:45 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-05 16:20:45 +0000
commitd298fad0c0564454271cba11e6f20c19681534ac (patch)
tree0a19d07d8b3bdd2574617305c300e404f2ace581 /lib/api
parentc9f9eec79cab801a50db698f682aacffbedf07f7 (diff)
downloadgitlab-ce-13.9.0-rc41.tar.gz
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc41
Diffstat (limited to 'lib/api')
-rw-r--r--lib/api/api.rb32
-rw-r--r--lib/api/applications.rb16
-rw-r--r--lib/api/concerns/packages/conan_endpoints.rb1
-rw-r--r--lib/api/debian_group_packages.rb4
-rw-r--r--lib/api/debian_package_endpoints.rb21
-rw-r--r--lib/api/debian_project_packages.rb14
-rw-r--r--lib/api/deploy_tokens.rb10
-rw-r--r--lib/api/entities/application_setting.rb1
-rw-r--r--lib/api/entities/user.rb1
-rw-r--r--lib/api/events.rb2
-rwxr-xr-xlib/api/go_proxy.rb16
-rw-r--r--lib/api/group_labels.rb2
-rw-r--r--lib/api/helpers.rb22
-rw-r--r--lib/api/helpers/notes_helpers.rb2
-rw-r--r--lib/api/internal/base.rb4
-rw-r--r--lib/api/internal/kubernetes.rb2
-rw-r--r--lib/api/jobs.rb3
-rw-r--r--lib/api/labels.rb6
-rw-r--r--lib/api/members.rb12
-rw-r--r--lib/api/merge_requests.rb6
-rw-r--r--lib/api/projects.rb2
-rw-r--r--lib/api/repositories.rb61
-rw-r--r--lib/api/resource_access_tokens.rb94
-rw-r--r--lib/api/settings.rb8
-rw-r--r--lib/api/snippet_repository_storage_moves.rb7
-rw-r--r--lib/api/subscriptions.rb5
-rw-r--r--lib/api/suggestions.rb10
-rw-r--r--lib/api/users.rb2
-rw-r--r--lib/api/version.rb2
29 files changed, 272 insertions, 96 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb
index ada0da28749..725dddead70 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -30,7 +30,7 @@ module API
]
allow_access_with_scope :api
- allow_access_with_scope :read_api, if: -> (request) { request.get? }
+ allow_access_with_scope :read_api, if: -> (request) { request.get? || request.head? }
prefix :api
version 'v3', using: :path do
@@ -123,13 +123,32 @@ module API
format :json
formatter :json, Gitlab::Json::GrapeFormatter
+ content_type :json, 'application/json'
+ # Remove the `text/plain+deprecated` with `api_always_use_application_json` feature flag
# There is a small chance some users depend on the old behavior.
# We this change under a feature flag to see if affects GitLab.com users.
- if Gitlab::Database.cached_table_exists?('features') && Feature.enabled?(:api_json_content_type)
- content_type :json, 'application/json'
- else
- content_type :txt, 'text/plain'
+ # The `+deprecated` is added to distinguish content type
+ # as defined by `API::API` vs ex. `API::Repositories`
+ content_type :txt, 'text/plain+deprecated'
+
+ before do
+ # the feature flag workaround is only for `.txt`
+ api_format = env[Grape::Env::API_FORMAT]
+ next unless api_format == :txt
+
+ # get all defined content-types for the endpoint
+ api_endpoint = env[Grape::Env::API_ENDPOINT]
+ content_types = api_endpoint&.namespace_stackable_with_hash(:content_types).to_h
+
+ # Only overwrite `text/plain+deprecated`
+ if content_types[api_format] == 'text/plain+deprecated'
+ if Feature.enabled?(:api_always_use_application_json)
+ content_type 'application/json'
+ else
+ content_type 'text/plain'
+ end
+ end
end
# Ensure the namespace is right, otherwise we might load Grape::API::Helpers
@@ -249,6 +268,7 @@ module API
mount ::API::Release::Links
mount ::API::RemoteMirrors
mount ::API::Repositories
+ mount ::API::ResourceAccessTokens
mount ::API::Search
mount ::API::Services
mount ::API::Settings
@@ -294,4 +314,4 @@ module API
end
end
-API::API.prepend_if_ee('::EE::API::API')
+API::API.prepend_ee_mod
diff --git a/lib/api/applications.rb b/lib/api/applications.rb
index 8b14e16b495..b883f83cc19 100644
--- a/lib/api/applications.rb
+++ b/lib/api/applications.rb
@@ -8,15 +8,6 @@ module API
feature_category :authentication_and_authorization
resource :applications do
- helpers do
- def validate_redirect_uri(value)
- uri = ::URI.parse(value)
- !uri.is_a?(URI::HTTP) || uri.host
- rescue URI::InvalidURIError
- false
- end
- end
-
desc 'Create a new application' do
detail 'This feature was introduced in GitLab 10.5'
success Entities::ApplicationWithSecret
@@ -30,13 +21,6 @@ module API
desc: 'Application will be used where the client secret is confidential'
end
post do
- # Validate that host in uri is specified
- # Please remove it when https://github.com/doorkeeper-gem/doorkeeper/pull/1440 is merged
- # and the doorkeeper gem version is bumped
- unless validate_redirect_uri(declared_params[:redirect_uri])
- render_api_error!({ redirect_uri: ["must be an absolute URI."] }, :bad_request)
- end
-
application = Doorkeeper::Application.new(declared_params)
if application.save
diff --git a/lib/api/concerns/packages/conan_endpoints.rb b/lib/api/concerns/packages/conan_endpoints.rb
index 6c8b3a1ba4a..1796d51324f 100644
--- a/lib/api/concerns/packages/conan_endpoints.rb
+++ b/lib/api/concerns/packages/conan_endpoints.rb
@@ -72,6 +72,7 @@ module API
namespace 'users' do
format :txt
+ content_type :txt, 'text/plain'
desc 'Authenticate user against conan CLI' do
detail 'This feature was introduced in GitLab 12.2'
diff --git a/lib/api/debian_group_packages.rb b/lib/api/debian_group_packages.rb
index e3cacc4132f..f138f400601 100644
--- a/lib/api/debian_group_packages.rb
+++ b/lib/api/debian_group_packages.rb
@@ -8,12 +8,14 @@ module API
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
+ require_packages_enabled!
+
not_found! unless ::Feature.enabled?(:debian_packages, user_group)
authorize_read_package!(user_group)
end
- namespace ':id/-/packages/debian' do
+ namespace ':id/packages/debian' do
include DebianPackageEndpoints
end
end
diff --git a/lib/api/debian_package_endpoints.rb b/lib/api/debian_package_endpoints.rb
index c95c75b7e5c..e7689b3feff 100644
--- a/lib/api/debian_package_endpoints.rb
+++ b/lib/api/debian_package_endpoints.rb
@@ -32,6 +32,7 @@ module API
helpers ::API::Helpers::Packages::BasicAuthHelpers
format :txt
+ content_type :txt, 'text/plain'
rescue_from ArgumentError do |e|
render_api_error!(e.message, 400)
@@ -50,33 +51,33 @@ module API
end
namespace 'dists/*distribution', requirements: DISTRIBUTION_REQUIREMENTS do
- # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/Release.gpg
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release.gpg
desc 'The Release file signature' do
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Release.gpg' do
not_found!
end
- # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/Release
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release
desc 'The unsigned Release file' do
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Release' do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO Release'
end
- # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/InRelease
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/InRelease
desc 'The signed Release file' do
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'InRelease' do
not_found!
end
@@ -87,12 +88,12 @@ module API
end
namespace ':component/binary-:architecture', requirements: COMPONENT_ARCHITECTURE_REQUIREMENTS do
- # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages
desc 'The binary files index' do
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Packages' do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO Packages'
@@ -107,7 +108,7 @@ module API
end
namespace 'pool/:component/:letter/:source_package', requirements: COMPONENT_LETTER_SOURCE_PACKAGE_REQUIREMENTS do
- # GET {projects|groups}/:id/-/packages/debian/pool/:component/:letter/:source_package/:file_name
+ # GET {projects|groups}/:id/packages/debian/pool/:component/:letter/:source_package/:file_name
params do
requires :file_name, type: String, desc: 'The Debian File Name'
end
@@ -115,7 +116,7 @@ module API
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get ':file_name', requirements: FILE_NAME_REQUIREMENTS do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO File'
diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb
index f8129c18dff..8c0db42a448 100644
--- a/lib/api/debian_project_packages.rb
+++ b/lib/api/debian_project_packages.rb
@@ -8,27 +8,29 @@ module API
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
+ require_packages_enabled!
+
not_found! unless ::Feature.enabled?(:debian_packages, user_project)
authorize_read_package!
end
- namespace ':id/-/packages/debian' do
+ namespace ':id/packages/debian' do
include DebianPackageEndpoints
params do
requires :file_name, type: String, desc: 'The file name'
end
- namespace 'incoming/:file_name', requirements: FILE_NAME_REQUIREMENTS do
+ namespace ':file_name', requirements: FILE_NAME_REQUIREMENTS do
content_type :json, Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
- # PUT {projects|groups}/:id/-/packages/debian/incoming/:file_name
+ # PUT {projects|groups}/:id/packages/debian/:file_name
params do
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put do
authorize_upload!(authorized_user_project)
bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:debian_max_file_size, params[:file].size)
@@ -42,8 +44,8 @@ module API
forbidden!
end
- # PUT {projects|groups}/:id/-/packages/debian/incoming/:file_name/authorize
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ # PUT {projects|groups}/:id/packages/debian/:file_name/authorize
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put 'authorize' do
authorize_workhorse!(
subject: authorized_user_project,
diff --git a/lib/api/deploy_tokens.rb b/lib/api/deploy_tokens.rb
index 5fab590eb4e..30ec4e52b2a 100644
--- a/lib/api/deploy_tokens.rb
+++ b/lib/api/deploy_tokens.rb
@@ -28,8 +28,6 @@ module API
use :pagination
end
get 'deploy_tokens' do
- service_unavailable! unless Feature.enabled?(:deploy_tokens_api, default_enabled: true)
-
authenticated_as_admin!
present paginate(DeployToken.all), with: Entities::DeployToken
@@ -39,10 +37,6 @@ module API
requires :id, type: String, desc: 'The ID of a project'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- before do
- service_unavailable! unless Feature.enabled?(:deploy_tokens_api, user_project, default_enabled: true)
- end
-
params do
use :pagination
end
@@ -102,10 +96,6 @@ module API
requires :id, type: String, desc: 'The ID of a group'
end
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- before do
- service_unavailable! unless Feature.enabled?(:deploy_tokens_api, user_group, default_enabled: true)
- end
-
params do
use :pagination
end
diff --git a/lib/api/entities/application_setting.rb b/lib/api/entities/application_setting.rb
index e9572a8d430..2468c1f9b18 100644
--- a/lib/api/entities/application_setting.rb
+++ b/lib/api/entities/application_setting.rb
@@ -31,6 +31,7 @@ module API
expose :password_authentication_enabled_for_web, as: :password_authentication_enabled
expose :password_authentication_enabled_for_web, as: :signin_enabled
expose :allow_local_requests_from_web_hooks_and_services, as: :allow_local_requests_from_hooks_and_services
+ expose :asset_proxy_allowlist, as: :asset_proxy_whitelist
end
end
end
diff --git a/lib/api/entities/user.rb b/lib/api/entities/user.rb
index 4aa5c9b7236..b392e7831e5 100644
--- a/lib/api/entities/user.rb
+++ b/lib/api/entities/user.rb
@@ -6,6 +6,7 @@ module API
include UsersHelper
expose :created_at, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) }
expose :bio, :bio_html, :location, :public_email, :skype, :linkedin, :twitter, :website_url, :organization, :job_title
+ expose :bot?, as: :bot
expose :work_information do |user|
work_information(user)
end
diff --git a/lib/api/events.rb b/lib/api/events.rb
index 233c62b5389..db5ed7b7e6e 100644
--- a/lib/api/events.rb
+++ b/lib/api/events.rb
@@ -6,7 +6,7 @@ module API
include APIGuard
helpers ::API::Helpers::EventsHelpers
- allow_access_with_scope :read_user, if: -> (request) { request.get? }
+ allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
feature_category :users
diff --git a/lib/api/go_proxy.rb b/lib/api/go_proxy.rb
index 2d978019f2a..ea30f17522e 100755
--- a/lib/api/go_proxy.rb
+++ b/lib/api/go_proxy.rb
@@ -30,20 +30,6 @@ module API
str.gsub(/![[:alpha:]]/) { |s| s[1..].upcase }
end
- def find_project!(id)
- # based on API::Helpers::Packages::BasicAuthHelpers#authorized_project_find!
-
- project = find_project(id)
-
- return project if project && can?(current_user, :read_project, project)
-
- if current_user
- not_found!('Project')
- else
- unauthorized!
- end
- end
-
def find_module
not_found! unless Feature.enabled?(:go_proxy, user_project)
@@ -74,7 +60,7 @@ module API
requires :id, type: String, desc: 'The ID of a project'
requires :module_name, type: String, desc: 'Module name', coerce_with: ->(val) { CGI.unescape(val) }
end
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, authenticate_non_public: true
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
authorize_read_package!
diff --git a/lib/api/group_labels.rb b/lib/api/group_labels.rb
index 7fbf4445116..bea538441ee 100644
--- a/lib/api/group_labels.rb
+++ b/lib/api/group_labels.rb
@@ -12,7 +12,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a group'
end
- resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :groups, requirements: ::API::Labels::LABEL_ENDPOINT_REQUIREMENTS do
desc 'Get all labels of the group' do
detail 'This feature was added in GitLab 11.8'
success Entities::GroupLabel
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 79af9c37378..0abb21c9831 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -119,11 +119,10 @@ module API
def find_project!(id)
project = find_project(id)
- if can?(current_user, :read_project, project)
- project
- else
- not_found!('Project')
- end
+ return project if can?(current_user, :read_project, project)
+ return unauthorized! if authenticate_non_public?
+
+ not_found!('Project')
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -139,11 +138,10 @@ module API
def find_group!(id)
group = find_group(id)
- if can?(current_user, :read_group, group)
- group
- else
- not_found!('Group')
- end
+ return group if can?(current_user, :read_group, group)
+ return unauthorized! if authenticate_non_public?
+
+ not_found!('Group')
end
def check_namespace_access(namespace)
@@ -657,6 +655,10 @@ module API
Gitlab::Shell.secret_token
end
+ def authenticate_non_public?
+ route_authentication_setting[:authenticate_non_public] && !current_user
+ end
+
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index 6798c4d284b..71a18524104 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -138,7 +138,7 @@ module API
parent = noteable_parent(noteable)
::Discussions::ResolveService.new(parent, current_user, one_or_more_discussions: discussion).execute
else
- discussion.unresolve!
+ ::Discussions::UnresolveService.new(discussion, current_user).execute
end
present discussion, with: Entities::Discussion
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index 12bb6e77c3e..6de80c17960 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -52,7 +52,9 @@ module API
actor.update_last_used_at!
check_result = begin
- access_check!(actor, params)
+ Gitlab::Auth::CurrentUserMode.bypass_session!(actor.user&.id) do
+ access_check!(actor, params)
+ end
rescue Gitlab::GitAccess::ForbiddenError => e
# The return code needs to be 401. If we return 403
# the custom message we return won't be shown to the user
diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb
index 73723a96401..87ad79d601f 100644
--- a/lib/api/internal/kubernetes.rb
+++ b/lib/api/internal/kubernetes.rb
@@ -52,6 +52,8 @@ module API
def check_agent_token
forbidden! unless agent_token
+
+ forbidden! unless Gitlab::Kas.included_in_gitlab_com_rollout?(agent.project)
end
end
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index e14a4a5e680..c09b01f5b4e 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -82,7 +82,8 @@ module API
content_type 'text/plain'
env['api.format'] = :binary
- trace = build.trace.raw
+ # The trace can be nil bu body method expects a string as an argument.
+ trace = build.trace.raw || ''
body trace
end
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index c9f29865664..aa3746dae42 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -9,10 +9,14 @@ module API
feature_category :issue_tracking
+ LABEL_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
+ name: API::NO_SLASH_URL_PART_REGEX,
+ label_id: API::NO_SLASH_URL_PART_REGEX)
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :projects, requirements: LABEL_ENDPOINT_REQUIREMENTS do
desc 'Get all labels of the project' do
success Entities::ProjectLabel
end
diff --git a/lib/api/members.rb b/lib/api/members.rb
index 9bea74e2ce9..42f608102b3 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -137,12 +137,14 @@ module API
authorize_admin_source!(source_type, source)
member = source_members(source).find_by!(user_id: params[:user_id])
- updated_member =
- ::Members::UpdateService
- .new(current_user, declared_params(include_missing: false))
- .execute(member)
- if updated_member.valid?
+ result = ::Members::UpdateService
+ .new(current_user, declared_params(include_missing: false))
+ .execute(member)
+
+ updated_member = result[:member]
+
+ if result[:status] == :success
present_members updated_member
else
render_validation_error!(updated_member)
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index ab0e9b95e4a..cff0866c65e 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -26,6 +26,7 @@ module API
%i[
assignee_id
assignee_ids
+ reviewer_ids
description
labels
add_labels
@@ -160,7 +161,8 @@ module API
helpers do
params :optional_params do
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
- optional :assignee_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The array of user IDs to assign issue'
+ optional :assignee_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Comma-separated list of assignee ids'
+ optional :reviewer_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Comma-separated list of reviewer ids'
optional :description, type: String, desc: 'The description of the merge request'
optional :labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
optional :add_labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
@@ -359,7 +361,7 @@ module API
with: Entities::MergeRequestChanges,
current_user: current_user,
project: user_project,
- access_raw_diffs: params.fetch(:access_raw_diffs, false)
+ access_raw_diffs: to_boolean(params.fetch(:access_raw_diffs, false))
end
desc 'Get the merge request pipelines' do
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 2d09ad01757..fca68c3606b 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -295,6 +295,8 @@ module API
optional :namespace_path, type: String, desc: 'The path of the namespace that the project will be forked into'
optional :path, type: String, desc: 'The path that will be assigned to the fork'
optional :name, type: String, desc: 'The name that will be assigned to the fork'
+ optional :description, type: String, desc: 'The description that will be assigned to the fork'
+ optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the fork'
end
post ':id/fork', feature_category: :source_code_management do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42284')
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 8af8ffc3b63..353f2ed1c25 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -170,6 +170,67 @@ module API
not_found!("Merge Base")
end
end
+
+ desc 'Generates a changelog section for a release' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ params do
+ requires :version,
+ type: String,
+ regexp: Gitlab::Regex.unbounded_semver_regex,
+ desc: 'The version of the release, using the semantic versioning format'
+
+ requires :from,
+ type: String,
+ desc: 'The first commit in the range of commits to use for the changelog'
+
+ requires :to,
+ type: String,
+ desc: 'The last commit in the range of commits to use for the changelog'
+
+ optional :date,
+ type: DateTime,
+ desc: 'The date and time of the release'
+
+ optional :branch,
+ type: String,
+ desc: 'The branch to commit the changelog changes to'
+
+ optional :trailer,
+ type: String,
+ desc: 'The Git trailer to use for determining if commits are to be included in the changelog',
+ default: ::Repositories::ChangelogService::DEFAULT_TRAILER
+
+ optional :file,
+ type: String,
+ desc: 'The file to commit the changelog changes to',
+ default: ::Repositories::ChangelogService::DEFAULT_FILE
+
+ optional :message,
+ type: String,
+ desc: 'The commit message to use when committing the changelog'
+ end
+ post ':id/repository/changelog' do
+ not_found! unless Feature.enabled?(:changelog_api, user_project)
+
+ branch = params[:branch] || user_project.default_branch_or_master
+ access = Gitlab::UserAccess.new(current_user, container: user_project)
+
+ unless access.can_push_to_branch?(branch)
+ forbidden!("You are not allowed to commit a changelog on this branch")
+ end
+
+ service = ::Repositories::ChangelogService.new(
+ user_project,
+ current_user,
+ **declared_params(include_missing: false)
+ )
+
+ service.execute
+ status(200)
+ rescue => ex
+ render_api_error!("Failed to generate the changelog: #{ex.message}", 500)
+ end
end
end
end
diff --git a/lib/api/resource_access_tokens.rb b/lib/api/resource_access_tokens.rb
new file mode 100644
index 00000000000..66948f9eaf3
--- /dev/null
+++ b/lib/api/resource_access_tokens.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+module API
+ class ResourceAccessTokens < ::API::Base
+ include PaginationParams
+
+ before { authenticate! }
+
+ feature_category :authentication_and_authorization
+
+ %w[project].each do |source_type|
+ resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Get list of all access tokens for the specified resource' do
+ detail 'This feature was introduced in GitLab 13.9.'
+ end
+ params do
+ requires :id, type: String, desc: "The #{source_type} ID"
+ end
+ get ":id/access_tokens" do
+ resource = find_source(source_type, params[:id])
+
+ next unauthorized! unless has_permission_to_read?(resource)
+
+ tokens = PersonalAccessTokensFinder.new({ user: resource.bots, impersonation: false }).execute
+
+ present paginate(tokens), with: Entities::PersonalAccessToken
+ end
+
+ desc 'Revoke a resource access token' do
+ detail 'This feature was introduced in GitLab 13.9.'
+ end
+ params do
+ requires :id, type: String, desc: "The #{source_type} ID"
+ requires :token_id, type: String, desc: "The ID of the token"
+ end
+ delete ':id/access_tokens/:token_id' do
+ resource = find_source(source_type, params[:id])
+ token = find_token(resource, params[:token_id])
+
+ if token.nil?
+ next not_found!("Could not find #{source_type} access token with token_id: #{params[:token_id]}")
+ end
+
+ service = ::ResourceAccessTokens::RevokeService.new(
+ current_user,
+ resource,
+ token
+ ).execute
+
+ service.success? ? no_content! : bad_request!(service.message)
+ end
+
+ desc 'Create a resource access token' do
+ detail 'This feature was introduced in GitLab 13.9.'
+ end
+ params do
+ requires :id, type: String, desc: "The #{source_type} ID"
+ requires :name, type: String, desc: "Resource access token name"
+ requires :scopes, type: Array[String], desc: "The permissions of the token"
+ optional :expires_at, type: Date, desc: "The expiration date of the token"
+ end
+ post ':id/access_tokens' do
+ resource = find_source(source_type, params[:id])
+
+ token_response = ::ResourceAccessTokens::CreateService.new(
+ current_user,
+ resource,
+ declared_params
+ ).execute
+
+ if token_response.success?
+ present token_response.payload[:access_token], with: Entities::PersonalAccessToken
+ else
+ bad_request!(token_response.message)
+ end
+ end
+ end
+ end
+
+ helpers do
+ def find_source(source_type, id)
+ public_send("find_#{source_type}!", id) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def find_token(resource, token_id)
+ PersonalAccessTokensFinder.new({ user: resource.bots, impersonation: false }).find_by_id(token_id)
+ end
+
+ def has_permission_to_read?(resource)
+ can?(current_user, :project_bot_access, resource) || can?(current_user, :admin_resource_access_tokens, resource)
+ end
+ end
+ end
+end
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index f329a94adf2..6b1ad33d84b 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -42,7 +42,8 @@ module API
optional :asset_proxy_enabled, type: Boolean, desc: 'Enable proxying of assets'
optional :asset_proxy_url, type: String, desc: 'URL of the asset proxy server'
optional :asset_proxy_secret_key, type: String, desc: 'Shared secret with the asset proxy server'
- optional :asset_proxy_whitelist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically whitelisted.'
+ optional :asset_proxy_whitelist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Deprecated: Use :asset_proxy_allowlist instead. Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically whitelisted.'
+ optional :asset_proxy_allowlist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed.'
optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)'
optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts"
optional :default_ci_config_path, type: String, desc: 'The instance default CI configuration path for new projects'
@@ -211,6 +212,11 @@ module API
attrs[:abuse_notification_email] = attrs.delete(:admin_notification_email)
end
+ # support legacy names, can be removed in v5
+ if attrs.has_key?(:asset_proxy_whitelist)
+ attrs[:asset_proxy_allowlist] = attrs.delete(:asset_proxy_whitelist)
+ end
+
# since 13.0 it's not possible to disable hashed storage - support can be removed in 14.0
attrs.delete(:hashed_storage_enabled) if attrs.has_key?(:hashed_storage_enabled)
diff --git a/lib/api/snippet_repository_storage_moves.rb b/lib/api/snippet_repository_storage_moves.rb
index 1a5b41eb1ec..84dbc03ba33 100644
--- a/lib/api/snippet_repository_storage_moves.rb
+++ b/lib/api/snippet_repository_storage_moves.rb
@@ -58,9 +58,14 @@ module API
resource :snippets do
helpers do
def user_snippet
- Snippet.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
+ @user_snippet ||= Snippet.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
end
end
+
+ before do
+ not_found!('Snippet') unless user_snippet
+ end
+
desc 'Get a list of all snippets repository storage moves' do
detail 'This feature was introduced in GitLab 13.8.'
success Entities::SnippetRepositoryStorageMove
diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb
index 914bab52929..87dc1358a51 100644
--- a/lib/api/subscriptions.rb
+++ b/lib/api/subscriptions.rb
@@ -6,6 +6,9 @@ module API
before { authenticate! }
+ SUBSCRIBE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
+ subscribable_id: API::NO_SLASH_URL_PART_REGEX)
+
subscribables = [
{
type: 'merge_requests',
@@ -44,7 +47,7 @@ module API
requires :id, type: String, desc: "The #{source_type} ID"
requires :subscribable_id, type: String, desc: 'The ID of a resource'
end
- resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource source_type.pluralize, requirements: SUBSCRIBE_ENDPOINT_REQUIREMENTS do
desc 'Subscribe to a resource' do
success subscribable[:entity]
end
diff --git a/lib/api/suggestions.rb b/lib/api/suggestions.rb
index a024d6de874..7921700e365 100644
--- a/lib/api/suggestions.rb
+++ b/lib/api/suggestions.rb
@@ -12,12 +12,13 @@ module API
end
params do
requires :id, type: String, desc: 'The suggestion ID'
+ optional :commit_message, type: String, desc: "A custom commit message to use instead of the default generated message or the project's default message"
end
put ':id/apply' do
suggestion = Suggestion.find_by_id(params[:id])
if suggestion
- apply_suggestions(suggestion, current_user)
+ apply_suggestions(suggestion, current_user, params[:commit_message])
else
render_api_error!(_('Suggestion is not applicable as the suggestion was not found.'), :not_found)
end
@@ -28,6 +29,7 @@ module API
end
params do
requires :ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: "An array of suggestion ID's"
+ optional :commit_message, type: String, desc: "A custom commit message to use instead of the default generated message or the project's default message"
end
put 'batch_apply' do
ids = params[:ids]
@@ -35,7 +37,7 @@ module API
suggestions = Suggestion.id_in(ids)
if suggestions.size == ids.length
- apply_suggestions(suggestions, current_user)
+ apply_suggestions(suggestions, current_user, params[:commit_message])
else
render_api_error!(_('Suggestions are not applicable as one or more suggestions were not found.'), :not_found)
end
@@ -43,10 +45,10 @@ module API
end
helpers do
- def apply_suggestions(suggestions, current_user)
+ def apply_suggestions(suggestions, current_user, message)
authorize_suggestions(*suggestions)
- result = ::Suggestions::ApplyService.new(current_user, *suggestions).execute
+ result = ::Suggestions::ApplyService.new(current_user, *suggestions, message: message).execute
if result[:status] == :success
present suggestions, with: Entities::Suggestion, current_user: current_user
diff --git a/lib/api/users.rb b/lib/api/users.rb
index cee09f60a2b..36368adf2f0 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -6,7 +6,7 @@ module API
include APIGuard
include Helpers::CustomAttributes
- allow_access_with_scope :read_user, if: -> (request) { request.get? }
+ allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
feature_category :users, ['/users/:id/custom_attributes', '/users/:id/custom_attributes/:key']
diff --git a/lib/api/version.rb b/lib/api/version.rb
index f8072658cc6..86eb34ca589 100644
--- a/lib/api/version.rb
+++ b/lib/api/version.rb
@@ -5,7 +5,7 @@ module API
helpers ::API::Helpers::GraphqlHelpers
include APIGuard
- allow_access_with_scope :read_user, if: -> (request) { request.get? }
+ allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
before { authenticate! }