2021-02-22 17:27:13 +05:30
# frozen_string_literal: true
# NuGet Package Manager Client API
#
# These API endpoints are not meant to be consumed directly by users. They are
# called by the NuGet package manager client when users run commands
# like `nuget install` or `nuget push`.
2021-03-08 18:12:59 +05:30
#
# This is the project level API.
2021-02-22 17:27:13 +05:30
module API
class NugetProjectPackages < :: API :: Base
2021-03-08 18:12:59 +05:30
helpers :: API :: Helpers :: PackagesHelpers
2021-02-22 17:27:13 +05:30
helpers :: API :: Helpers :: Packages :: BasicAuthHelpers
2021-03-08 18:12:59 +05:30
include :: API :: Helpers :: Authentication
2021-02-22 17:27:13 +05:30
feature_category :package_registry
PACKAGE_FILENAME = 'package.nupkg'
2021-09-30 23:02:18 +05:30
SYMBOL_PACKAGE_FILENAME = 'package.snupkg'
2021-02-22 17:27:13 +05:30
default_format :json
2021-03-08 18:12:59 +05:30
authenticate_with do | accept |
2021-03-11 19:13:27 +05:30
accept . token_types ( :personal_access_token_with_username , :deploy_token_with_username , :job_token_with_username )
2021-03-08 18:12:59 +05:30
. sent_through ( :http_basic_auth )
end
2021-02-22 17:27:13 +05:30
rescue_from ArgumentError do | e |
render_api_error! ( e . message , 400 )
end
2021-03-08 18:12:59 +05:30
after_validation do
2021-02-22 17:27:13 +05:30
require_packages_enabled!
end
2021-03-08 18:12:59 +05:30
helpers do
2021-09-30 23:02:18 +05:30
params :file_params do
2023-01-13 00:05:48 +05:30
requires :package , type : :: API :: Validations :: Types :: WorkhorseFile , desc : 'The package file to be published (generated by Multipart middleware)' , documentation : { type : 'file' }
2021-09-30 23:02:18 +05:30
end
2021-03-08 18:12:59 +05:30
def project_or_group
2023-03-04 22:38:38 +05:30
authorized_user_project ( action : :read_package )
2021-03-08 18:12:59 +05:30
end
2021-09-04 01:27:46 +05:30
def snowplow_gitlab_standard_context
2023-03-04 22:38:38 +05:30
{ project : project_or_group , namespace : project_or_group . namespace }
2021-09-04 01:27:46 +05:30
end
2021-09-30 23:02:18 +05:30
def authorize_nuget_upload
2023-03-04 22:38:38 +05:30
project = project_or_group
2021-09-30 23:02:18 +05:30
authorize_workhorse! (
2023-03-04 22:38:38 +05:30
subject : project ,
2021-09-30 23:02:18 +05:30
has_length : false ,
2023-03-04 22:38:38 +05:30
maximum_size : project . actual_limits . nuget_max_file_size
2021-09-30 23:02:18 +05:30
)
end
def temp_file_name ( symbol_package )
return :: Packages :: Nuget :: TEMPORARY_SYMBOL_PACKAGE_NAME if symbol_package
:: Packages :: Nuget :: TEMPORARY_PACKAGE_NAME
end
def file_name ( symbol_package )
return SYMBOL_PACKAGE_FILENAME if symbol_package
PACKAGE_FILENAME
end
def upload_nuget_package_file ( symbol_package : false )
2023-03-04 22:38:38 +05:30
project = project_or_group
authorize_upload! ( project )
bad_request! ( 'File is too large' ) if project . actual_limits . exceeded? ( :nuget_max_file_size , params [ :package ] . size )
2021-09-30 23:02:18 +05:30
file_params = params . merge (
file : params [ :package ] ,
file_name : file_name ( symbol_package )
)
package = :: Packages :: CreateTemporaryPackageService . new (
2023-03-04 22:38:38 +05:30
project , current_user , declared_params . merge ( build : current_authenticated_job )
2021-09-30 23:02:18 +05:30
) . execute ( :nuget , name : temp_file_name ( symbol_package ) )
package_file = :: Packages :: CreatePackageFileService . new ( package , file_params . merge ( build : current_authenticated_job ) )
. execute
yield ( package ) if block_given?
:: Packages :: Nuget :: ExtractionWorker . perform_async ( package_file . id ) # rubocop:disable CodeReuse/Worker
created!
end
2023-03-17 16:20:25 +05:30
def required_permission
:read_package
end
2021-03-08 18:12:59 +05:30
end
2021-02-22 17:27:13 +05:30
params do
2023-01-13 00:05:48 +05:30
requires :id , types : [ String , Integer ] , desc : 'The ID or URL-encoded path of the project' , regexp : :: API :: Concerns :: Packages :: NugetEndpoints :: POSITIVE_INTEGER_REGEX
2021-02-22 17:27:13 +05:30
end
resource :projects , requirements : API :: NAMESPACE_OR_PROJECT_REQUIREMENTS do
namespace ':id/packages/nuget' do
include :: API :: Concerns :: Packages :: NugetEndpoints
# https://docs.microsoft.com/en-us/nuget/api/package-publish-resource
desc 'The NuGet Package Publish endpoint' do
detail 'This feature was introduced in GitLab 12.6'
2023-03-04 22:38:38 +05:30
success code : 201
failure [
{ code : 400 , message : 'Bad Request' } ,
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' } ,
{ code : 404 , message : 'Not Found' }
]
tags %w[ nuget_packages ]
2021-02-22 17:27:13 +05:30
end
params do
2021-09-30 23:02:18 +05:30
use :file_params
2021-02-22 17:27:13 +05:30
end
2022-07-16 23:28:13 +05:30
put urgency : :low do
2021-09-30 23:02:18 +05:30
upload_nuget_package_file do | package |
track_package_event (
'push_package' ,
:nuget ,
category : 'API::NugetPackages' ,
user : current_user ,
project : package . project ,
namespace : package . project . namespace
)
end
rescue ObjectStorage :: RemoteStoreError = > e
Gitlab :: ErrorTracking . track_exception ( e , extra : { file_name : params [ :file_name ] , project_id : project_or_group . id } )
2021-02-22 17:27:13 +05:30
2021-09-30 23:02:18 +05:30
forbidden!
end
2023-03-04 22:38:38 +05:30
desc 'The NuGet Package Authorize endpoint' do
detail 'This feature was introduced in GitLab 14.1'
success code : 200
failure [
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' } ,
{ code : 404 , message : 'Not Found' }
]
tags %w[ nuget_packages ]
end
2022-07-16 23:28:13 +05:30
put 'authorize' , urgency : :low do
2021-09-30 23:02:18 +05:30
authorize_nuget_upload
end
2021-02-22 17:27:13 +05:30
2021-09-30 23:02:18 +05:30
# https://docs.microsoft.com/en-us/nuget/api/symbol-package-publish-resource
desc 'The NuGet Symbol Package Publish endpoint' do
detail 'This feature was introduced in GitLab 14.1'
2023-03-04 22:38:38 +05:30
success code : 201
failure [
{ code : 400 , message : 'Bad Request' } ,
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' } ,
{ code : 404 , message : 'Not Found' }
]
tags %w[ nuget_packages ]
2021-09-30 23:02:18 +05:30
end
params do
use :file_params
end
2022-07-16 23:28:13 +05:30
put 'symbolpackage' , urgency : :low do
2021-09-30 23:02:18 +05:30
upload_nuget_package_file ( symbol_package : true ) do | package |
track_package_event (
'push_symbol_package' ,
:nuget ,
category : 'API::NugetPackages' ,
user : current_user ,
project : package . project ,
namespace : package . project . namespace
)
end
2021-02-22 17:27:13 +05:30
rescue ObjectStorage :: RemoteStoreError = > e
2021-03-08 18:12:59 +05:30
Gitlab :: ErrorTracking . track_exception ( e , extra : { file_name : params [ :file_name ] , project_id : project_or_group . id } )
2021-02-22 17:27:13 +05:30
forbidden!
end
2023-03-04 22:38:38 +05:30
desc 'The NuGet Symbol Package Authorize endpoint' do
detail 'This feature was introduced in GitLab 14.1'
success code : 200
failure [
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' } ,
{ code : 404 , message : 'Not Found' }
]
tags %w[ nuget_packages ]
end
2022-07-16 23:28:13 +05:30
put 'symbolpackage/authorize' , urgency : :low do
2021-09-30 23:02:18 +05:30
authorize_nuget_upload
2021-02-22 17:27:13 +05:30
end
# https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource
params do
2023-03-04 22:38:38 +05:30
requires :package_name , type : String , desc : 'The NuGet package name' , regexp : API :: NO_SLASH_URL_PART_REGEX , documentation : { example : 'mynugetpkg.1.3.0.17.nupkg' }
2021-02-22 17:27:13 +05:30
end
namespace '/download/*package_name' do
2021-03-08 18:12:59 +05:30
after_validation do
authorize_read_package! ( project_or_group )
2021-02-22 17:27:13 +05:30
end
desc 'The NuGet Content Service - index request' do
detail 'This feature was introduced in GitLab 12.8'
2023-03-04 22:38:38 +05:30
success code : 200 , model : :: API :: Entities :: Nuget :: PackagesVersions
failure [
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' } ,
{ code : 404 , message : 'Not Found' }
]
tags %w[ nuget_packages ]
2021-02-22 17:27:13 +05:30
end
2022-07-16 23:28:13 +05:30
get 'index' , format : :json , urgency : :low do
2021-03-08 18:12:59 +05:30
present :: Packages :: Nuget :: PackagesVersionsPresenter . new ( find_packages ( params [ :package_name ] ) ) ,
2021-02-22 17:27:13 +05:30
with : :: API :: Entities :: Nuget :: PackagesVersions
end
desc 'The NuGet Content Service - content request' do
detail 'This feature was introduced in GitLab 12.8'
2023-03-04 22:38:38 +05:30
success code : 200
failure [
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' } ,
{ code : 404 , message : 'Not Found' }
]
tags %w[ nuget_packages ]
2021-02-22 17:27:13 +05:30
end
params do
2023-03-04 22:38:38 +05:30
requires :package_version , type : String , desc : 'The NuGet package version' , regexp : API :: NO_SLASH_URL_PART_REGEX , documentation : { example : '1.3.0.17' }
requires :package_filename , type : String , desc : 'The NuGet package filename' , regexp : API :: NO_SLASH_URL_PART_REGEX , documentation : { example : 'mynugetpkg.1.3.0.17.nupkg' }
2021-02-22 17:27:13 +05:30
end
2022-07-16 23:28:13 +05:30
get '*package_version/*package_filename' , format : [ :nupkg , :snupkg ] , urgency : :low do
2021-02-22 17:27:13 +05:30
filename = " #{ params [ :package_filename ] } . #{ params [ :format ] } "
2021-03-08 18:12:59 +05:30
package_file = :: Packages :: PackageFileFinder . new ( find_package ( params [ :package_name ] , params [ :package_version ] ) , filename , with_file_name_like : true )
2021-02-22 17:27:13 +05:30
. execute
not_found! ( 'Package' ) unless package_file
2021-09-30 23:02:18 +05:30
track_package_event (
params [ :format ] == 'snupkg' ? 'pull_symbol_package' : 'pull_package' ,
:nuget ,
category : 'API::NugetPackages' ,
project : package_file . project ,
namespace : package_file . project . namespace
)
2021-02-22 17:27:13 +05:30
# nuget and dotnet don't support 302 Moved status codes, supports_direct_download has to be set to false
2022-10-11 01:57:18 +05:30
present_package_file! ( package_file , supports_direct_download : false )
2021-02-22 17:27:13 +05:30
end
end
end
end
end
end