diff options
Diffstat (limited to 'spec/requests/api/pypi_packages_spec.rb')
-rw-r--r-- | spec/requests/api/pypi_packages_spec.rb | 242 |
1 files changed, 88 insertions, 154 deletions
diff --git a/spec/requests/api/pypi_packages_spec.rb b/spec/requests/api/pypi_packages_spec.rb index 718004a0087..86925e6a0ba 100644 --- a/spec/requests/api/pypi_packages_spec.rb +++ b/spec/requests/api/pypi_packages_spec.rb @@ -8,69 +8,59 @@ RSpec.describe API::PypiPackages do using RSpec::Parameterized::TableSyntax let_it_be(:user) { create(:user) } - let_it_be(:project, reload: true) { create(:project, :public) } + let_it_be_with_reload(:group) { create(:group) } + let_it_be_with_reload(:project) { create(:project, :public, group: group) } let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) } let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) } - let_it_be(:job) { create(:ci_build, :running, user: user) } + let_it_be(:job) { create(:ci_build, :running, user: user, project: project) } + let(:headers) { {} } - describe 'GET /api/v4/projects/:id/packages/pypi/simple/:package_name' do + context 'simple API endpoint' do let_it_be(:package) { create(:pypi_package, project: project) } - let(:url) { "/projects/#{project.id}/packages/pypi/simple/#{package.name}" } - subject { get api(url) } + subject { get api(url), headers: headers } - context 'with valid project' do - where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do - 'PUBLIC' | :developer | true | true | 'PyPI package versions' | :success - 'PUBLIC' | :guest | true | true | 'PyPI package versions' | :success - 'PUBLIC' | :developer | true | false | 'PyPI package versions' | :success - 'PUBLIC' | :guest | true | false | 'PyPI package versions' | :success - 'PUBLIC' | :developer | false | true | 'PyPI package versions' | :success - 'PUBLIC' | :guest | false | true | 'PyPI package versions' | :success - 'PUBLIC' | :developer | false | false | 'PyPI package versions' | :success - 'PUBLIC' | :guest | false | false | 'PyPI package versions' | :success - 'PUBLIC' | :anonymous | false | true | 'PyPI package versions' | :success - 'PRIVATE' | :developer | true | true | 'PyPI package versions' | :success - 'PRIVATE' | :guest | true | true | 'process PyPI api request' | :forbidden - 'PRIVATE' | :developer | true | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :guest | true | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :developer | false | true | 'process PyPI api request' | :not_found - 'PRIVATE' | :guest | false | true | 'process PyPI api request' | :not_found - 'PRIVATE' | :developer | false | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :guest | false | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :anonymous | false | true | 'process PyPI api request' | :unauthorized - end + describe 'GET /api/v4/groups/:id/-/packages/pypi/simple/:package_name' do + let(:url) { "/groups/#{group.id}/-/packages/pypi/simple/#{package.name}" } + let(:snowplow_gitlab_standard_context) { {} } - with_them do - let(:token) { user_token ? personal_access_token.token : 'wrong' } - let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) } + it_behaves_like 'pypi simple API endpoint' + it_behaves_like 'rejects PyPI access with unknown group id' - subject { get api(url), headers: headers } + context 'deploy tokens' do + let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token, group: group) } before do - project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false)) + project.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) + group.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) end - it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member] + it_behaves_like 'deploy token for package GET requests' end - end - context 'with a normalized package name' do - let_it_be(:package) { create(:pypi_package, project: project, name: 'my.package') } - let(:url) { "/projects/#{project.id}/packages/pypi/simple/my-package" } - let(:headers) { basic_auth_header(user.username, personal_access_token.token) } + context 'job token' do + before do + project.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) + group.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) + group.add_developer(user) + end - subject { get api(url), headers: headers } + it_behaves_like 'job token for package GET requests' + end - it_behaves_like 'PyPI package versions', :developer, :success + it_behaves_like 'a pypi user namespace endpoint' end - it_behaves_like 'deploy token for package GET requests' - - it_behaves_like 'job token for package GET requests' + describe 'GET /api/v4/projects/:id/packages/pypi/simple/:package_name' do + let(:url) { "/projects/#{project.id}/packages/pypi/simple/#{package.name}" } + let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } } - it_behaves_like 'rejects PyPI access with unknown project id' + it_behaves_like 'pypi simple API endpoint' + it_behaves_like 'rejects PyPI access with unknown project id' + it_behaves_like 'deploy token for package GET requests' + it_behaves_like 'job token for package GET requests' + end end describe 'POST /api/v4/projects/:id/packages/pypi/authorize' do @@ -82,25 +72,25 @@ RSpec.describe API::PypiPackages do subject { post api(url), headers: headers } context 'with valid project' do - where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do - 'PUBLIC' | :developer | true | true | 'process PyPI api request' | :success - 'PUBLIC' | :guest | true | true | 'process PyPI api request' | :forbidden - 'PUBLIC' | :developer | true | false | 'process PyPI api request' | :unauthorized - 'PUBLIC' | :guest | true | false | 'process PyPI api request' | :unauthorized - 'PUBLIC' | :developer | false | true | 'process PyPI api request' | :forbidden - 'PUBLIC' | :guest | false | true | 'process PyPI api request' | :forbidden - 'PUBLIC' | :developer | false | false | 'process PyPI api request' | :unauthorized - 'PUBLIC' | :guest | false | false | 'process PyPI api request' | :unauthorized - 'PUBLIC' | :anonymous | false | true | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :developer | true | true | 'process PyPI api request' | :success - 'PRIVATE' | :guest | true | true | 'process PyPI api request' | :forbidden - 'PRIVATE' | :developer | true | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :guest | true | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :developer | false | true | 'process PyPI api request' | :not_found - 'PRIVATE' | :guest | false | true | 'process PyPI api request' | :not_found - 'PRIVATE' | :developer | false | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :guest | false | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :anonymous | false | true | 'process PyPI api request' | :unauthorized + where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do + :public | :developer | true | true | 'process PyPI api request' | :success + :public | :guest | true | true | 'process PyPI api request' | :forbidden + :public | :developer | true | false | 'process PyPI api request' | :unauthorized + :public | :guest | true | false | 'process PyPI api request' | :unauthorized + :public | :developer | false | true | 'process PyPI api request' | :forbidden + :public | :guest | false | true | 'process PyPI api request' | :forbidden + :public | :developer | false | false | 'process PyPI api request' | :unauthorized + :public | :guest | false | false | 'process PyPI api request' | :unauthorized + :public | :anonymous | false | true | 'process PyPI api request' | :unauthorized + :private | :developer | true | true | 'process PyPI api request' | :success + :private | :guest | true | true | 'process PyPI api request' | :forbidden + :private | :developer | true | false | 'process PyPI api request' | :unauthorized + :private | :guest | true | false | 'process PyPI api request' | :unauthorized + :private | :developer | false | true | 'process PyPI api request' | :not_found + :private | :guest | false | true | 'process PyPI api request' | :not_found + :private | :developer | false | false | 'process PyPI api request' | :unauthorized + :private | :guest | false | false | 'process PyPI api request' | :unauthorized + :private | :anonymous | false | true | 'process PyPI api request' | :unauthorized end with_them do @@ -109,7 +99,7 @@ RSpec.describe API::PypiPackages do let(:headers) { user_headers.merge(workhorse_headers) } before do - project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false)) + project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s)) end it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member] @@ -133,6 +123,7 @@ RSpec.describe API::PypiPackages do let(:base_params) { { requires_python: requires_python, version: '1.0.0', name: 'sample-project', sha256_digest: '123' } } let(:params) { base_params.merge(content: temp_file(file_name)) } let(:send_rewritten_field) { true } + let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: user } } subject do workhorse_finalize( @@ -146,25 +137,25 @@ RSpec.describe API::PypiPackages do end context 'with valid project' do - where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do - 'PUBLIC' | :developer | true | true | 'PyPI package creation' | :created - 'PUBLIC' | :guest | true | true | 'process PyPI api request' | :forbidden - 'PUBLIC' | :developer | true | false | 'process PyPI api request' | :unauthorized - 'PUBLIC' | :guest | true | false | 'process PyPI api request' | :unauthorized - 'PUBLIC' | :developer | false | true | 'process PyPI api request' | :forbidden - 'PUBLIC' | :guest | false | true | 'process PyPI api request' | :forbidden - 'PUBLIC' | :developer | false | false | 'process PyPI api request' | :unauthorized - 'PUBLIC' | :guest | false | false | 'process PyPI api request' | :unauthorized - 'PUBLIC' | :anonymous | false | true | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :developer | true | true | 'process PyPI api request' | :created - 'PRIVATE' | :guest | true | true | 'process PyPI api request' | :forbidden - 'PRIVATE' | :developer | true | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :guest | true | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :developer | false | true | 'process PyPI api request' | :not_found - 'PRIVATE' | :guest | false | true | 'process PyPI api request' | :not_found - 'PRIVATE' | :developer | false | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :guest | false | false | 'process PyPI api request' | :unauthorized - 'PRIVATE' | :anonymous | false | true | 'process PyPI api request' | :unauthorized + where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do + :public | :developer | true | true | 'PyPI package creation' | :created + :public | :guest | true | true | 'process PyPI api request' | :forbidden + :public | :developer | true | false | 'process PyPI api request' | :unauthorized + :public | :guest | true | false | 'process PyPI api request' | :unauthorized + :public | :developer | false | true | 'process PyPI api request' | :forbidden + :public | :guest | false | true | 'process PyPI api request' | :forbidden + :public | :developer | false | false | 'process PyPI api request' | :unauthorized + :public | :guest | false | false | 'process PyPI api request' | :unauthorized + :public | :anonymous | false | true | 'process PyPI api request' | :unauthorized + :private | :developer | true | true | 'process PyPI api request' | :created + :private | :guest | true | true | 'process PyPI api request' | :forbidden + :private | :developer | true | false | 'process PyPI api request' | :unauthorized + :private | :guest | true | false | 'process PyPI api request' | :unauthorized + :private | :developer | false | true | 'process PyPI api request' | :not_found + :private | :guest | false | true | 'process PyPI api request' | :not_found + :private | :developer | false | false | 'process PyPI api request' | :unauthorized + :private | :guest | false | false | 'process PyPI api request' | :unauthorized + :private | :anonymous | false | true | 'process PyPI api request' | :unauthorized end with_them do @@ -173,7 +164,7 @@ RSpec.describe API::PypiPackages do let(:headers) { user_headers.merge(workhorse_headers) } before do - project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false)) + project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(visibility_level.to_s)) end it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member] @@ -187,7 +178,7 @@ RSpec.describe API::PypiPackages do let(:headers) { user_headers.merge(workhorse_headers) } before do - project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) + project.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) end it_behaves_like 'process PyPI api request', :developer, :bad_request, true @@ -225,84 +216,27 @@ RSpec.describe API::PypiPackages do end end - describe 'GET /api/v4/projects/:id/packages/pypi/files/:sha256/*file_identifier' do + context 'file download endpoint' do let_it_be(:package_name) { 'Dummy-Package' } let_it_be(:package) { create(:pypi_package, project: project, name: package_name, version: '1.0.0') } - let(:url) { "/projects/#{project.id}/packages/pypi/files/#{package.package_files.first.file_sha256}/#{package_name}-1.0.0.tar.gz" } - - subject { get api(url) } - - context 'with valid project' do - where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do - 'PUBLIC' | :developer | true | true | 'PyPI package download' | :success - 'PUBLIC' | :guest | true | true | 'PyPI package download' | :success - 'PUBLIC' | :developer | true | false | 'PyPI package download' | :success - 'PUBLIC' | :guest | true | false | 'PyPI package download' | :success - 'PUBLIC' | :developer | false | true | 'PyPI package download' | :success - 'PUBLIC' | :guest | false | true | 'PyPI package download' | :success - 'PUBLIC' | :developer | false | false | 'PyPI package download' | :success - 'PUBLIC' | :guest | false | false | 'PyPI package download' | :success - 'PUBLIC' | :anonymous | false | true | 'PyPI package download' | :success - 'PRIVATE' | :developer | true | true | 'PyPI package download' | :success - 'PRIVATE' | :guest | true | true | 'PyPI package download' | :success - 'PRIVATE' | :developer | true | false | 'PyPI package download' | :success - 'PRIVATE' | :guest | true | false | 'PyPI package download' | :success - 'PRIVATE' | :developer | false | true | 'PyPI package download' | :success - 'PRIVATE' | :guest | false | true | 'PyPI package download' | :success - 'PRIVATE' | :developer | false | false | 'PyPI package download' | :success - 'PRIVATE' | :guest | false | false | 'PyPI package download' | :success - 'PRIVATE' | :anonymous | false | true | 'PyPI package download' | :success - 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 } + 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 deploy token headers' do - let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token) } - - context 'valid token' do - it_behaves_like 'returning response status', :success - end - - context 'invalid token' do - let(:headers) { basic_auth_header('foo', 'bar') } + describe 'GET /api/v4/groups/:id/-/packages/pypi/files/:sha256/*file_identifier' do + let(:url) { "/groups/#{group.id}/-/packages/pypi/files/#{package.package_files.first.file_sha256}/#{package_name}-1.0.0.tar.gz" } + let(:snowplow_gitlab_standard_context) { {} } - it_behaves_like 'returning response status', :success - end + it_behaves_like 'pypi file download endpoint' + it_behaves_like 'rejects PyPI access with unknown group id' + it_behaves_like 'a pypi user namespace endpoint' end - context 'with job token headers' do - let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token) } - - context 'valid token' do - it_behaves_like 'returning response status', :success - end - - context 'invalid token' do - let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar') } - - it_behaves_like 'returning response status', :success - end - - context 'invalid user' do - let(:headers) { basic_auth_header('foo', job.token) } + describe 'GET /api/v4/projects/:id/packages/pypi/files/:sha256/*file_identifier' do + let(:url) { "/projects/#{project.id}/packages/pypi/files/#{package.package_files.first.file_sha256}/#{package_name}-1.0.0.tar.gz" } + let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace } } - it_behaves_like 'returning response status', :success - end + it_behaves_like 'pypi file download endpoint' + it_behaves_like 'rejects PyPI access with unknown project id' end - - it_behaves_like 'rejects PyPI access with unknown project id' end end |