diff options
Diffstat (limited to 'lib/api/nuget_project_packages.rb')
-rw-r--r-- | lib/api/nuget_project_packages.rb | 280 |
1 files changed, 155 insertions, 125 deletions
diff --git a/lib/api/nuget_project_packages.rb b/lib/api/nuget_project_packages.rb index cd16aaf6b5f..2716d6f0b64 100644 --- a/lib/api/nuget_project_packages.rb +++ b/lib/api/nuget_project_packages.rb @@ -17,14 +17,10 @@ module API PACKAGE_FILENAME = 'package.nupkg' SYMBOL_PACKAGE_FILENAME = 'package.snupkg' + API_KEY_HEADER = 'X-Nuget-Apikey' default_format :json - authenticate_with do |accept| - accept.token_types(:personal_access_token_with_username, :deploy_token_with_username, :job_token_with_username) - .sent_through(:http_basic_auth) - end - rescue_from ArgumentError do |e| render_api_error!(e.message, 400) end @@ -34,6 +30,8 @@ module API end helpers do + include ::Gitlab::Utils::StrongMemoize + params :file_params do requires :package, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } end @@ -42,10 +40,19 @@ module API authorized_user_project(action: :read_package) end + def project_or_group_without_auth + find_project(params[:id]).presence || not_found! + end + strong_memoize_attr :project_or_group_without_auth + def snowplow_gitlab_standard_context { project: project_or_group, namespace: project_or_group.namespace } end + def snowplow_gitlab_standard_context_without_auth + { project: project_or_group_without_auth, namespace: project_or_group_without_auth.namespace } + end + def authorize_nuget_upload project = project_or_group authorize_workhorse!( @@ -97,115 +104,127 @@ module API end params do - requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project', regexp: ::API::Concerns::Packages::NugetEndpoints::POSITIVE_INTEGER_REGEX + requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project', regexp: ::API::Concerns::Packages::Nuget::PrivateEndpoints::POSITIVE_INTEGER_REGEX 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' - 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] + namespace ':id/packages' do + namespace '/nuget' do + include ::API::Concerns::Packages::Nuget::PublicEndpoints end - params do - use :file_params + authenticate_with do |accept| + accept.token_types(:personal_access_token_with_username, :deploy_token_with_username, :job_token_with_username) + .sent_through(:http_basic_auth) end - put urgency: :low do - upload_nuget_package_file do |package| - track_package_event( - 'push_package', - :nuget, - category: 'API::NugetPackages', - 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 }) - forbidden! - end + namespace '/nuget' do + include ::API::Concerns::Packages::Nuget::PrivateEndpoints - 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 - put 'authorize', urgency: :low do - authorize_nuget_upload - end - - # 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' - 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] - end - params do - use :file_params - end - put 'symbolpackage', urgency: :low do - upload_nuget_package_file(symbol_package: true) do |package| - track_package_event( - 'push_symbol_package', - :nuget, - category: 'API::NugetPackages', - project: package.project, - namespace: package.project.namespace - ) + # 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, documentation: { example: 'mynugetpkg.1.3.0.17.nupkg' } + end + namespace '/download/*package_name' do + after_validation do + authorize_read_package!(project_or_group) + end + + desc 'The NuGet Content Service - index request' do + detail 'This feature was introduced in GitLab 12.8' + 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] + end + get 'index', format: :json, urgency: :low do + present ::Packages::Nuget::PackagesVersionsPresenter.new(find_packages(params[:package_name])), + with: ::API::Entities::Nuget::PackagesVersions + end + + desc 'The NuGet Content Service - content request' do + detail 'This feature was introduced in GitLab 12.8' + success code: 200 + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not Found' } + ] + tags %w[nuget_packages] + end + params do + 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' } + end + get '*package_version/*package_filename', format: [:nupkg, :snupkg], urgency: :low do + filename = "#{params[:package_filename]}.#{params[:format]}" + package_file = ::Packages::PackageFileFinder.new(find_package(params[:package_name], params[:package_version]), filename, with_file_name_like: true) + .execute + + not_found!('Package') unless package_file + + track_package_event( + params[:format] == 'snupkg' ? 'pull_symbol_package' : 'pull_package', + :nuget, + category: 'API::NugetPackages', + project: package_file.project, + namespace: package_file.project.namespace + ) + + # nuget and dotnet don't support 302 Moved status codes, supports_direct_download has to be set to false + present_package_file!(package_file, supports_direct_download: false) + end end - rescue ObjectStorage::RemoteStoreError => e - Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: project_or_group.id }) - - forbidden! end - 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 - put 'symbolpackage/authorize', urgency: :low do - authorize_nuget_upload + # To support an additional authentication option for download endpoints, + # we redefine the `authenticate_with` method by combining the previous + # authentication option with the new one. + authenticate_with do |accept| + accept.token_types(:personal_access_token_with_username, :deploy_token_with_username, :job_token_with_username) + .sent_through(:http_basic_auth) + accept.token_types(:personal_access_token, :deploy_token, :job_token) + .sent_through(http_header: API_KEY_HEADER) 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, documentation: { example: 'mynugetpkg.1.3.0.17.nupkg' } - end - namespace '/download/*package_name' do - after_validation do - authorize_read_package!(project_or_group) + namespace '/nuget' do + # 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' + 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] + end + + params do + use :file_params + end + put urgency: :low do + upload_nuget_package_file do |package| + track_package_event( + 'push_package', + :nuget, + category: 'API::NugetPackages', + 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 }) + + forbidden! end - desc 'The NuGet Content Service - index request' do - detail 'This feature was introduced in GitLab 12.8' - success code: 200, model: ::API::Entities::Nuget::PackagesVersions + 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' }, @@ -213,15 +232,16 @@ module API ] tags %w[nuget_packages] end - get 'index', format: :json, urgency: :low do - present ::Packages::Nuget::PackagesVersionsPresenter.new(find_packages(params[:package_name])), - with: ::API::Entities::Nuget::PackagesVersions + put 'authorize', urgency: :low do + authorize_nuget_upload end - desc 'The NuGet Content Service - content request' do - detail 'This feature was introduced in GitLab 12.8' - success code: 200 + # 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' + success code: 201 failure [ + { code: 400, message: 'Bad Request' }, { code: 401, message: 'Unauthorized' }, { code: 403, message: 'Forbidden' }, { code: 404, message: 'Not Found' } @@ -229,26 +249,36 @@ module API tags %w[nuget_packages] end params do - 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' } + use :file_params + end + put 'symbolpackage', urgency: :low do + upload_nuget_package_file(symbol_package: true) do |package| + track_package_event( + 'push_symbol_package', + :nuget, + category: 'API::NugetPackages', + 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 }) + + forbidden! + end + + 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 - get '*package_version/*package_filename', format: [:nupkg, :snupkg], urgency: :low do - filename = "#{params[:package_filename]}.#{params[:format]}" - package_file = ::Packages::PackageFileFinder.new(find_package(params[:package_name], params[:package_version]), filename, with_file_name_like: true) - .execute - - not_found!('Package') unless package_file - - track_package_event( - params[:format] == 'snupkg' ? 'pull_symbol_package' : 'pull_package', - :nuget, - category: 'API::NugetPackages', - project: package_file.project, - namespace: package_file.project.namespace - ) - - # nuget and dotnet don't support 302 Moved status codes, supports_direct_download has to be set to false - present_package_file!(package_file, supports_direct_download: false) + put 'symbolpackage/authorize', urgency: :low do + authorize_nuget_upload end end end |