diff options
Diffstat (limited to 'lib/api/nuget_project_packages.rb')
-rw-r--r-- | lib/api/nuget_project_packages.rb | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/lib/api/nuget_project_packages.rb b/lib/api/nuget_project_packages.rb new file mode 100644 index 00000000000..b2516cc91f8 --- /dev/null +++ b/lib/api/nuget_project_packages.rb @@ -0,0 +1,139 @@ +# 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`. +module API + class NugetProjectPackages < ::API::Base + helpers ::API::Helpers::PackagesManagerClientsHelpers + helpers ::API::Helpers::Packages::BasicAuthHelpers + + feature_category :package_registry + + PACKAGE_FILENAME = 'package.nupkg' + + default_format :json + + rescue_from ArgumentError do |e| + render_api_error!(e.message, 400) + end + + before do + require_packages_enabled! + end + + params do + requires :id, type: String, desc: 'The ID of a project', regexp: ::API::Concerns::Packages::NugetEndpoints::POSITIVE_INTEGER_REGEX + end + + 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 + end + + 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' + 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, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true + + put do + authorize_upload!(authorized_user_project) + bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:nuget_max_file_size, params[:package].size) + + file_params = params.merge( + file: params[:package], + file_name: PACKAGE_FILENAME + ) + + package = ::Packages::Nuget::CreatePackageService.new( + authorized_user_project, + current_user, + declared_params.merge(build: current_authenticated_job) + ).execute + + package_file = ::Packages::CreatePackageFileService.new( + package, + file_params.merge(build: current_authenticated_job) + ).execute + + track_package_event('push_package', :nuget, category: 'API::NugetPackages') + + ::Packages::Nuget::ExtractionWorker.perform_async(package_file.id) # rubocop:disable CodeReuse/Worker + + created! + rescue ObjectStorage::RemoteStoreError => e + Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: authorized_user_project.id }) + + forbidden! + end + + 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, + maximum_size: authorized_user_project.actual_limits.nuget_max_file_size + ) + end + + # https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource + params do + requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX + end + namespace '/download/*package_name' do + before do + authorize_read_package!(authorized_user_project) + end + + 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, 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 + end + + desc 'The NuGet Content Service - content request' do + detail 'This feature was introduced in GitLab 12.8' + end + params do + 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, 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) + .execute + + not_found!('Package') unless package_file + + track_package_event('pull_package', :nuget, category: 'API::NugetPackages') + + # nuget and dotnet don't support 302 Moved status codes, supports_direct_download has to be set to false + present_carrierwave_file!(package_file.file, supports_direct_download: false) + end + end + end + end + end +end |