diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-18 09:08:33 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-18 09:08:33 +0300 |
commit | ef19a5c55c0f38b29f7ac98119041b054c6579c7 (patch) | |
tree | a622280b300c5d17a2af0a59ea9b2fa6a663d13c /spec | |
parent | aed2039d57b51847981e160cf7a1915f3ef490aa (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/graphql/types/release_assets_type_spec.rb | 2 | ||||
-rw-r--r-- | spec/graphql/types/release_source_type_spec.rb | 2 | ||||
-rw-r--r-- | spec/graphql/types/release_type_spec.rb | 1 | ||||
-rw-r--r-- | spec/models/ci/build_spec.rb | 6 | ||||
-rw-r--r-- | spec/policies/releases/source_policy_spec.rb | 88 | ||||
-rw-r--r-- | spec/presenters/release_presenter_spec.rb | 32 | ||||
-rw-r--r-- | spec/requests/api/graphql/project/release_spec.rb | 341 | ||||
-rw-r--r-- | spec/requests/api/graphql/project/releases_spec.rb | 152 | ||||
-rw-r--r-- | spec/requests/api/runner_spec.rb | 6 | ||||
-rw-r--r-- | spec/simplecov_env.rb | 2 |
10 files changed, 406 insertions, 226 deletions
diff --git a/spec/graphql/types/release_assets_type_spec.rb b/spec/graphql/types/release_assets_type_spec.rb index 58f0f7ee697..d8db162db62 100644 --- a/spec/graphql/types/release_assets_type_spec.rb +++ b/spec/graphql/types/release_assets_type_spec.rb @@ -7,7 +7,7 @@ describe GitlabSchema.types['ReleaseAssets'] do it 'has the expected fields' do expected_fields = %w[ - assets_count links sources + count links sources ] expect(described_class).to include_graphql_fields(*expected_fields) diff --git a/spec/graphql/types/release_source_type_spec.rb b/spec/graphql/types/release_source_type_spec.rb index e471ac1a5ac..929c6339479 100644 --- a/spec/graphql/types/release_source_type_spec.rb +++ b/spec/graphql/types/release_source_type_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe GitlabSchema.types['ReleaseSource'] do - it { expect(described_class).to require_graphql_authorizations(:read_release_sources) } + it { expect(described_class).to require_graphql_authorizations(:download_code) } it 'has the expected fields' do expected_fields = %w[ diff --git a/spec/graphql/types/release_type_spec.rb b/spec/graphql/types/release_type_spec.rb index feafe5ed519..11eab7127c1 100644 --- a/spec/graphql/types/release_type_spec.rb +++ b/spec/graphql/types/release_type_spec.rb @@ -44,6 +44,5 @@ describe GitlabSchema.types['Release'] do subject { described_class.fields['commit'] } it { is_expected.to have_graphql_type(Types::CommitType) } - it { is_expected.to require_graphql_authorizations(:reporter_access) } end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 4caf80eaf7d..a646f08ffb4 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -4302,15 +4302,15 @@ describe Ci::Build do end end - context 'when `release_steps` feature is required by build' do + context 'when `multi_build_steps` feature is required by build' do before do expect(build).to receive(:runner_required_feature_names) do - [:release_steps] + [:multi_build_steps] end end context 'when runner provides given feature' do - let(:runner_features) { { release_steps: true } } + let(:runner_features) { { multi_build_steps: true } } it { is_expected.to be_truthy } end diff --git a/spec/policies/releases/source_policy_spec.rb b/spec/policies/releases/source_policy_spec.rb deleted file mode 100644 index 1bc6d5415d3..00000000000 --- a/spec/policies/releases/source_policy_spec.rb +++ /dev/null @@ -1,88 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Releases::SourcePolicy do - using RSpec::Parameterized::TableSyntax - - let(:policy) { described_class.new(user, source) } - - let_it_be(:public_user) { create(:user) } - let_it_be(:guest) { create(:user) } - let_it_be(:reporter) { create(:user) } - - let(:release) { create(:release, project: project) } - let(:source) { release.sources.first } - - shared_examples 'source code access' do - it "allows access a release's source code" do - expect(policy).to be_allowed(:read_release_sources) - end - end - - shared_examples 'no source code access' do - it "does not allow access a release's source code" do - expect(policy).to be_disallowed(:read_release_sources) - end - end - - context 'a private project' do - let_it_be(:project) { create(:project, :private) } - - context 'accessed by a public user' do - let(:user) { public_user } - - it_behaves_like 'no source code access' - end - - context 'accessed by a user with Guest permissions' do - let(:user) { guest } - - before do - project.add_guest(user) - end - - it_behaves_like 'no source code access' - end - - context 'accessed by a user with Reporter permissions' do - let(:user) { reporter } - - before do - project.add_reporter(user) - end - - it_behaves_like 'source code access' - end - end - - context 'a public project' do - let_it_be(:project) { create(:project, :public) } - - context 'accessed by a public user' do - let(:user) { public_user } - - it_behaves_like 'source code access' - end - - context 'accessed by a user with Guest permissions' do - let(:user) { guest } - - before do - project.add_guest(user) - end - - it_behaves_like 'source code access' - end - - context 'accessed by a user with Reporter permissions' do - let(:user) { reporter } - - before do - project.add_reporter(user) - end - - it_behaves_like 'source code access' - end - end -end diff --git a/spec/presenters/release_presenter_spec.rb b/spec/presenters/release_presenter_spec.rb index d1f023b8760..57de99f6a61 100644 --- a/spec/presenters/release_presenter_spec.rb +++ b/spec/presenters/release_presenter_spec.rb @@ -112,4 +112,36 @@ describe ReleasePresenter do it { is_expected.to be_nil } end end + + describe '#assets_count' do + subject { presenter.assets_count } + + it 'returns the number of assets associated to the release' do + is_expected.to be release.assets_count + end + + context 'when a user is not allowed to download release sources' do + let(:presenter) { described_class.new(release, current_user: guest) } + + it 'returns the number of all non-source assets associated to the release' do + is_expected.to be release.assets_count(except: [:sources]) + end + end + end + + describe '#name' do + subject { presenter.name } + + it 'returns the release name' do + is_expected.to eq release.name + end + + context "when a user is not allowed to access any repository information" do + let(:presenter) { described_class.new(release, current_user: guest) } + + it 'returns a replacement name to avoid potentially leaking tag information' do + is_expected.to eq "Release-#{release.id}" + end + end + end end diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb index f8624a97a2b..e377f32ad10 100644 --- a/spec/requests/api/graphql/project/release_spec.rb +++ b/spec/requests/api/graphql/project/release_spec.rb @@ -7,15 +7,10 @@ describe 'Query.project(fullPath).release(tagName)' do include GraphqlHelpers include Presentable - let_it_be(:project) { create(:project, :repository) } - let_it_be(:milestone_1) { create(:milestone, project: project) } - let_it_be(:milestone_2) { create(:milestone, project: project) } - let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2]) } - let_it_be(:release_link_1) { create(:release_link, release: release) } - let_it_be(:release_link_2) { create(:release_link, release: release) } let_it_be(:developer) { create(:user) } - - let(:current_user) { developer } + let_it_be(:guest) { create(:user) } + let_it_be(:reporter) { create(:user) } + let_it_be(:stranger) { create(:user) } def query(rq = release_fields) graphql_query_for(:project, { fullPath: project.full_path }, @@ -27,179 +22,267 @@ describe 'Query.project(fullPath).release(tagName)' do let(:data) { graphql_data.dig(*path) } - before do - project.add_developer(developer) - end + shared_examples 'full access to the release field' do + describe 'scalar fields' do + let(:path) { path_prefix } - describe 'scalar fields' do - let(:path) { path_prefix } - let(:release_fields) do - query_graphql_field(%{ - tagName - tagPath - description - descriptionHtml - name - createdAt - releasedAt - }) - end + let(:release_fields) do + query_graphql_field(%{ + tagName + tagPath + description + descriptionHtml + name + createdAt + releasedAt + }) + end - before do - post_query - end + before do + post_query + end - it 'finds all release data' do - expect(data).to eq({ - 'tagName' => release.tag, - 'tagPath' => project_tag_path(project, release.tag), - 'description' => release.description, - 'descriptionHtml' => release.description_html, - 'name' => release.name, - 'createdAt' => release.created_at.iso8601, - 'releasedAt' => release.released_at.iso8601 - }) + it 'finds all release data' do + expect(data).to eq({ + 'tagName' => release.tag, + 'tagPath' => project_tag_path(project, release.tag), + 'description' => release.description, + 'descriptionHtml' => release.description_html, + 'name' => release.name, + 'createdAt' => release.created_at.iso8601, + 'releasedAt' => release.released_at.iso8601 + }) + end end - end - describe 'milestones' do - let(:path) { path_prefix + %w[milestones nodes] } - let(:release_fields) do - query_graphql_field(:milestones, nil, 'nodes { id title }') + describe 'milestones' do + let(:path) { path_prefix + %w[milestones nodes] } + + let(:release_fields) do + query_graphql_field(:milestones, nil, 'nodes { id title }') + end + + it 'finds all milestones associated to a release' do + post_query + + expected = release.milestones.map do |milestone| + { 'id' => global_id_of(milestone), 'title' => milestone.title } + end + + expect(data).to match_array(expected) + end end - it 'finds all milestones associated to a release' do - post_query + describe 'author' do + let(:path) { path_prefix + %w[author] } - expected = release.milestones.map do |milestone| - { 'id' => global_id_of(milestone), 'title' => milestone.title } + let(:release_fields) do + query_graphql_field(:author, nil, 'id username') end - expect(data).to match_array(expected) - end - end + it 'finds the author of the release' do + post_query - describe 'author' do - let(:path) { path_prefix + %w[author] } - let(:release_fields) do - query_graphql_field(:author, nil, 'id username') + expect(data).to eq({ + 'id' => global_id_of(release.author), + 'username' => release.author.username + }) + end end - it 'finds the author of the release' do - post_query + describe 'commit' do + let(:path) { path_prefix + %w[commit] } - expect(data).to eq({ - 'id' => global_id_of(release.author), - 'username' => release.author.username - }) - end - end + let(:release_fields) do + query_graphql_field(:commit, nil, 'sha') + end + + it 'finds the commit associated with the release' do + post_query - describe 'commit' do - let(:path) { path_prefix + %w[commit] } - let(:release_fields) do - query_graphql_field(:commit, nil, 'sha') + expect(data).to eq({ 'sha' => release.commit.sha }) + end end - it 'finds the commit associated with the release' do - post_query + describe 'assets' do + describe 'count' do + let(:path) { path_prefix + %w[assets] } - expect(data).to eq({ 'sha' => release.commit.sha }) - end - end + let(:release_fields) do + query_graphql_field(:assets, nil, 'count') + end - describe 'assets' do - describe 'assetsCount' do - let(:path) { path_prefix + %w[assets] } - let(:release_fields) do - query_graphql_field(:assets, nil, 'assetsCount') + it 'returns the number of assets associated to the release' do + post_query + + expect(data).to eq({ 'count' => release.sources.size + release.links.size }) + end end - it 'returns the number of assets associated to the release' do - post_query + describe 'links' do + let(:path) { path_prefix + %w[assets links nodes] } + + let(:release_fields) do + query_graphql_field(:assets, nil, + query_graphql_field(:links, nil, 'nodes { id name url external }')) + end - expect(data).to eq({ 'assetsCount' => release.sources.size + release.links.size }) + it 'finds all release links' do + post_query + + expected = release.links.map do |link| + { + 'id' => global_id_of(link), + 'name' => link.name, + 'url' => link.url, + 'external' => link.external? + } + end + + expect(data).to match_array(expected) + end + end + + describe 'sources' do + let(:path) { path_prefix + %w[assets sources nodes] } + + let(:release_fields) do + query_graphql_field(:assets, nil, + query_graphql_field(:sources, nil, 'nodes { format url }')) + end + + it 'finds all release sources' do + post_query + + expected = release.sources.map do |source| + { + 'format' => source.format, + 'url' => source.url + } + end + + expect(data).to match_array(expected) + end end end - describe 'links' do - let(:path) { path_prefix + %w[assets links nodes] } + describe 'evidences' do + let(:path) { path_prefix + %w[evidences] } + let(:release_fields) do - query_graphql_field(:assets, nil, - query_graphql_field(:links, nil, 'nodes { id name url external }')) + query_graphql_field(:evidences, nil, 'nodes { id sha filepath collectedAt }') end - it 'finds all release links' do + it 'finds all evidence fields' do post_query - expected = release.links.map do |link| - { - 'id' => global_id_of(link), - 'name' => link.name, - 'url' => link.url, - 'external' => link.external? - } - end + evidence = release.evidences.first.present + expected = { + 'id' => global_id_of(evidence), + 'sha' => evidence.sha, + 'filepath' => evidence.filepath, + 'collectedAt' => evidence.collected_at.utc.iso8601 + } - expect(data).to match_array(expected) + expect(data["nodes"].first).to eq(expected) end end + end + + shared_examples 'no access to the release field' do + describe 'repository-related fields' do + let(:path) { path_prefix } - describe 'sources' do - let(:path) { path_prefix + %w[assets sources nodes] } let(:release_fields) do - query_graphql_field(:assets, nil, - query_graphql_field(:sources, nil, 'nodes { format url }')) + query_graphql_field('description') end - it 'finds all release sources' do + before do post_query + end - expected = release.sources.map do |source| - { - 'format' => source.format, - 'url' => source.url - } - end + it 'returns nil' do + expect(data).to eq(nil) + end + end + end - expect(data).to match_array(expected) + describe "ensures that the correct data is returned based on the project's visibility and the user's access level" do + context 'when the project is private' do + let_it_be(:project) { create(:project, :repository, :private) } + let_it_be(:milestone_1) { create(:milestone, project: project) } + let_it_be(:milestone_2) { create(:milestone, project: project) } + let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2]) } + let_it_be(:release_link_1) { create(:release_link, release: release) } + let_it_be(:release_link_2) { create(:release_link, release: release) } + + before_all do + project.add_developer(developer) + project.add_guest(guest) + project.add_reporter(reporter) + end + + context 'when the user is not logged in' do + let(:current_user) { stranger } + + it_behaves_like 'no access to the release field' + end + + context 'when the user has Guest permissions' do + let(:current_user) { guest } + + it_behaves_like 'no access to the release field' + end + + context 'when the user has Reporter permissions' do + let(:current_user) { reporter } + + it_behaves_like 'full access to the release field' + end + + context 'when the user has Developer permissions' do + let(:current_user) { developer } + + it_behaves_like 'full access to the release field' end end - describe 'evidences' do - let(:path) { path_prefix + %w[evidences] } - let(:release_fields) do - query_graphql_field(:evidences, nil, 'nodes { id sha filepath collectedAt }') + context 'when the project is public' do + let_it_be(:project) { create(:project, :repository, :public) } + let_it_be(:milestone_1) { create(:milestone, project: project) } + let_it_be(:milestone_2) { create(:milestone, project: project) } + let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2]) } + let_it_be(:release_link_1) { create(:release_link, release: release) } + let_it_be(:release_link_2) { create(:release_link, release: release) } + + before_all do + project.add_developer(developer) + project.add_guest(guest) + project.add_reporter(reporter) end - context 'for a developer' do - it 'finds all evidence fields' do - post_query + context 'when the user is not logged in' do + let(:current_user) { stranger } - evidence = release.evidences.first.present - expected = { - 'id' => global_id_of(evidence), - 'sha' => evidence.sha, - 'filepath' => evidence.filepath, - 'collectedAt' => evidence.collected_at.utc.iso8601 - } + it_behaves_like 'full access to the release field' + end - expect(data["nodes"].first).to eq(expected) - end + context 'when the user has Guest permissions' do + let(:current_user) { guest } + + it_behaves_like 'full access to the release field' end - context 'for a guest' do - let(:current_user) { create :user } + context 'when the user has Reporter permissions' do + let(:current_user) { reporter } - before do - project.add_guest(current_user) - end + it_behaves_like 'full access to the release field' + end - it 'denies access' do - post_query + context 'when the user has Developer permissions' do + let(:current_user) { developer } - expect(data['node']).to be_nil - end + it_behaves_like 'full access to the release field' end end end diff --git a/spec/requests/api/graphql/project/releases_spec.rb b/spec/requests/api/graphql/project/releases_spec.rb new file mode 100644 index 00000000000..4254eb36376 --- /dev/null +++ b/spec/requests/api/graphql/project/releases_spec.rb @@ -0,0 +1,152 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Query.project(fullPath).releases()' do + include GraphqlHelpers + + let_it_be(:guest) { create(:user) } + let_it_be(:reporter) { create(:user) } + let_it_be(:stranger) { create(:user) } + + let(:query) do + graphql_query_for(:project, { fullPath: project.full_path }, + %{ + releases { + nodes { + tagName + tagPath + name + commit { + sha + } + assets { + count + sources { + nodes { + url + } + } + } + evidences { + nodes { + sha + } + } + } + } + }) + end + + let(:post_query) { post_graphql(query, current_user: current_user) } + + let(:data) { graphql_data.dig('project', 'releases', 'nodes', 0) } + + shared_examples 'full access to all repository-related fields' do + describe 'repository-related fields' do + before do + post_query + end + + it 'returns data for fields that are protected in private projects' do + expected_sources = release.sources.map do |s| + { 'url' => s.url } + end + + expected_evidences = release.evidences.map do |e| + { 'sha' => e.sha } + end + + expect(data).to eq({ + 'tagName' => release.tag, + 'tagPath' => project_tag_path(project, release.tag), + 'name' => release.name, + 'commit' => { + 'sha' => release.commit.sha + }, + 'assets' => { + 'count' => release.assets_count, + 'sources' => { + 'nodes' => expected_sources + } + }, + 'evidences' => { + 'nodes' => expected_evidences + } + }) + end + end + end + + shared_examples 'no access to any repository-related fields' do + describe 'repository-related fields' do + before do + post_query + end + + it 'does not return data for fields that expose repository information' do + expect(data).to eq({ + 'tagName' => nil, + 'tagPath' => nil, + 'name' => "Release-#{release.id}", + 'commit' => nil, + 'assets' => { + 'count' => release.assets_count(except: [:sources]), + 'sources' => { + 'nodes' => [] + } + }, + 'evidences' => { + 'nodes' => [] + } + }) + end + end + end + + describe "ensures that the correct data is returned based on the project's visibility and the user's access level" do + context 'when the project is private' do + let_it_be(:project) { create(:project, :repository, :private) } + let_it_be(:release) { create(:release, :with_evidence, project: project) } + + before_all do + project.add_guest(guest) + project.add_reporter(reporter) + end + + context 'when the user has Guest permissions' do + let(:current_user) { guest } + + it_behaves_like 'no access to any repository-related fields' + end + + context 'when the user has Reporter permissions' do + let(:current_user) { reporter } + + it_behaves_like 'full access to all repository-related fields' + end + end + + context 'when the project is public' do + let_it_be(:project) { create(:project, :repository, :public) } + let_it_be(:release) { create(:release, :with_evidence, project: project) } + + before_all do + project.add_guest(guest) + project.add_reporter(reporter) + end + + context 'when the user is not logged in' do + let(:current_user) { stranger } + + it_behaves_like 'full access to all repository-related fields' + end + + context 'when the user has Guest permissions' do + let(:current_user) { guest } + + it_behaves_like 'full access to all repository-related fields' + end + end + end +end diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index 774615757b9..fe1435826a0 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -651,9 +651,9 @@ describe API::Runner, :clean_gitlab_redis_shared_state do context 'when job is for a release' do let!(:job) { create(:ci_build, :release_options, pipeline: pipeline) } - context 'when `release_steps` is passed by the runner' do + context 'when `multi_build_steps` is passed by the runner' do it 'exposes release info' do - request_job info: { features: { release_steps: true } } + request_job info: { features: { multi_build_steps: true } } expect(response).to have_gitlab_http_status(:created) expect(response.headers).not_to have_key('X-GitLab-Last-Update') @@ -677,7 +677,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do end end - context 'when `release_steps` is not passed by the runner' do + context 'when `multi_build_steps` is not passed by the runner' do it 'drops the job' do request_job diff --git a/spec/simplecov_env.rb b/spec/simplecov_env.rb index c5b8a6db605..92f7eb211d6 100644 --- a/spec/simplecov_env.rb +++ b/spec/simplecov_env.rb @@ -46,8 +46,10 @@ module SimpleCovEnv add_filter 'lib/gitlab/sidekiq_middleware/' add_filter 'lib/system_check/' + add_group 'Channels', 'app/channels' add_group 'Controllers', 'app/controllers' add_group 'Finders', 'app/finders' + add_group 'GraphQL', 'app/graphql' add_group 'Helpers', 'app/helpers' add_group 'Libraries', 'lib' add_group 'Mailers', 'app/mailers' |