summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/requests
diff options
context:
space:
mode:
Diffstat (limited to 'spec/support/shared_examples/requests')
-rw-r--r--spec/support/shared_examples/requests/api/boards_shared_examples.rb33
-rw-r--r--spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb69
-rw-r--r--spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb146
-rw-r--r--spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb58
-rw-r--r--spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb219
-rw-r--r--spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/rack_attack_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/requests/releases_shared_examples.rb61
-rw-r--r--spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb84
9 files changed, 568 insertions, 109 deletions
diff --git a/spec/support/shared_examples/requests/api/boards_shared_examples.rb b/spec/support/shared_examples/requests/api/boards_shared_examples.rb
index 0096aab55e3..8e8edd61ef9 100644
--- a/spec/support/shared_examples/requests/api/boards_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/boards_shared_examples.rb
@@ -44,16 +44,35 @@ RSpec.shared_examples 'group and project boards' do |route_definition, ee = fals
expect_schema_match_for(response, 'public_api/v4/boards', ee)
end
+ end
+ end
- describe "GET #{route_definition}/:board_id" do
- let(:url) { "#{root_url}/#{board.id}" }
+ describe "GET #{route_definition}/:board_id" do
+ let(:url) { "#{root_url}/#{board.id}" }
- it 'get a single board by id' do
- get api(url, user)
+ it 'get a single board by id' do
+ get api(url, user)
- expect_schema_match_for(response, 'public_api/v4/board', ee)
- end
- end
+ expect_schema_match_for(response, 'public_api/v4/board', ee)
+ end
+ end
+
+ describe "PUT #{route_definition}/:board_id" do
+ let(:url) { "#{root_url}/#{board.id}" }
+
+ it 'updates the board name' do
+ put api(url, user), params: { name: 'changed board name' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['name']).to eq('changed board name')
+ end
+
+ it 'updates the issue board booleans' do
+ put api(url, user), params: { hide_backlog_list: true, hide_closed_list: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['hide_backlog_list']).to eq(true)
+ expect(json_response['hide_closed_list']).to eq(true)
end
end
diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
index f55043fe64f..83ba72c12aa 100644
--- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
@@ -37,9 +37,9 @@ RSpec.shared_context 'Debian repository shared context' do |object_type|
let(:params) { workhorse_params }
let(:auth_headers) { {} }
+ let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
let(:workhorse_headers) do
if method == :put
- workhorse_token = JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256')
{ 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token }
else
{}
@@ -117,12 +117,13 @@ RSpec.shared_examples 'Debian project repository PUT request' do |user_role, add
and_body = body.nil? ? '' : ' and expected body'
if status == :created
- it 'creates package files' do
+ it 'creates package files', :aggregate_failures do
pending "Debian package creation not implemented"
expect { subject }
.to change { project.packages.debian.count }.by(1)
expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('text/plain')
unless body.nil?
expect(response.body).to eq(body)
@@ -130,7 +131,59 @@ RSpec.shared_examples 'Debian project repository PUT request' do |user_role, add
end
it_behaves_like 'a package tracking event', described_class.name, 'push_package'
else
- it "returns #{status}#{and_body}" do
+ it "returns #{status}#{and_body}", :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to eq(body)
+ end
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'Debian project repository PUT authorize request' do |user_role, add_member, status, body, is_authorize|
+ context "for user type #{user_role}" do
+ before do
+ project.send("add_#{user_role}", user) if add_member && user_role != :anonymous
+ end
+
+ and_body = body.nil? ? '' : ' and expected body'
+
+ if status == :created
+ it 'authorizes package file upload', :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ expect(json_response['TempPath']).to eq(Packages::PackageFileUploader.workhorse_local_upload_path)
+ expect(json_response['RemoteObject']).to be_nil
+ expect(json_response['MaximumSize']).to be_nil
+ end
+
+ context 'without a valid token' do
+ let(:workhorse_token) { 'invalid' }
+
+ it 'rejects request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'bypassing gitlab-workhorse' do
+ let(:workhorse_headers) { {} }
+
+ it 'rejects request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ else
+ it "returns #{status}#{and_body}", :aggregate_failures do
subject
expect(response).to have_gitlab_http_status(status)
@@ -194,7 +247,7 @@ RSpec.shared_examples 'Debian project repository GET endpoint' do |success_statu
it_behaves_like 'rejects Debian access with unknown project id'
end
-RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_status, success_body|
+RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_status, success_body, is_authorize = false|
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
@@ -221,7 +274,13 @@ RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_statu
with_them do
include_context 'Debian repository project access', params[:project_visibility_level], params[:user_role], params[:user_token], :basic do
- it_behaves_like 'Debian project repository PUT request', params[:user_role], params[:member], params[:expected_status], params[:expected_body]
+ desired_behavior = if is_authorize
+ 'Debian project repository PUT authorize request'
+ else
+ 'Debian project repository PUT request'
+ end
+
+ it_behaves_like desired_behavior, params[:user_role], params[:member], params[:expected_status], params[:expected_body]
end
end
end
diff --git a/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
index f808d12baf4..7b7d2a33e8c 100644
--- a/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
@@ -1,31 +1,31 @@
# frozen_string_literal: true
-RSpec.shared_examples 'handling nuget service requests' do
+RSpec.shared_examples 'handling nuget service requests' do |anonymous_requests_example_name: 'process nuget service index request', anonymous_requests_status: :success|
subject { get api(url) }
- context 'with valid project' do
+ context 'with valid target' 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
+ where(: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 | anonymous_requests_example_name | anonymous_requests_status
+ '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
@@ -35,7 +35,7 @@ RSpec.shared_examples 'handling nuget service requests' do
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
@@ -43,7 +43,7 @@ RSpec.shared_examples 'handling nuget service requests' do
end
context 'with job token' do
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ where(: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
@@ -52,7 +52,7 @@ RSpec.shared_examples 'handling nuget service requests' do
'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
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'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
@@ -71,7 +71,7 @@ RSpec.shared_examples 'handling nuget service requests' do
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
@@ -79,14 +79,18 @@ RSpec.shared_examples 'handling nuget service requests' do
end
end
- it_behaves_like 'deploy token for package GET requests'
+ it_behaves_like 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
- it_behaves_like 'rejects nuget access with unknown project id'
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget access with invalid project id'
+ it_behaves_like 'rejects nuget access with invalid target id'
end
-RSpec.shared_examples 'handling nuget metadata requests with package name' do
+RSpec.shared_examples 'handling nuget metadata requests with package name' do |anonymous_requests_example_name: 'process nuget metadata request at package name level', anonymous_requests_status: :success|
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
@@ -99,19 +103,19 @@ RSpec.shared_examples 'handling nuget metadata requests with package name' do
packages.each { |pkg| create_dependencies_for(pkg) }
end
- context 'with valid project' do
+ context 'with valid target' do
using RSpec::Parameterized::TableSyntax
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ where(: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 | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'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
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'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
@@ -130,21 +134,25 @@ RSpec.shared_examples 'handling nuget metadata requests with package name' do
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(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 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
- it_behaves_like 'rejects nuget access with unknown project id'
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget access with invalid project id'
+ it_behaves_like 'rejects nuget access with invalid target id'
end
end
-RSpec.shared_examples 'handling nuget metadata requests with package name and package version' do
+RSpec.shared_examples 'handling nuget metadata requests with package name and package version' do |anonymous_requests_example_name: 'process nuget metadata request at package name and package version level', anonymous_requests_status: :success|
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
@@ -157,19 +165,19 @@ RSpec.shared_examples 'handling nuget metadata requests with package name and pa
create_dependencies_for(package)
end
- context 'with valid project' do
+ context 'with valid target' do
using RSpec::Parameterized::TableSyntax
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ where(: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 | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'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
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'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
@@ -188,23 +196,25 @@ RSpec.shared_examples 'handling nuget metadata requests with package name and pa
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(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 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
- context 'with invalid package name' do
- let_it_be(:package_name) { 'Unkown' }
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget packages access', :developer, :not_found
- end
+ it_behaves_like 'rejects nuget access with invalid target id'
end
-RSpec.shared_examples 'handling nuget search requests' do
+RSpec.shared_examples 'handling nuget search requests' do |anonymous_requests_example_name: 'process nuget search request', anonymous_requests_status: :success|
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) }
@@ -219,19 +229,19 @@ RSpec.shared_examples 'handling nuget search requests' do
subject { get api(url) }
- context 'with valid project' do
+ context 'with valid target' do
using RSpec::Parameterized::TableSyntax
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ where(: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 | true | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'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
+ 'PUBLIC' | :developer | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'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
@@ -250,16 +260,20 @@ RSpec.shared_examples 'handling nuget search requests' do
subject { get api(url), headers: headers }
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
+ update_visibility_to(Gitlab::VisibilityLevel.const_get(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 'deploy token for package GET requests' do
+ before do
+ update_visibility_to(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
- it_behaves_like 'rejects nuget access with unknown project id'
+ it_behaves_like 'rejects nuget access with unknown target id'
- it_behaves_like 'rejects nuget access with invalid project id'
+ it_behaves_like 'rejects nuget access with invalid target id'
end
diff --git a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
index dc6ac5f0371..8b60857cdaf 100644
--- a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
@@ -3,7 +3,7 @@
RSpec.shared_examples 'rejects nuget packages access' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -21,7 +21,7 @@ end
RSpec.shared_examples 'process nuget service index request' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -37,7 +37,7 @@ RSpec.shared_examples 'process nuget service index request' do |user_type, statu
end
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/index.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/index.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -57,7 +57,7 @@ end
RSpec.shared_examples 'process nuget metadata request at package name level' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -65,7 +65,7 @@ RSpec.shared_examples 'process nuget metadata request at package name level' do
it_behaves_like 'returning nuget metadata json response with json schema', 'public_api/v4/packages/nuget/packages_metadata'
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/index.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/metadata/#{package_name}/index.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -83,7 +83,7 @@ end
RSpec.shared_examples 'process nuget metadata request at package name and package version level' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -91,7 +91,7 @@ RSpec.shared_examples 'process nuget metadata request at package name and packag
it_behaves_like 'returning nuget metadata json response with json schema', 'public_api/v4/packages/nuget/package_metadata'
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/metadata/#{package_name}/#{package.version}.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/metadata/#{package_name}/#{package.version}.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -109,7 +109,7 @@ end
RSpec.shared_examples 'process nuget workhorse authorization' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -128,7 +128,7 @@ RSpec.shared_examples 'process nuget workhorse authorization' do |user_type, sta
end
before do
- project.add_maintainer(user)
+ target.add_maintainer(user)
end
it_behaves_like 'returning response status', :forbidden
@@ -141,18 +141,18 @@ RSpec.shared_examples 'process nuget upload' do |user_type, status, add_member =
it 'creates package files' do
expect(::Packages::Nuget::ExtractionWorker).to receive(:perform_async).once
expect { subject }
- .to change { project.packages.count }.by(1)
+ .to change { target.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
expect(response).to have_gitlab_http_status(status)
- package_file = project.packages.last.package_files.reload.last
+ package_file = target.packages.last.package_files.reload.last
expect(package_file.file_name).to eq('package.nupkg')
end
end
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
context 'with object storage disabled' do
@@ -206,7 +206,7 @@ RSpec.shared_examples 'process nuget upload' do |user_type, status, add_member =
context 'with crafted package.path param' do
let(:crafted_file) { Tempfile.new('nuget.crafted.package.path') }
- let(:url) { "/projects/#{project.id}/packages/nuget?package.path=#{crafted_file.path}" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget?package.path=#{crafted_file.path}" }
let(:params) { { file: temp_file(file_name) } }
let(:file_key) { :file }
@@ -255,7 +255,7 @@ RSpec.shared_examples 'process nuget download versions request' do |user_type, s
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -263,7 +263,7 @@ RSpec.shared_examples 'process nuget download versions request' do |user_type, s
it_behaves_like 'returns a valid nuget download versions json response'
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/download/#{package_name}/index.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/download/#{package_name}/index.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -281,7 +281,7 @@ end
RSpec.shared_examples 'process nuget download content request' do |user_type, status, add_member = true|
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returning response status', status
@@ -295,7 +295,7 @@ RSpec.shared_examples 'process nuget download content request' do |user_type, st
end
context 'with invalid format' do
- let(:url) { "/projects/#{project.id}/packages/nuget/download/#{package.name}/#{package.version}/#{package.name}.#{package.version}.xls" }
+ let(:url) { "/#{target_type}/#{target.id}/packages/nuget/download/#{package.name}/#{package.version}/#{package.name}.#{package.version}.xls" }
it_behaves_like 'rejects nuget packages access', :anonymous, :not_found
end
@@ -331,7 +331,7 @@ RSpec.shared_examples 'process nuget search request' do |user_type, status, add_
context "for user type #{user_type}" do
before do
- project.send("add_#{user_type}", user) if add_member && user_type != :anonymous
+ target.send("add_#{user_type}", user) if add_member && user_type != :anonymous
end
it_behaves_like 'returns a valid json search response', status, 4, [1, 5, 5, 1]
@@ -370,20 +370,20 @@ RSpec.shared_examples 'process nuget search request' do |user_type, status, add_
end
end
-RSpec.shared_examples 'rejects nuget access with invalid project id' do
- context 'with a project id with invalid integers' do
+RSpec.shared_examples 'rejects nuget access with invalid target id' do
+ context 'with a target id with invalid integers' do
using RSpec::Parameterized::TableSyntax
- let(:project) { OpenStruct.new(id: id) }
+ let(:target) { OpenStruct.new(id: id) }
where(:id, :status) do
- '/../' | :unauthorized
+ '/../' | :bad_request
'' | :not_found
- '%20' | :unauthorized
- '%2e%2e%2f' | :unauthorized
- 'NaN' | :unauthorized
+ '%20' | :bad_request
+ '%2e%2e%2f' | :bad_request
+ 'NaN' | :bad_request
00002345 | :unauthorized
- 'anything25' | :unauthorized
+ 'anything25' | :bad_request
end
with_them do
@@ -392,9 +392,9 @@ RSpec.shared_examples 'rejects nuget access with invalid project id' do
end
end
-RSpec.shared_examples 'rejects nuget access with unknown project id' do
- context 'with an unknown project' do
- let(:project) { OpenStruct.new(id: 1234567890) }
+RSpec.shared_examples 'rejects nuget access with unknown target id' do
+ context 'with an unknown target' do
+ let(:target) { OpenStruct.new(id: 1234567890) }
context 'as anonymous' do
it_behaves_like 'rejects nuget packages access', :anonymous, :unauthorized
diff --git a/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
new file mode 100644
index 00000000000..b2970fd265d
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
@@ -0,0 +1,219 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'repository_storage_moves API' do |container_type|
+ include AccessMatchersForRequest
+
+ let_it_be(:user) { create(:admin) }
+
+ shared_examples 'get single container repository storage move' do
+ let(:repository_storage_move_id) { storage_move.id }
+
+ def get_container_repository_storage_move
+ get api(url, user)
+ end
+
+ it 'returns a container repository storage move', :aggregate_failures do
+ get_container_repository_storage_move
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema("public_api/v4/#{container_type.singularize}_repository_storage_move")
+ expect(json_response['id']).to eq(storage_move.id)
+ expect(json_response['state']).to eq(storage_move.human_state_name)
+ end
+
+ context 'non-existent container repository storage move' do
+ let(:repository_storage_move_id) { non_existing_record_id }
+
+ it 'returns not found' do
+ get_container_repository_storage_move
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ describe 'permissions' do
+ it { expect { get_container_repository_storage_move }.to be_allowed_for(:admin) }
+ it { expect { get_container_repository_storage_move }.to be_denied_for(:user) }
+ end
+ end
+
+ shared_examples 'get container repository storage move list' do
+ def get_container_repository_storage_moves
+ get api(url, user)
+ end
+
+ it 'returns container repository storage moves', :aggregate_failures do
+ get_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema("public_api/v4/#{container_type.singularize}_repository_storage_moves")
+ expect(json_response.size).to eq(1)
+ expect(json_response.first['id']).to eq(storage_move.id)
+ expect(json_response.first['state']).to eq(storage_move.human_state_name)
+ end
+
+ it 'avoids N+1 queries', :request_store do
+ # prevent `let` from polluting the control
+ get_container_repository_storage_moves
+
+ control = ActiveRecord::QueryRecorder.new { get_container_repository_storage_moves }
+
+ create(repository_storage_move_factory, :scheduled, container: container)
+
+ expect { get_container_repository_storage_moves }.not_to exceed_query_limit(control)
+ end
+
+ it 'returns the most recently created first' do
+ storage_move_oldest = create(repository_storage_move_factory, :scheduled, container: container, created_at: 2.days.ago)
+ storage_move_middle = create(repository_storage_move_factory, :scheduled, container: container, created_at: 1.day.ago)
+
+ get_container_repository_storage_moves
+
+ json_ids = json_response.map {|storage_move| storage_move['id'] }
+ expect(json_ids).to eq([
+ storage_move.id,
+ storage_move_middle.id,
+ storage_move_oldest.id
+ ])
+ end
+
+ describe 'permissions' do
+ it { expect { get_container_repository_storage_moves }.to be_allowed_for(:admin) }
+ it { expect { get_container_repository_storage_moves }.to be_denied_for(:user) }
+ end
+ end
+
+ describe "GET /#{container_type}/:id/repository_storage_moves" do
+ it_behaves_like 'get container repository storage move list' do
+ let(:url) { "/#{container_type}/#{container.id}/repository_storage_moves" }
+ end
+ end
+
+ describe "GET /#{container_type}/:id/repository_storage_moves/:repository_storage_move_id" do
+ it_behaves_like 'get single container repository storage move' do
+ let(:url) { "/#{container_type}/#{container.id}/repository_storage_moves/#{repository_storage_move_id}" }
+ end
+ end
+
+ describe "GET /#{container_type.singularize}_repository_storage_moves" do
+ it_behaves_like 'get container repository storage move list' do
+ let(:url) { "/#{container_type.singularize}_repository_storage_moves" }
+ end
+ end
+
+ describe "GET /#{container_type.singularize}_repository_storage_moves/:repository_storage_move_id" do
+ it_behaves_like 'get single container repository storage move' do
+ let(:url) { "/#{container_type.singularize}_repository_storage_moves/#{repository_storage_move_id}" }
+ end
+ end
+
+ describe "POST /#{container_type}/:id/repository_storage_moves" do
+ let(:url) { "/#{container_type}/#{container.id}/repository_storage_moves" }
+ let(:destination_storage_name) { 'test_second_storage' }
+
+ def create_container_repository_storage_move
+ post api(url, user), params: { destination_storage_name: destination_storage_name }
+ end
+
+ before do
+ stub_storage_settings('test_second_storage' => { 'path' => 'tmp/tests/extra_storage' })
+ end
+
+ it 'schedules a container repository storage move', :aggregate_failures do
+ create_container_repository_storage_move
+
+ storage_move = container.repository_storage_moves.last
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(response).to match_response_schema("public_api/v4/#{container_type.singularize}_repository_storage_move")
+ expect(json_response['id']).to eq(storage_move.id)
+ expect(json_response['state']).to eq('scheduled')
+ expect(json_response['source_storage_name']).to eq('default')
+ expect(json_response['destination_storage_name']).to eq(destination_storage_name)
+ end
+
+ describe 'permissions' do
+ it { expect { create_container_repository_storage_move }.to be_allowed_for(:admin) }
+ it { expect { create_container_repository_storage_move }.to be_denied_for(:user) }
+ end
+
+ context 'destination_storage_name is missing', :aggregate_failures do
+ let(:destination_storage_name) { nil }
+
+ it 'schedules a container repository storage move' do
+ create_container_repository_storage_move
+
+ storage_move = container.repository_storage_moves.last
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(response).to match_response_schema("public_api/v4/#{container_type.singularize}_repository_storage_move")
+ expect(json_response['id']).to eq(storage_move.id)
+ expect(json_response['state']).to eq('scheduled')
+ expect(json_response['source_storage_name']).to eq('default')
+ expect(json_response['destination_storage_name']).to be_present
+ end
+ end
+ end
+
+ describe "POST /#{container_type.singularize}_repository_storage_moves" do
+ let(:url) { "/#{container_type.singularize}_repository_storage_moves" }
+ let(:source_storage_name) { 'default' }
+ let(:destination_storage_name) { 'test_second_storage' }
+
+ def create_container_repository_storage_moves
+ post api(url, user), params: {
+ source_storage_name: source_storage_name,
+ destination_storage_name: destination_storage_name
+ }
+ end
+
+ before do
+ stub_storage_settings('test_second_storage' => { 'path' => 'tmp/tests/extra_storage' })
+ end
+
+ it 'schedules the worker' do
+ expect(bulk_worker_klass).to receive(:perform_async).with(source_storage_name, destination_storage_name)
+
+ create_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:accepted)
+ end
+
+ context 'source_storage_name is invalid' do
+ let(:destination_storage_name) { 'not-a-real-storage' }
+
+ it 'gives an error' do
+ create_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'destination_storage_name is missing' do
+ let(:destination_storage_name) { nil }
+
+ it 'schedules the worker' do
+ expect(bulk_worker_klass).to receive(:perform_async).with(source_storage_name, destination_storage_name)
+
+ create_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:accepted)
+ end
+ end
+
+ context 'destination_storage_name is invalid' do
+ let(:destination_storage_name) { 'not-a-real-storage' }
+
+ it 'gives an error' do
+ create_container_repository_storage_moves
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ describe 'normal user' do
+ it { expect { create_container_repository_storage_moves }.to be_denied_for(:user) }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb b/spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb
index 5748e873fd4..460e8d57a2b 100644
--- a/spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb
@@ -9,6 +9,7 @@ RSpec.shared_examples 'resolvable discussions API' do |parent_type, noteable_typ
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['notes'].size).to eq(1)
expect(json_response['notes'][0]['resolved']).to eq(true)
+ expect(Time.parse(json_response['notes'][0]['resolved_at'])).to be_like_time(note.reload.resolved_at)
end
it "unresolves discussion if resolved is false" do
@@ -18,6 +19,7 @@ RSpec.shared_examples 'resolvable discussions API' do |parent_type, noteable_typ
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['notes'].size).to eq(1)
expect(json_response['notes'][0]['resolved']).to eq(false)
+ expect(json_response['notes'][0]['resolved_at']).to be_nil
end
it "returns a 400 bad request error if resolved parameter is not passed" do
diff --git a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
index 5d300d38e4a..3b039049ca9 100644
--- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
@@ -154,10 +154,11 @@ RSpec.shared_examples 'rate-limited token-authenticated requests' do
end
def make_request(args)
+ path, options = args
if request_method == 'POST'
- post(*args)
+ post(path, **options)
else
- get(*args)
+ get(path, **options)
end
end
end
diff --git a/spec/support/shared_examples/requests/releases_shared_examples.rb b/spec/support/shared_examples/requests/releases_shared_examples.rb
new file mode 100644
index 00000000000..b835947e497
--- /dev/null
+++ b/spec/support/shared_examples/requests/releases_shared_examples.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'correct release milestone order' do
+ let_it_be_with_reload(:milestone_1) { create(:milestone, project: project) }
+ let_it_be_with_reload(:milestone_2) { create(:milestone, project: project) }
+
+ shared_examples 'correct sort order' do
+ it 'sorts milestonee_1 before milestone_2' do
+ freeze_time do
+ expect(actual_milestone_title_order).to eq([milestone_1.title, milestone_2.title])
+ end
+ end
+ end
+
+ context 'due_date' do
+ before do
+ milestone_1.update!(due_date: Time.zone.now, start_date: 1.day.ago, title: 'z')
+ milestone_2.update!(due_date: 1.day.from_now, start_date: 2.days.ago, title: 'a')
+ end
+
+ context 'when both milestones have a due_date' do
+ it_behaves_like 'correct sort order'
+ end
+
+ context 'when one milestone does not have a due_date' do
+ before do
+ milestone_2.update!(due_date: nil)
+ end
+
+ it_behaves_like 'correct sort order'
+ end
+ end
+
+ context 'start_date' do
+ before do
+ milestone_1.update!(due_date: 1.day.from_now, start_date: 1.day.ago, title: 'z' )
+ milestone_2.update!(due_date: 1.day.from_now, start_date: milestone_2_start_date, title: 'a' )
+ end
+
+ context 'when both milestones have a start_date' do
+ let(:milestone_2_start_date) { Time.zone.now }
+
+ it_behaves_like 'correct sort order'
+ end
+
+ context 'when one milestone does not have a start_date' do
+ let(:milestone_2_start_date) { nil }
+
+ it_behaves_like 'correct sort order'
+ end
+ end
+
+ context 'title' do
+ before do
+ milestone_1.update!(due_date: 1.day.from_now, start_date: Time.zone.now, title: 'a' )
+ milestone_2.update!(due_date: 1.day.from_now, start_date: Time.zone.now, title: 'z' )
+ end
+
+ it_behaves_like 'correct sort order'
+ end
+end
diff --git a/spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb b/spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb
new file mode 100644
index 00000000000..d82da1b01e1
--- /dev/null
+++ b/spec/support/shared_examples/requests/sessionless_auth_request_shared_examples.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'authenticates sessionless user for the request spec' do |params|
+ params ||= {}
+
+ before do
+ stub_authentication_activity_metrics(debug: false)
+ end
+
+ let(:user) { create(:user) }
+ let(:personal_access_token) { create(:personal_access_token, user: user) }
+ let(:default_params) { params.except(:public) || {} }
+
+ context "when the 'personal_access_token' param is populated with the personal access token" do
+ it 'logs the user in' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ get url, params: default_params.merge(private_token: personal_access_token.token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(controller.current_user).to eq(user)
+ end
+
+ it 'does not log the user in if page is public', if: params[:public] do
+ get url, params: default_params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(controller.current_user).to be_nil
+ end
+ end
+
+ context 'when the personal access token has no api scope', unless: params[:public] do
+ it 'does not log the user in' do
+ # Several instances of where these specs are shared route the request
+ # through ApplicationController#route_not_found which does not involve
+ # the usual auth code from Devise, so does not increment the
+ # :user_unauthenticated_counter
+ #
+ unless params[:ignore_incrementing]
+ expect(authentication_metrics)
+ .to increment(:user_unauthenticated_counter)
+ end
+
+ personal_access_token.update!(scopes: [:read_user])
+
+ get url, params: default_params.merge(private_token: personal_access_token.token)
+
+ expect(response).not_to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context "when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do
+ it 'logs the user in' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ headers = { 'PRIVATE-TOKEN': personal_access_token.token }
+ get url, params: default_params, headers: headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ it "doesn't log the user in otherwise", unless: params[:public] do
+ # Several instances of where these specs are shared route the request
+ # through ApplicationController#route_not_found which does not involve
+ # the usual auth code from Devise, so does not increment the
+ # :user_unauthenticated_counter
+ #
+ unless params[:ignore_incrementing]
+ expect(authentication_metrics)
+ .to increment(:user_unauthenticated_counter)
+ end
+
+ get url, params: default_params.merge(private_token: 'token')
+
+ expect(response).not_to have_gitlab_http_status(:ok)
+ end
+end