Commit 0c4d3ba4 authored by Sean McGivern's avatar Sean McGivern

Merge branch '36423-create-nuget-shared-endpoints' into 'master'

Create Nuget shared endpoints

See merge request gitlab-org/gitlab!49141
parents 11277843 e41d508e
...@@ -211,7 +211,7 @@ module API ...@@ -211,7 +211,7 @@ module API
mount ::API::ProjectPackages mount ::API::ProjectPackages
mount ::API::GroupPackages mount ::API::GroupPackages
mount ::API::PackageFiles mount ::API::PackageFiles
mount ::API::NugetPackages mount ::API::NugetProjectPackages
mount ::API::PypiPackages mount ::API::PypiPackages
mount ::API::ComposerPackages mount ::API::ComposerPackages
mount ::API::ConanProjectPackages mount ::API::ConanProjectPackages
......
# frozen_string_literal: true
#
# NuGet Package Manager Client API
#
# These API endpoints are not consumed directly by users, so there is no documentation for the
# individual endpoints. They are called by the NuGet package manager client when users run commands
# like `nuget install` or `nuget push`. The usage of the GitLab NuGet registry is documented here:
# https://docs.gitlab.com/ee/user/packages/nuget_repository/
#
# Technical debt: https://gitlab.com/gitlab-org/gitlab/issues/35798
module API
module Concerns
module Packages
module NugetEndpoints
extend ActiveSupport::Concern
POSITIVE_INTEGER_REGEX = %r{\A[1-9]\d*\z}.freeze
NON_NEGATIVE_INTEGER_REGEX = %r{\A0|[1-9]\d*\z}.freeze
included do
helpers do
def find_packages
packages = package_finder.execute
not_found!('Packages') unless packages.exists?
packages
end
def find_package
package = package_finder(package_version: params[:package_version]).execute
.first
not_found!('Package') unless package
package
end
def package_finder(finder_params = {})
::Packages::Nuget::PackageFinder.new(
authorized_user_project,
**finder_params.merge(package_name: params[:package_name])
)
end
end
# https://docs.microsoft.com/en-us/nuget/api/service-index
desc 'The NuGet Service Index' do
detail 'This feature was introduced in GitLab 12.6'
end
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)
track_package_event('cli_metadata', :nuget, category: 'API::NugetPackages')
present ::Packages::Nuget::ServiceIndexPresenter.new(authorized_user_project),
with: ::API::Entities::Nuget::ServiceIndex
end
# https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
params do
requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX
end
namespace '/metadata/*package_name' do
before do
authorize_read_package!(authorized_user_project)
end
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, 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
end
desc 'The NuGet Metadata Service - Package name and version level' 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
end
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
end
end
# https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource
params do
requires :q, type: String, desc: 'The search term'
optional :skip, type: Integer, desc: 'The number of results to skip', default: 0, regexp: NON_NEGATIVE_INTEGER_REGEX
optional :take, type: Integer, desc: 'The number of results to return', default: Kaminari.config.default_per_page, regexp: POSITIVE_INTEGER_REGEX
optional :prerelease, type: ::Grape::API::Boolean, desc: 'Include prerelease versions', default: true
end
namespace '/query' do
before do
authorize_read_package!(authorized_user_project)
end
desc 'The NuGet Search Service' 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 format: :json do
search_options = {
include_prerelease_versions: params[:prerelease],
per_page: params[:take],
padding: params[:skip]
}
search = ::Packages::Nuget::SearchService
.new(authorized_user_project, params[:q], search_options)
.execute
track_package_event('search_package', :nuget, category: 'API::NugetPackages')
present ::Packages::Nuget::SearchResultsPresenter.new(search),
with: ::API::Entities::Nuget::SearchResults
end
end
end
end
end
end
end
...@@ -6,15 +6,12 @@ ...@@ -6,15 +6,12 @@
# called by the NuGet package manager client when users run commands # called by the NuGet package manager client when users run commands
# like `nuget install` or `nuget push`. # like `nuget install` or `nuget push`.
module API module API
class NugetPackages < ::API::Base class NugetProjectPackages < ::API::Base
helpers ::API::Helpers::PackagesManagerClientsHelpers helpers ::API::Helpers::PackagesManagerClientsHelpers
helpers ::API::Helpers::Packages::BasicAuthHelpers helpers ::API::Helpers::Packages::BasicAuthHelpers
feature_category :package_registry feature_category :package_registry
POSITIVE_INTEGER_REGEX = %r{\A[1-9]\d*\z}.freeze
NON_NEGATIVE_INTEGER_REGEX = %r{\A0|[1-9]\d*\z}.freeze
PACKAGE_FILENAME = 'package.nupkg' PACKAGE_FILENAME = 'package.nupkg'
default_format :json default_format :json
...@@ -23,38 +20,12 @@ module API ...@@ -23,38 +20,12 @@ module API
render_api_error!(e.message, 400) render_api_error!(e.message, 400)
end end
helpers do
def find_packages
packages = package_finder.execute
not_found!('Packages') unless packages.exists?
packages
end
def find_package
package = package_finder(package_version: params[:package_version]).execute
.first
not_found!('Package') unless package
package
end
def package_finder(finder_params = {})
::Packages::Nuget::PackageFinder.new(
authorized_user_project,
**finder_params.merge(package_name: params[:package_name])
)
end
end
before do before do
require_packages_enabled! require_packages_enabled!
end end
params do params do
requires :id, type: String, desc: 'The ID of a project', regexp: POSITIVE_INTEGER_REGEX requires :id, type: String, desc: 'The ID of a project', regexp: ::API::Concerns::Packages::NugetEndpoints::POSITIVE_INTEGER_REGEX
end end
route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true route_setting :authentication, deploy_token_allowed: true, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true
...@@ -65,21 +36,7 @@ module API ...@@ -65,21 +36,7 @@ module API
end end
namespace ':id/packages/nuget' do namespace ':id/packages/nuget' do
# https://docs.microsoft.com/en-us/nuget/api/service-index include ::API::Concerns::Packages::NugetEndpoints
desc 'The NuGet Service Index' do
detail 'This feature was introduced in GitLab 12.6'
end
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)
track_package_event('cli_metadata', :nuget)
present ::Packages::Nuget::ServiceIndexPresenter.new(authorized_user_project),
with: ::API::Entities::Nuget::ServiceIndex
end
# https://docs.microsoft.com/en-us/nuget/api/package-publish-resource # https://docs.microsoft.com/en-us/nuget/api/package-publish-resource
desc 'The NuGet Package Publish endpoint' do desc 'The NuGet Package Publish endpoint' do
...@@ -112,7 +69,7 @@ module API ...@@ -112,7 +69,7 @@ module API
file_params.merge(build: current_authenticated_job) file_params.merge(build: current_authenticated_job)
).execute ).execute
track_package_event('push_package', :nuget) track_package_event('push_package', :nuget, category: 'API::NugetPackages')
::Packages::Nuget::ExtractionWorker.perform_async(package_file.id) # rubocop:disable CodeReuse/Worker ::Packages::Nuget::ExtractionWorker.perform_async(package_file.id) # rubocop:disable CodeReuse/Worker
...@@ -133,41 +90,6 @@ module API ...@@ -133,41 +90,6 @@ module API
) )
end end
params do
requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX
end
namespace '/metadata/*package_name' do
before do
authorize_read_package!(authorized_user_project)
end
# https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
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, 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
end
desc 'The NuGet Metadata Service - Package name and version level' 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
end
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
end
end
# https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource # https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource
params do params do
requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX requires :package_name, type: String, desc: 'The NuGet package name', regexp: API::NO_SLASH_URL_PART_REGEX
...@@ -205,47 +127,12 @@ module API ...@@ -205,47 +127,12 @@ module API
not_found!('Package') unless package_file not_found!('Package') unless package_file
track_package_event('pull_package', :nuget) 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 # 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) present_carrierwave_file!(package_file.file, supports_direct_download: false)
end end
end end
params do
requires :q, type: String, desc: 'The search term'
optional :skip, type: Integer, desc: 'The number of results to skip', default: 0, regexp: NON_NEGATIVE_INTEGER_REGEX
optional :take, type: Integer, desc: 'The number of results to return', default: Kaminari.config.default_per_page, regexp: POSITIVE_INTEGER_REGEX
optional :prerelease, type: Boolean, desc: 'Include prerelease versions', default: true
end
namespace '/query' do
before do
authorize_read_package!(authorized_user_project)
end
# https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource
desc 'The NuGet Search Service' 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 format: :json do
search_options = {
include_prerelease_versions: params[:prerelease],
per_page: params[:take],
padding: params[:skip]
}
search = Packages::Nuget::SearchService
.new(authorized_user_project, params[:q], search_options)
.execute
track_package_event('search_package', :nuget)
present ::Packages::Nuget::SearchResultsPresenter.new(search),
with: ::API::Entities::Nuget::SearchResults
end
end
end end
end end
end end
......
# frozen_string_literal: true # frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
RSpec.describe API::NugetPackages do RSpec.describe API::NugetProjectPackages do
include WorkhorseHelpers include WorkhorseHelpers
include PackagesManagerApiSpecHelpers include PackagesManagerApiSpecHelpers
include HttpBasicAuthHelpers include HttpBasicAuthHelpers
...@@ -13,92 +13,26 @@ RSpec.describe API::NugetPackages do ...@@ -13,92 +13,26 @@ RSpec.describe API::NugetPackages do
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) } let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
describe 'GET /api/v4/projects/:id/packages/nuget' do describe 'GET /api/v4/projects/:id/packages/nuget' do
it_behaves_like 'handling nuget service requests' do
let(:url) { "/projects/#{project.id}/packages/nuget/index.json" } let(:url) { "/projects/#{project.id}/packages/nuget/index.json" }
subject { get api(url) }
context 'without the need for a license' do
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
context 'personal token' do
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | true | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | true | false | 'process nuget service index request' | :success
'PUBLIC' | :guest | true | false | 'process nuget service index request' | :success
'PUBLIC' | :developer | false | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | false | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | false | false | 'process nuget service index request' | :success
'PUBLIC' | :guest | false | false | 'process nuget service index request' | :success
'PUBLIC' | :anonymous | false | true | 'process nuget service index request' | :success
'PRIVATE' | :developer | true | true | 'process nuget service index request' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member] describe 'GET /api/v4/projects/:id/packages/nuget/metadata/*package_name/index' do
end it_behaves_like 'handling nuget metadata requests with package name' do
end let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/index.json" }
context 'with job token' do
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | true | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :developer | false | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | false | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process nuget service index request' | :success
'PRIVATE' | :developer | true | true | 'process nuget service index request' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end end
with_them do
let(:job) { user_token ? create(:ci_build, project: project, user: user, status: :running) : double(token: 'wrong') }
let(:headers) { user_role == :anonymous ? {} : job_basic_auth_header(job) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member] describe 'GET /api/v4/projects/:id/packages/nuget/metadata/*package_name/*package_version' do
end it_behaves_like 'handling nuget metadata requests with package name and package version' do
let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/#{package.version}.json" }
end end
end end
it_behaves_like 'deploy token for package GET requests' describe 'GET /api/v4/projects/:id/packages/nuget/query' do
it_behaves_like 'handling nuget search requests' do
it_behaves_like 'rejects nuget access with unknown project id' let(:url) { "/projects/#{project.id}/packages/nuget/query?#{query_parameters.to_query}" }
it_behaves_like 'rejects nuget access with invalid project id'
end end
end end
...@@ -235,130 +169,6 @@ RSpec.describe API::NugetPackages do ...@@ -235,130 +169,6 @@ RSpec.describe API::NugetPackages do
end end
end end
describe 'GET /api/v4/projects/:id/packages/nuget/metadata/*package_name/index' do
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
let_it_be(:packages) { create_list(:nuget_package, 5, :with_metadatum, name: package_name, project: project) }
let_it_be(:tags) { packages.each { |pkg| create(:packages_tag, package: pkg, name: 'test') } }
let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/index.json" }
subject { get api(url) }
before do
packages.each { |pkg| create_dependencies_for(pkg) }
end
context 'without the need for license' do
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | true | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :developer | true | false | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | true | false | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :developer | false | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | false | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :developer | false | false | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | false | false | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :anonymous | false | true | 'process nuget metadata request at package name level' | :success
'PRIVATE' | :developer | true | true | 'process nuget metadata request at package name level' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
it_behaves_like 'deploy token for package GET requests'
it_behaves_like 'rejects nuget access with unknown project id'
it_behaves_like 'rejects nuget access with invalid project id'
end
end
end
describe 'GET /api/v4/projects/:id/packages/nuget/metadata/*package_name/*package_version' do
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
let_it_be(:package) { create(:nuget_package, :with_metadatum, name: 'Dummy.Package', project: project) }
let_it_be(:tag) { create(:packages_tag, package: package, name: 'test') }
let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/#{package.version}.json" }
subject { get api(url) }
before do
create_dependencies_for(package)
end
context 'without the need for a license' do
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | true | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :developer | true | false | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | true | false | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :developer | false | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | false | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :developer | false | false | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | false | false | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :anonymous | false | true | 'process nuget metadata request at package name and package version level' | :success
'PRIVATE' | :developer | true | true | 'process nuget metadata request at package name and package version level' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
it_behaves_like 'deploy token for package GET requests'
context 'with invalid package name' do
let_it_be(:package_name) { 'Unkown' }
it_behaves_like 'rejects nuget packages access', :developer, :not_found
end
end
end
describe 'GET /api/v4/projects/:id/packages/nuget/download/*package_name/index' do describe 'GET /api/v4/projects/:id/packages/nuget/download/*package_name/index' do
let_it_be(:package_name) { 'Dummy.Package' } let_it_be(:package_name) { 'Dummy.Package' }
let_it_be(:packages) { create_list(:nuget_package, 5, name: package_name, project: project) } let_it_be(:packages) { create_list(:nuget_package, 5, name: package_name, project: project) }
...@@ -467,67 +277,4 @@ RSpec.describe API::NugetPackages do ...@@ -467,67 +277,4 @@ RSpec.describe API::NugetPackages do
it_behaves_like 'rejects nuget access with invalid project id' it_behaves_like 'rejects nuget access with invalid project id'
end end
end end
describe 'GET /api/v4/projects/:id/packages/nuget/query' do
let_it_be(:package_a) { create(:nuget_package, :with_metadatum, name: 'Dummy.PackageA', project: project) }
let_it_be(:tag) { create(:packages_tag, package: package_a, name: 'test') }
let_it_be(:packages_b) { create_list(:nuget_package, 5, name: 'Dummy.PackageB', project: project) }
let_it_be(:packages_c) { create_list(:nuget_package, 5, name: 'Dummy.PackageC', project: project) }
let_it_be(:package_d) { create(:nuget_package, name: 'Dummy.PackageD', version: '5.0.5-alpha', project: project) }
let_it_be(:package_e) { create(:nuget_package, name: 'Foo.BarE', project: project) }
let(:search_term) { 'uMmy' }
let(:take) { 26 }
let(:skip) { 0 }
let(:include_prereleases) { true }
let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases } }
let(:url) { "/projects/#{project.id}/packages/nuget/query?#{query_parameters.to_query}" }
subject { get api(url) }
context 'without the need for a license' do
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget search request' | :success
'PUBLIC' | :guest | true | true | 'process nuget search request' | :success
'PUBLIC' | :developer | true | false | 'process nuget search request' | :success
'PUBLIC' | :guest | true | false | 'process nuget search request' | :success
'PUBLIC' | :developer | false | true | 'process nuget search request' | :success
'PUBLIC' | :guest | false | true | 'process nuget search request' | :success
'PUBLIC' | :developer | false | false | 'process nuget search request' | :success
'PUBLIC' | :guest | false | false | 'process nuget search request' | :success
'PUBLIC' | :anonymous | false | true | 'process nuget search request' | :success
'PRIVATE' | :developer | true | true | 'process nuget search request' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
it_behaves_like 'deploy token for package GET requests'
it_behaves_like 'rejects nuget access with unknown project id'
it_behaves_like 'rejects nuget access with invalid project id'
end
end
end end
# frozen_string_literal: true
RSpec.shared_examples 'handling nuget service requests' do
subject { get api(url) }
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
context 'personal token' do
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | true | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | true | false | 'process nuget service index request' | :success
'PUBLIC' | :guest | true | false | 'process nuget service index request' | :success
'PUBLIC' | :developer | false | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | false | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | false | false | 'process nuget service index request' | :success
'PUBLIC' | :guest | false | false | 'process nuget service index request' | :success
'PUBLIC' | :anonymous | false | true | 'process nuget service index request' | :success
'PRIVATE' | :developer | true | true | 'process nuget service index request' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
context 'with job token' do
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | true | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :developer | false | true | 'process nuget service index request' | :success
'PUBLIC' | :guest | false | true | 'process nuget service index request' | :success
'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process nuget service index request' | :success
'PRIVATE' | :developer | true | true | 'process nuget service index request' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
let(:job) { user_token ? create(:ci_build, project: project, user: user, status: :running) : double(token: 'wrong') }
let(:headers) { user_role == :anonymous ? {} : job_basic_auth_header(job) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
end
it_behaves_like 'deploy token for package GET requests'
it_behaves_like 'rejects nuget access with unknown project id'
it_behaves_like 'rejects nuget access with invalid project id'
end
RSpec.shared_examples 'handling nuget metadata requests with package name' do
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
let_it_be(:packages) { create_list(:nuget_package, 5, :with_metadatum, name: package_name, project: project) }
let_it_be(:tags) { packages.each { |pkg| create(:packages_tag, package: pkg, name: 'test') } }
subject { get api(url) }
before do
packages.each { |pkg| create_dependencies_for(pkg) }
end
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | true | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :developer | true | false | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | true | false | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :developer | false | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | false | true | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :developer | false | false | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :guest | false | false | 'process nuget metadata request at package name level' | :success
'PUBLIC' | :anonymous | false | true | 'process nuget metadata request at package name level' | :success
'PRIVATE' | :developer | true | true | 'process nuget metadata request at package name level' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
it_behaves_like 'deploy token for package GET requests'
it_behaves_like 'rejects nuget access with unknown project id'
it_behaves_like 'rejects nuget access with invalid project id'
end
end
RSpec.shared_examples 'handling nuget metadata requests with package name and package version' do
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
let_it_be(:package) { create(:nuget_package, :with_metadatum, name: 'Dummy.Package', project: project) }
let_it_be(:tag) { create(:packages_tag, package: package, name: 'test') }
subject { get api(url) }
before do
create_dependencies_for(package)
end
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | true | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :developer | true | false | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | true | false | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :developer | false | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | false | true | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :developer | false | false | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :guest | false | false | 'process nuget metadata request at package name and package version level' | :success
'PUBLIC' | :anonymous | false | true | 'process nuget metadata request at package name and package version level' | :success
'PRIVATE' | :developer | true | true | 'process nuget metadata request at package name and package version level' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
it_behaves_like 'deploy token for package GET requests'
context 'with invalid package name' do
let_it_be(:package_name) { 'Unkown' }
it_behaves_like 'rejects nuget packages access', :developer, :not_found
end
end
RSpec.shared_examples 'handling nuget search requests' do
let_it_be(:package_a) { create(:nuget_package, :with_metadatum, name: 'Dummy.PackageA', project: project) }
let_it_be(:tag) { create(:packages_tag, package: package_a, name: 'test') }
let_it_be(:packages_b) { create_list(:nuget_package, 5, name: 'Dummy.PackageB', project: project) }
let_it_be(:packages_c) { create_list(:nuget_package, 5, name: 'Dummy.PackageC', project: project) }
let_it_be(:package_d) { create(:nuget_package, name: 'Dummy.PackageD', version: '5.0.5-alpha', project: project) }
let_it_be(:package_e) { create(:nuget_package, name: 'Foo.BarE', project: project) }
let(:search_term) { 'uMmy' }
let(:take) { 26 }
let(:skip) { 0 }
let(:include_prereleases) { true }
let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases } }
subject { get api(url) }
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process nuget search request' | :success
'PUBLIC' | :guest | true | true | 'process nuget search request' | :success
'PUBLIC' | :developer | true | false | 'process nuget search request' | :success
'PUBLIC' | :guest | true | false | 'process nuget search request' | :success
'PUBLIC' | :developer | false | true | 'process nuget search request' | :success
'PUBLIC' | :guest | false | true | 'process nuget search request' | :success
'PUBLIC' | :developer | false | false | 'process nuget search request' | :success
'PUBLIC' | :guest | false | false | 'process nuget search request' | :success
'PUBLIC' | :anonymous | false | true | 'process nuget search request' | :success
'PRIVATE' | :developer | true | true | 'process nuget search request' | :success
'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :guest | false | true | 'rejects nuget packages access' | :not_found
'PRIVATE' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'rejects nuget packages access' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
it_behaves_like 'deploy token for package GET requests'
it_behaves_like 'rejects nuget access with unknown project id'
it_behaves_like 'rejects nuget access with invalid project id'
end
...@@ -26,7 +26,7 @@ RSpec.shared_examples 'process nuget service index request' do |user_type, statu ...@@ -26,7 +26,7 @@ RSpec.shared_examples 'process nuget service index request' do |user_type, statu
it_behaves_like 'returning response status', status it_behaves_like 'returning response status', status
it_behaves_like 'a package tracking event', described_class.name, 'cli_metadata' it_behaves_like 'a package tracking event', 'API::NugetPackages', 'cli_metadata'
it 'returns a valid json response' do it 'returns a valid json response' do
subject subject
...@@ -169,7 +169,7 @@ RSpec.shared_examples 'process nuget upload' do |user_type, status, add_member = ...@@ -169,7 +169,7 @@ RSpec.shared_examples 'process nuget upload' do |user_type, status, add_member =
context 'with correct params' do context 'with correct params' do
it_behaves_like 'package workhorse uploads' it_behaves_like 'package workhorse uploads'
it_behaves_like 'creates nuget package files' it_behaves_like 'creates nuget package files'
it_behaves_like 'a package tracking event', described_class.name, 'push_package' it_behaves_like 'a package tracking event', 'API::NugetPackages', 'push_package'
end end
end end
...@@ -286,7 +286,7 @@ RSpec.shared_examples 'process nuget download content request' do |user_type, st ...@@ -286,7 +286,7 @@ RSpec.shared_examples 'process nuget download content request' do |user_type, st
it_behaves_like 'returning response status', status it_behaves_like 'returning response status', status
it_behaves_like 'a package tracking event', described_class.name, 'pull_package' it_behaves_like 'a package tracking event', 'API::NugetPackages', 'pull_package'
it 'returns a valid package archive' do it 'returns a valid package archive' do
subject subject
...@@ -336,7 +336,7 @@ RSpec.shared_examples 'process nuget search request' do |user_type, status, add_ ...@@ -336,7 +336,7 @@ RSpec.shared_examples 'process nuget search request' do |user_type, status, add_
it_behaves_like 'returns a valid json search response', status, 4, [1, 5, 5, 1] it_behaves_like 'returns a valid json search response', status, 4, [1, 5, 5, 1]
it_behaves_like 'a package tracking event', described_class.name, 'search_package' it_behaves_like 'a package tracking event', 'API::NugetPackages', 'search_package'
context 'with skip set to 2' do context 'with skip set to 2' do
let(:skip) { 2 } let(:skip) { 2 }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment