diff options
author | Robert Speicher <rspeicher@gmail.com> | 2019-03-22 13:07:37 +0000 |
---|---|---|
committer | Robert Speicher <rspeicher@gmail.com> | 2019-03-22 13:07:37 +0000 |
commit | 940cd50965fcbb0ec2fc0c2ab9e455a197aa48f0 (patch) | |
tree | 13cc74443e568d51b4bcb2e5ae61fd9949c1be87 | |
parent | 893abc4a3d9ceaf2da4a1739746d478e02757f6c (diff) | |
download | gitlab-ce-revert-322c14be.tar.gz |
Revert "Merge branch 'ce-6618-extract-ee-specific-files-lines-for-create-spec-finders' into 'master'"revert-322c14be
This reverts merge request !26337
11 files changed, 617 insertions, 662 deletions
diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb index f8fcc2d0e40..d6d95906f5e 100644 --- a/spec/finders/group_projects_finder_spec.rb +++ b/spec/finders/group_projects_finder_spec.rb @@ -1,7 +1,26 @@ require 'spec_helper' describe GroupProjectsFinder do - include_context 'GroupProjectsFinder context' + let(:group) { create(:group) } + let(:subgroup) { create(:group, parent: group) } + let(:current_user) { create(:user) } + let(:options) { {} } + + let(:finder) { described_class.new(group: group, current_user: current_user, options: options) } + + let!(:public_project) { create(:project, :public, group: group, path: '1') } + let!(:private_project) { create(:project, :private, group: group, path: '2') } + let!(:shared_project_1) { create(:project, :public, path: '3') } + let!(:shared_project_2) { create(:project, :private, path: '4') } + let!(:shared_project_3) { create(:project, :internal, path: '5') } + let!(:subgroup_project) { create(:project, :public, path: '6', group: subgroup) } + let!(:subgroup_private_project) { create(:project, :private, path: '7', group: subgroup) } + + before do + shared_project_1.project_group_links.create(group_access: Gitlab::Access::MAINTAINER, group: group) + shared_project_2.project_group_links.create(group_access: Gitlab::Access::MAINTAINER, group: group) + shared_project_3.project_group_links.create(group_access: Gitlab::Access::MAINTAINER, group: group) + end subject { finder.execute } @@ -125,24 +144,6 @@ describe GroupProjectsFinder do end end - describe 'with an admin current user' do - let(:current_user) { create(:admin) } - - context "only shared" do - let(:options) { { only_shared: true } } - it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1]) } - end - - context "only owned" do - let(:options) { { only_owned: true } } - it { is_expected.to eq([private_project, public_project]) } - end - - context "all" do - it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1, private_project, public_project]) } - end - end - describe "no user" do context "only shared" do let(:options) { { only_shared: true } } diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index 00b6cad1a66..f74eb1364a6 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -1,10 +1,45 @@ require 'spec_helper' describe IssuesFinder do - include_context 'IssuesFinder context' + set(:user) { create(:user) } + set(:user2) { create(:user) } + set(:group) { create(:group) } + set(:subgroup) { create(:group, parent: group) } + set(:project1) { create(:project, group: group) } + set(:project2) { create(:project) } + set(:project3) { create(:project, group: subgroup) } + set(:milestone) { create(:milestone, project: project1) } + set(:label) { create(:label, project: project2) } + set(:issue1) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago, updated_at: 1.week.ago) } + set(:issue2) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab', created_at: 1.week.from_now, updated_at: 1.week.from_now) } + set(:issue3) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 2.weeks.from_now, updated_at: 2.weeks.from_now) } + set(:issue4) { create(:issue, project: project3) } + set(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue1) } + set(:award_emoji2) { create(:award_emoji, name: 'thumbsup', user: user2, awardable: issue2) } + set(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) } describe '#execute' do - include_context 'IssuesFinder#execute context' + let!(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') } + let!(:label_link) { create(:label_link, label: label, target: issue2) } + let(:search_user) { user } + let(:params) { {} } + let(:issues) { described_class.new(search_user, params.reverse_merge(scope: scope, state: 'opened')).execute } + + before(:context) do + project1.add_maintainer(user) + project2.add_developer(user) + project2.add_developer(user2) + project3.add_developer(user) + + issue1 + issue2 + issue3 + issue4 + + award_emoji1 + award_emoji2 + award_emoji3 + end context 'scope: all' do let(:scope) { 'all' } @@ -21,21 +56,6 @@ describe IssuesFinder do end end - context 'filtering by assignee usernames' do - set(:user3) { create(:user) } - let(:params) { { assignee_username: [user2.username, user3.username] } } - - before do - project2.add_developer(user3) - - issue3.assignees = [user2, user3] - end - - it 'returns issues assigned to those users' do - expect(issues).to contain_exactly(issue3) - end - end - context 'filtering by no assignee' do let(:params) { { assignee_id: 'None' } } @@ -623,16 +643,6 @@ describe IssuesFinder do expect(subject).to include(public_issue, confidential_issue) end end - - context 'for an admin' do - let(:admin_user) { create(:user, :admin) } - - subject { described_class.new(admin_user, params).with_confidentiality_access_check } - - it 'returns all issues' do - expect(subject).to include(public_issue, confidential_issue) - end - end end context 'when searching within a specific project' do @@ -700,22 +710,6 @@ describe IssuesFinder do subject end end - - context 'for an admin' do - let(:admin_user) { create(:user, :admin) } - - subject { described_class.new(admin_user, params).with_confidentiality_access_check } - - it 'returns all issues' do - expect(subject).to include(public_issue, confidential_issue) - end - - it 'does not filter by confidentiality' do - expect(Issue).not_to receive(:where).with(a_string_matching('confidential'), anything) - - subject - end - end end end diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb index 56136eb84bc..f1178b07eec 100644 --- a/spec/finders/merge_requests_finder_spec.rb +++ b/spec/finders/merge_requests_finder_spec.rb @@ -1,24 +1,72 @@ require 'spec_helper' describe MergeRequestsFinder do + include ProjectForksHelper + + # We need to explicitly permit Gitaly N+1s because of the specs that use + # :request_store. Gitaly N+1 detection is only enabled when :request_store is, + # but we don't care about potential N+1s when we're just creating several + # projects in the setup phase. + def create_project_without_n_plus_1(*args) + Gitlab::GitalyClient.allow_n_plus_1_calls do + create(:project, :public, *args) + end + end + context "multiple projects with merge requests" do - include_context 'MergeRequestsFinder multiple projects with merge requests context' + let(:user) { create :user } + let(:user2) { create :user } + + let(:group) { create(:group) } + let(:subgroup) { create(:group, parent: group) } + let(:project1) { create_project_without_n_plus_1(group: group) } + let(:project2) do + Gitlab::GitalyClient.allow_n_plus_1_calls do + fork_project(project1, user) + end + end + let(:project3) do + Gitlab::GitalyClient.allow_n_plus_1_calls do + p = fork_project(project1, user) + p.update!(archived: true) + p + end + end + let(:project4) { create_project_without_n_plus_1(:repository, group: subgroup) } + let(:project5) { create_project_without_n_plus_1(group: subgroup) } + let(:project6) { create_project_without_n_plus_1(group: subgroup) } + + let!(:merge_request1) { create(:merge_request, author: user, source_project: project2, target_project: project1, target_branch: 'merged-target') } + let!(:merge_request2) { create(:merge_request, :conflict, author: user, source_project: project2, target_project: project1, state: 'closed') } + let!(:merge_request3) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project2, state: 'locked', title: 'thing WIP thing') } + let!(:merge_request4) { create(:merge_request, :simple, author: user, source_project: project3, target_project: project3, title: 'WIP thing') } + let!(:merge_request5) { create(:merge_request, :simple, author: user, source_project: project4, target_project: project4, title: '[WIP]') } + let!(:merge_request6) { create(:merge_request, :simple, author: user, source_project: project5, target_project: project5, title: 'WIP: thing') } + let!(:merge_request7) { create(:merge_request, :simple, author: user, source_project: project6, target_project: project6, title: 'wip thing') } + let!(:merge_request8) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project1, title: '[wip] thing') } + let!(:merge_request9) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project2, title: 'wip: thing') } + + before do + project1.add_maintainer(user) + project2.add_developer(user) + project3.add_developer(user) + project2.add_developer(user2) + project4.add_developer(user) + project5.add_developer(user) + project6.add_developer(user) + end describe '#execute' do it 'filters by scope' do params = { scope: 'authored', state: 'opened' } - merge_requests = described_class.new(user, params).execute - - expect(merge_requests).to contain_exactly(merge_request1, merge_request4, merge_request5) + expect(merge_requests.size).to eq(7) end it 'filters by project' do params = { project_id: project1.id, scope: 'authored', state: 'opened' } - merge_requests = described_class.new(user, params).execute - - expect(merge_requests).to contain_exactly(merge_request1) + expect(merge_requests.size).to eq(2) end it 'filters by commit sha' do @@ -31,15 +79,24 @@ describe MergeRequestsFinder do end context 'filtering by group' do - it 'includes all merge requests when user has access exceluding merge requests from projects the user does not have access to' do - private_project = allow_gitaly_n_plus_1 { create(:project, :private, group: group) } - private_project.add_guest(user) - create(:merge_request, :simple, author: user, source_project: private_project, target_project: private_project) + it 'includes all merge requests when user has access' do + params = { group_id: group.id } + + merge_requests = described_class.new(user, params).execute + + expect(merge_requests.size).to eq(3) + end + + it 'excludes merge requests from projects the user does not have access to' do + private_project = create_project_without_n_plus_1(:private, group: group) + private_mr = create(:merge_request, :simple, author: user, source_project: private_project, target_project: private_project) params = { group_id: group.id } + private_project.add_guest(user) merge_requests = described_class.new(user, params).execute - expect(merge_requests).to contain_exactly(merge_request1, merge_request2) + expect(merge_requests.size).to eq(3) + expect(merge_requests).not_to include(private_mr) end it 'filters by group including subgroups', :nested_groups do @@ -47,16 +104,14 @@ describe MergeRequestsFinder do merge_requests = described_class.new(user, params).execute - expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request5) + expect(merge_requests.size).to eq(6) end end it 'filters by non_archived' do params = { non_archived: true } - merge_requests = described_class.new(user, params).execute - - expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request5) + expect(merge_requests.size).to eq(8) end it 'filters by iid' do @@ -91,45 +146,41 @@ describe MergeRequestsFinder do expect(merge_requests).to contain_exactly(merge_request3) end - describe 'WIP state' do - let!(:wip_merge_request1) { create(:merge_request, :simple, author: user, source_project: project5, target_project: project5, title: 'WIP: thing') } - let!(:wip_merge_request2) { create(:merge_request, :simple, author: user, source_project: project6, target_project: project6, title: 'wip thing') } - let!(:wip_merge_request3) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project1, title: '[wip] thing') } - let!(:wip_merge_request4) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project2, title: 'wip: thing') } - - it 'filters by wip' do - params = { wip: 'yes' } + it 'filters by wip' do + params = { wip: 'yes' } - merge_requests = described_class.new(user, params).execute + merge_requests = described_class.new(user, params).execute - expect(merge_requests).to contain_exactly(merge_request4, merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, wip_merge_request4) - end + expect(merge_requests).to contain_exactly(merge_request4, merge_request5, merge_request6, merge_request7, merge_request8, merge_request9) + end - it 'filters by not wip' do - params = { wip: 'no' } + it 'filters by not wip' do + params = { wip: 'no' } - merge_requests = described_class.new(user, params).execute + merge_requests = described_class.new(user, params).execute - expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3) - end + expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3) + end - it 'returns all items if no valid wip param exists' do - params = { wip: '' } + it 'returns all items if no valid wip param exists' do + params = { wip: '' } - merge_requests = described_class.new(user, params).execute + merge_requests = described_class.new(user, params).execute - expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, wip_merge_request4) - end + expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5, merge_request6, merge_request7, merge_request8, merge_request9) + end - it 'adds wip to scalar params' do - scalar_params = described_class.scalar_params + it 'adds wip to scalar params' do + scalar_params = described_class.scalar_params - expect(scalar_params).to include(:wip, :assignee_id) - end + expect(scalar_params).to include(:wip, :assignee_id) end context 'filtering by group milestone' do + let!(:group) { create(:group, :public) } let(:group_milestone) { create(:milestone, group: group) } + let!(:group_member) { create(:group_member, group: group, user: user) } + let(:params) { { milestone_title: group_milestone.title } } before do project2.update(namespace: group) @@ -137,9 +188,7 @@ describe MergeRequestsFinder do merge_request3.update(milestone: group_milestone) end - it 'returns merge requests assigned to that group milestone' do - params = { milestone_title: group_milestone.title } - + it 'returns issues assigned to that group milestone' do merge_requests = described_class.new(user, params).execute expect(merge_requests).to contain_exactly(merge_request2, merge_request3) @@ -236,7 +285,7 @@ describe MergeRequestsFinder do it 'returns the number of rows for the default state' do finder = described_class.new(user) - expect(finder.row_count).to eq(3) + expect(finder.row_count).to eq(7) end it 'returns the number of rows for a given state' do diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb index 93287f3e9b8..134fb5f2c04 100644 --- a/spec/finders/snippets_finder_spec.rb +++ b/spec/finders/snippets_finder_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe SnippetsFinder do include Gitlab::Allowable + using RSpec::Parameterized::TableSyntax describe '#initialize' do it 'raises ArgumentError when a project and author are given' do @@ -13,142 +14,174 @@ describe SnippetsFinder do end end - describe '#execute' do - set(:user) { create(:user) } - set(:private_personal_snippet) { create(:personal_snippet, :private, author: user) } - set(:internal_personal_snippet) { create(:personal_snippet, :internal, author: user) } - set(:public_personal_snippet) { create(:personal_snippet, :public, author: user) } + context 'filter by scope' do + let(:user) { create :user } + let!(:snippet1) { create(:personal_snippet, :private, author: user) } + let!(:snippet2) { create(:personal_snippet, :internal, author: user) } + let!(:snippet3) { create(:personal_snippet, :public, author: user) } - context 'filter by scope' do - it "returns all snippets for 'all' scope" do - snippets = described_class.new(user, scope: :all).execute + it "returns all snippets for 'all' scope" do + snippets = described_class.new(user, scope: :all).execute - expect(snippets).to contain_exactly(private_personal_snippet, internal_personal_snippet, public_personal_snippet) - end + expect(snippets).to include(snippet1, snippet2, snippet3) + end - it "returns all snippets for 'are_private' scope" do - snippets = described_class.new(user, scope: :are_private).execute + it "returns all snippets for 'are_private' scope" do + snippets = described_class.new(user, scope: :are_private).execute - expect(snippets).to contain_exactly(private_personal_snippet) - end + expect(snippets).to include(snippet1) + expect(snippets).not_to include(snippet2, snippet3) + end - it "returns all snippets for 'are_internal' scope" do - snippets = described_class.new(user, scope: :are_internal).execute + it "returns all snippets for 'are_internal' scope" do + snippets = described_class.new(user, scope: :are_internal).execute - expect(snippets).to contain_exactly(internal_personal_snippet) - end + expect(snippets).to include(snippet2) + expect(snippets).not_to include(snippet1, snippet3) + end - it "returns all snippets for 'are_private' scope" do - snippets = described_class.new(user, scope: :are_public).execute + it "returns all snippets for 'are_private' scope" do + snippets = described_class.new(user, scope: :are_public).execute - expect(snippets).to contain_exactly(public_personal_snippet) - end + expect(snippets).to include(snippet3) + expect(snippets).not_to include(snippet1, snippet2) end + end - context 'filter by author' do - it 'returns all public and internal snippets' do - snippets = described_class.new(create(:user), author: user).execute + context 'filter by author' do + let(:user) { create :user } + let(:user1) { create :user } + let!(:snippet1) { create(:personal_snippet, :private, author: user) } + let!(:snippet2) { create(:personal_snippet, :internal, author: user) } + let!(:snippet3) { create(:personal_snippet, :public, author: user) } - expect(snippets).to contain_exactly(internal_personal_snippet, public_personal_snippet) - end + it "returns all public and internal snippets" do + snippets = described_class.new(user1, author: user).execute - it 'returns internal snippets' do - snippets = described_class.new(user, author: user, scope: :are_internal).execute + expect(snippets).to include(snippet2, snippet3) + expect(snippets).not_to include(snippet1) + end - expect(snippets).to contain_exactly(internal_personal_snippet) - end + it "returns internal snippets" do + snippets = described_class.new(user, author: user, scope: :are_internal).execute - it 'returns private snippets' do - snippets = described_class.new(user, author: user, scope: :are_private).execute + expect(snippets).to include(snippet2) + expect(snippets).not_to include(snippet1, snippet3) + end - expect(snippets).to contain_exactly(private_personal_snippet) - end + it "returns private snippets" do + snippets = described_class.new(user, author: user, scope: :are_private).execute - it 'returns public snippets' do - snippets = described_class.new(user, author: user, scope: :are_public).execute + expect(snippets).to include(snippet1) + expect(snippets).not_to include(snippet2, snippet3) + end - expect(snippets).to contain_exactly(public_personal_snippet) - end + it "returns public snippets" do + snippets = described_class.new(user, author: user, scope: :are_public).execute - it 'returns all snippets' do - snippets = described_class.new(user, author: user).execute + expect(snippets).to include(snippet3) + expect(snippets).not_to include(snippet1, snippet2) + end - expect(snippets).to contain_exactly(private_personal_snippet, internal_personal_snippet, public_personal_snippet) - end + it "returns all snippets" do + snippets = described_class.new(user, author: user).execute - it 'returns only public snippets if unauthenticated user' do - snippets = described_class.new(nil, author: user).execute + expect(snippets).to include(snippet1, snippet2, snippet3) + end - expect(snippets).to contain_exactly(public_personal_snippet) - end + it "returns only public snippets if unauthenticated user" do + snippets = described_class.new(nil, author: user).execute - it 'returns all snippets for an admin' do - admin = create(:user, :admin) - snippets = described_class.new(admin, author: user).execute + expect(snippets).to include(snippet3) + expect(snippets).not_to include(snippet2, snippet1) + end - expect(snippets).to contain_exactly(private_personal_snippet, internal_personal_snippet, public_personal_snippet) - end + it 'returns all snippets for an admin' do + admin = create(:user, :admin) + snippets = described_class.new(admin, author: user).execute + + expect(snippets).to include(snippet1, snippet2, snippet3) end + end - context 'project snippets' do - let(:group) { create(:group, :public) } - let(:project) { create(:project, :public, group: group) } - let!(:private_project_snippet) { create(:project_snippet, :private, project: project) } - let!(:internal_project_snippet) { create(:project_snippet, :internal, project: project) } - let!(:public_project_snippet) { create(:project_snippet, :public, project: project) } + context 'filter by project' do + let(:user) { create :user } + let(:group) { create :group, :public } + let(:project1) { create(:project, :public, group: group) } - it 'returns public personal and project snippets for unauthorized user' do - snippets = described_class.new(nil, project: project).execute + before do + @snippet1 = create(:project_snippet, :private, project: project1) + @snippet2 = create(:project_snippet, :internal, project: project1) + @snippet3 = create(:project_snippet, :public, project: project1) + end - expect(snippets).to contain_exactly(public_project_snippet) - end + it "returns public snippets for unauthorized user" do + snippets = described_class.new(nil, project: project1).execute - it 'returns public and internal snippets for non project members' do - snippets = described_class.new(user, project: project).execute + expect(snippets).to include(@snippet3) + expect(snippets).not_to include(@snippet1, @snippet2) + end - expect(snippets).to contain_exactly(internal_project_snippet, public_project_snippet) - end + it "returns public and internal snippets for non project members" do + snippets = described_class.new(user, project: project1).execute - it 'returns public snippets for non project members' do - snippets = described_class.new(user, project: project, scope: :are_public).execute + expect(snippets).to include(@snippet2, @snippet3) + expect(snippets).not_to include(@snippet1) + end - expect(snippets).to contain_exactly(public_project_snippet) - end + it "returns public snippets for non project members" do + snippets = described_class.new(user, project: project1, scope: :are_public).execute - it 'returns internal snippets for non project members' do - snippets = described_class.new(user, project: project, scope: :are_internal).execute + expect(snippets).to include(@snippet3) + expect(snippets).not_to include(@snippet1, @snippet2) + end - expect(snippets).to contain_exactly(internal_project_snippet) - end + it "returns internal snippets for non project members" do + snippets = described_class.new(user, project: project1, scope: :are_internal).execute - it 'does not return private snippets for non project members' do - snippets = described_class.new(user, project: project, scope: :are_private).execute + expect(snippets).to include(@snippet2) + expect(snippets).not_to include(@snippet1, @snippet3) + end - expect(snippets).to be_empty - end + it "does not return private snippets for non project members" do + snippets = described_class.new(user, project: project1, scope: :are_private).execute - it 'returns all snippets for project members' do - project.add_developer(user) + expect(snippets).not_to include(@snippet1, @snippet2, @snippet3) + end - snippets = described_class.new(user, project: project).execute + it "returns all snippets for project members" do + project1.add_developer(user) - expect(snippets).to contain_exactly(private_project_snippet, internal_project_snippet, public_project_snippet) - end + snippets = described_class.new(user, project: project1).execute - it 'returns private snippets for project members' do - project.add_developer(user) + expect(snippets).to include(@snippet1, @snippet2, @snippet3) + end - snippets = described_class.new(user, project: project, scope: :are_private).execute + it "returns private snippets for project members" do + project1.add_developer(user) - expect(snippets).to contain_exactly(private_project_snippet) - end + snippets = described_class.new(user, project: project1, scope: :are_private).execute - it 'returns all snippets for an admin' do - admin = create(:user, :admin) - snippets = described_class.new(admin, project: project).execute + expect(snippets).to include(@snippet1) + end - expect(snippets).to contain_exactly(private_project_snippet, internal_project_snippet, public_project_snippet) - end + it 'returns all snippets for an admin' do + admin = create(:user, :admin) + snippets = described_class.new(admin, project: project1).execute + + expect(snippets).to include(@snippet1, @snippet2, @snippet3) + end + end + + describe '#execute' do + let(:project) { create(:project, :public) } + let!(:project_snippet) { create(:project_snippet, :public, project: project) } + let!(:personal_snippet) { create(:personal_snippet, :public) } + let(:user) { create(:user) } + subject(:finder) { described_class.new(user) } + + it 'returns project- and personal snippets' do + expect(finder.execute).to contain_exactly(project_snippet, personal_snippet) end context 'when the user cannot read cross project' do @@ -158,7 +191,7 @@ describe SnippetsFinder do end it 'returns only personal snippets when the user cannot read cross project' do - expect(described_class.new(user).execute).to contain_exactly(private_personal_snippet, internal_personal_snippet, public_personal_snippet) + expect(finder.execute).to contain_exactly(personal_snippet) end end end diff --git a/spec/finders/users_finder_spec.rb b/spec/finders/users_finder_spec.rb index d71d3c99272..fecf97dc641 100644 --- a/spec/finders/users_finder_spec.rb +++ b/spec/finders/users_finder_spec.rb @@ -2,7 +2,10 @@ require 'spec_helper' describe UsersFinder do describe '#execute' do - include_context 'UsersFinder#execute filter by project context' + let!(:user1) { create(:user, username: 'johndoe') } + let!(:user2) { create(:user, :blocked, username: 'notsorandom') } + let!(:external_user) { create(:user, :external) } + let!(:omniauth_user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') } context 'with a normal user' do let(:user) { create(:user) } @@ -10,43 +13,43 @@ describe UsersFinder do it 'returns all users' do users = described_class.new(user).execute - expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user) + expect(users).to contain_exactly(user, user1, user2, omniauth_user) end it 'filters by username' do users = described_class.new(user, username: 'johndoe').execute - expect(users).to contain_exactly(normal_user) + expect(users).to contain_exactly(user1) end it 'filters by username (case insensitive)' do users = described_class.new(user, username: 'joHNdoE').execute - expect(users).to contain_exactly(normal_user) + expect(users).to contain_exactly(user1) end it 'filters by search' do users = described_class.new(user, search: 'orando').execute - expect(users).to contain_exactly(blocked_user) + expect(users).to contain_exactly(user2) end it 'filters by blocked users' do users = described_class.new(user, blocked: true).execute - expect(users).to contain_exactly(blocked_user) + expect(users).to contain_exactly(user2) end it 'filters by active users' do users = described_class.new(user, active: true).execute - expect(users).to contain_exactly(user, normal_user, omniauth_user) + expect(users).to contain_exactly(user, user1, omniauth_user) end it 'returns no external users' do users = described_class.new(user, external: true).execute - expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user) + expect(users).to contain_exactly(user, user1, user2, omniauth_user) end it 'filters by created_at' do @@ -66,7 +69,7 @@ describe UsersFinder do custom_attributes: { foo: 'bar' } ).execute - expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user) + expect(users).to contain_exactly(user, user1, user2, omniauth_user) end end @@ -82,20 +85,20 @@ describe UsersFinder do it 'returns all users' do users = described_class.new(admin).execute - expect(users).to contain_exactly(admin, normal_user, blocked_user, external_user, omniauth_user) + expect(users).to contain_exactly(admin, user1, user2, external_user, omniauth_user) end it 'filters by custom attributes' do - create :user_custom_attribute, user: normal_user, key: 'foo', value: 'foo' - create :user_custom_attribute, user: normal_user, key: 'bar', value: 'bar' - create :user_custom_attribute, user: blocked_user, key: 'foo', value: 'foo' + create :user_custom_attribute, user: user1, key: 'foo', value: 'foo' + create :user_custom_attribute, user: user1, key: 'bar', value: 'bar' + create :user_custom_attribute, user: user2, key: 'foo', value: 'foo' users = described_class.new( admin, custom_attributes: { foo: 'foo', bar: 'bar' } ).execute - expect(users).to contain_exactly(normal_user) + expect(users).to contain_exactly(user1) end end end diff --git a/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb deleted file mode 100644 index a0d994c4d8d..00000000000 --- a/spec/support/shared_contexts/finders/group_projects_finder_shared_contexts.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'spec_helper' - -RSpec.shared_context 'GroupProjectsFinder context' do - let(:group) { create(:group) } - let(:subgroup) { create(:group, parent: group) } - let(:current_user) { create(:user) } - let(:options) { {} } - - let(:finder) { described_class.new(group: group, current_user: current_user, options: options) } - - let!(:public_project) { create(:project, :public, group: group, path: '1') } - let!(:private_project) { create(:project, :private, group: group, path: '2') } - let!(:shared_project_1) { create(:project, :public, path: '3') } - let!(:shared_project_2) { create(:project, :private, path: '4') } - let!(:shared_project_3) { create(:project, :internal, path: '5') } - let!(:subgroup_project) { create(:project, :public, path: '6', group: subgroup) } - let!(:subgroup_private_project) { create(:project, :private, path: '7', group: subgroup) } - - before do - shared_project_1.project_group_links.create(group_access: Gitlab::Access::MAINTAINER, group: group) - shared_project_2.project_group_links.create(group_access: Gitlab::Access::MAINTAINER, group: group) - shared_project_3.project_group_links.create(group_access: Gitlab::Access::MAINTAINER, group: group) - end -end diff --git a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb deleted file mode 100644 index b8a9554f55f..00000000000 --- a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb +++ /dev/null @@ -1,44 +0,0 @@ -require 'spec_helper' - -RSpec.shared_context 'IssuesFinder context' do - set(:user) { create(:user) } - set(:user2) { create(:user) } - set(:group) { create(:group) } - set(:subgroup) { create(:group, parent: group) } - set(:project1) { create(:project, group: group) } - set(:project2) { create(:project) } - set(:project3) { create(:project, group: subgroup) } - set(:milestone) { create(:milestone, project: project1) } - set(:label) { create(:label, project: project2) } - set(:issue1) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago, updated_at: 1.week.ago) } - set(:issue2) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab', created_at: 1.week.from_now, updated_at: 1.week.from_now) } - set(:issue3) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 2.weeks.from_now, updated_at: 2.weeks.from_now) } - set(:issue4) { create(:issue, project: project3) } - set(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue1) } - set(:award_emoji2) { create(:award_emoji, name: 'thumbsup', user: user2, awardable: issue2) } - set(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) } -end - -RSpec.shared_context 'IssuesFinder#execute context' do - let!(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') } - let!(:label_link) { create(:label_link, label: label, target: issue2) } - let(:search_user) { user } - let(:params) { {} } - let(:issues) { described_class.new(search_user, params.reverse_merge(scope: scope, state: 'opened')).execute } - - before(:context) do - project1.add_maintainer(user) - project2.add_developer(user) - project2.add_developer(user2) - project3.add_developer(user) - - issue1 - issue2 - issue3 - issue4 - - award_emoji1 - award_emoji2 - award_emoji3 - end -end diff --git a/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb deleted file mode 100644 index 4df80b4168a..00000000000 --- a/spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb +++ /dev/null @@ -1,65 +0,0 @@ -require 'spec_helper' - -RSpec.shared_context 'MergeRequestsFinder multiple projects with merge requests context' do - include ProjectForksHelper - - # We need to explicitly permit Gitaly N+1s because of the specs that use - # :request_store. Gitaly N+1 detection is only enabled when :request_store is, - # but we don't care about potential N+1s when we're just creating several - # projects in the setup phase. - def allow_gitaly_n_plus_1 - Gitlab::GitalyClient.allow_n_plus_1_calls do - yield - end - end - - set(:user) { create(:user) } - set(:user2) { create(:user) } - - set(:group) { create(:group) } - set(:subgroup) { create(:group, parent: group) } - set(:project1) do - allow_gitaly_n_plus_1 { create(:project, :public, group: group) } - end - # We cannot use `set` here otherwise we get: - # Failure/Error: allow(RepositoryForkWorker).to receive(:perform_async).and_return(true) - # The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported. - let(:project2) do - allow_gitaly_n_plus_1 do - fork_project(project1, user) - end - end - let(:project3) do - allow_gitaly_n_plus_1 do - fork_project(project1, user).tap do |project| - project.update!(archived: true) - end - end - end - set(:project4) do - allow_gitaly_n_plus_1 { create(:project, :repository, group: subgroup) } - end - set(:project5) do - allow_gitaly_n_plus_1 { create(:project, group: subgroup) } - end - set(:project6) do - allow_gitaly_n_plus_1 { create(:project, group: subgroup) } - end - - let!(:merge_request1) { create(:merge_request, author: user, source_project: project2, target_project: project1, target_branch: 'merged-target') } - let!(:merge_request2) { create(:merge_request, :conflict, author: user, source_project: project2, target_project: project1, state: 'closed') } - let!(:merge_request3) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project2, state: 'locked', title: 'thing WIP thing') } - let!(:merge_request4) { create(:merge_request, :simple, author: user, source_project: project3, target_project: project3, title: 'WIP thing') } - let!(:merge_request5) { create(:merge_request, :simple, author: user, source_project: project4, target_project: project4, title: '[WIP]') } - - before do - project1.add_maintainer(user) - project2.add_developer(user) - project3.add_developer(user) - project4.add_developer(user) - project5.add_developer(user) - project6.add_developer(user) - - project2.add_developer(user2) - end -end diff --git a/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb deleted file mode 100644 index 9e1f89ee0ed..00000000000 --- a/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'spec_helper' - -RSpec.shared_context 'UsersFinder#execute filter by project context' do - set(:normal_user) { create(:user, username: 'johndoe') } - set(:blocked_user) { create(:user, :blocked, username: 'notsorandom') } - set(:external_user) { create(:user, :external) } - set(:omniauth_user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') } -end diff --git a/spec/support/shared_examples/snippet_visibility.rb b/spec/support/shared_examples/snippet_visibility.rb new file mode 100644 index 00000000000..3a7c69b7877 --- /dev/null +++ b/spec/support/shared_examples/snippet_visibility.rb @@ -0,0 +1,322 @@ +RSpec.shared_examples 'snippet visibility' do + let!(:author) { create(:user) } + let!(:member) { create(:user) } + let!(:external) { create(:user, :external) } + + let!(:snippet_type_visibilities) do + { + public: Snippet::PUBLIC, + internal: Snippet::INTERNAL, + private: Snippet::PRIVATE + } + end + + context "For project snippets" do + let!(:users) do + { + unauthenticated: nil, + external: external, + non_member: create(:user), + member: member, + author: author + } + end + + let!(:project_type_visibilities) do + { + public: Gitlab::VisibilityLevel::PUBLIC, + internal: Gitlab::VisibilityLevel::INTERNAL, + private: Gitlab::VisibilityLevel::PRIVATE + } + end + + let(:project_feature_visibilities) do + { + enabled: ProjectFeature::ENABLED, + private: ProjectFeature::PRIVATE, + disabled: ProjectFeature::DISABLED + } + end + + where(:project_type, :feature_visibility, :user_type, :snippet_type, :outcome) do + [ + # Public projects + [:public, :enabled, :unauthenticated, :public, true], + [:public, :enabled, :unauthenticated, :internal, false], + [:public, :enabled, :unauthenticated, :private, false], + + [:public, :enabled, :external, :public, true], + [:public, :enabled, :external, :internal, false], + [:public, :enabled, :external, :private, false], + + [:public, :enabled, :non_member, :public, true], + [:public, :enabled, :non_member, :internal, true], + [:public, :enabled, :non_member, :private, false], + + [:public, :enabled, :member, :public, true], + [:public, :enabled, :member, :internal, true], + [:public, :enabled, :member, :private, true], + + [:public, :enabled, :author, :public, true], + [:public, :enabled, :author, :internal, true], + [:public, :enabled, :author, :private, true], + + [:public, :private, :unauthenticated, :public, false], + [:public, :private, :unauthenticated, :internal, false], + [:public, :private, :unauthenticated, :private, false], + + [:public, :private, :external, :public, false], + [:public, :private, :external, :internal, false], + [:public, :private, :external, :private, false], + + [:public, :private, :non_member, :public, false], + [:public, :private, :non_member, :internal, false], + [:public, :private, :non_member, :private, false], + + [:public, :private, :member, :public, true], + [:public, :private, :member, :internal, true], + [:public, :private, :member, :private, true], + + [:public, :private, :author, :public, true], + [:public, :private, :author, :internal, true], + [:public, :private, :author, :private, true], + + [:public, :disabled, :unauthenticated, :public, false], + [:public, :disabled, :unauthenticated, :internal, false], + [:public, :disabled, :unauthenticated, :private, false], + + [:public, :disabled, :external, :public, false], + [:public, :disabled, :external, :internal, false], + [:public, :disabled, :external, :private, false], + + [:public, :disabled, :non_member, :public, false], + [:public, :disabled, :non_member, :internal, false], + [:public, :disabled, :non_member, :private, false], + + [:public, :disabled, :member, :public, false], + [:public, :disabled, :member, :internal, false], + [:public, :disabled, :member, :private, false], + + [:public, :disabled, :author, :public, false], + [:public, :disabled, :author, :internal, false], + [:public, :disabled, :author, :private, false], + + # Internal projects + [:internal, :enabled, :unauthenticated, :public, false], + [:internal, :enabled, :unauthenticated, :internal, false], + [:internal, :enabled, :unauthenticated, :private, false], + + [:internal, :enabled, :external, :public, false], + [:internal, :enabled, :external, :internal, false], + [:internal, :enabled, :external, :private, false], + + [:internal, :enabled, :non_member, :public, true], + [:internal, :enabled, :non_member, :internal, true], + [:internal, :enabled, :non_member, :private, false], + + [:internal, :enabled, :member, :public, true], + [:internal, :enabled, :member, :internal, true], + [:internal, :enabled, :member, :private, true], + + [:internal, :enabled, :author, :public, true], + [:internal, :enabled, :author, :internal, true], + [:internal, :enabled, :author, :private, true], + + [:internal, :private, :unauthenticated, :public, false], + [:internal, :private, :unauthenticated, :internal, false], + [:internal, :private, :unauthenticated, :private, false], + + [:internal, :private, :external, :public, false], + [:internal, :private, :external, :internal, false], + [:internal, :private, :external, :private, false], + + [:internal, :private, :non_member, :public, false], + [:internal, :private, :non_member, :internal, false], + [:internal, :private, :non_member, :private, false], + + [:internal, :private, :member, :public, true], + [:internal, :private, :member, :internal, true], + [:internal, :private, :member, :private, true], + + [:internal, :private, :author, :public, true], + [:internal, :private, :author, :internal, true], + [:internal, :private, :author, :private, true], + + [:internal, :disabled, :unauthenticated, :public, false], + [:internal, :disabled, :unauthenticated, :internal, false], + [:internal, :disabled, :unauthenticated, :private, false], + + [:internal, :disabled, :external, :public, false], + [:internal, :disabled, :external, :internal, false], + [:internal, :disabled, :external, :private, false], + + [:internal, :disabled, :non_member, :public, false], + [:internal, :disabled, :non_member, :internal, false], + [:internal, :disabled, :non_member, :private, false], + + [:internal, :disabled, :member, :public, false], + [:internal, :disabled, :member, :internal, false], + [:internal, :disabled, :member, :private, false], + + [:internal, :disabled, :author, :public, false], + [:internal, :disabled, :author, :internal, false], + [:internal, :disabled, :author, :private, false], + + # Private projects + [:private, :enabled, :unauthenticated, :public, false], + [:private, :enabled, :unauthenticated, :internal, false], + [:private, :enabled, :unauthenticated, :private, false], + + [:private, :enabled, :external, :public, true], + [:private, :enabled, :external, :internal, true], + [:private, :enabled, :external, :private, true], + + [:private, :enabled, :non_member, :public, false], + [:private, :enabled, :non_member, :internal, false], + [:private, :enabled, :non_member, :private, false], + + [:private, :enabled, :member, :public, true], + [:private, :enabled, :member, :internal, true], + [:private, :enabled, :member, :private, true], + + [:private, :enabled, :author, :public, true], + [:private, :enabled, :author, :internal, true], + [:private, :enabled, :author, :private, true], + + [:private, :private, :unauthenticated, :public, false], + [:private, :private, :unauthenticated, :internal, false], + [:private, :private, :unauthenticated, :private, false], + + [:private, :private, :external, :public, true], + [:private, :private, :external, :internal, true], + [:private, :private, :external, :private, true], + + [:private, :private, :non_member, :public, false], + [:private, :private, :non_member, :internal, false], + [:private, :private, :non_member, :private, false], + + [:private, :private, :member, :public, true], + [:private, :private, :member, :internal, true], + [:private, :private, :member, :private, true], + + [:private, :private, :author, :public, true], + [:private, :private, :author, :internal, true], + [:private, :private, :author, :private, true], + + [:private, :disabled, :unauthenticated, :public, false], + [:private, :disabled, :unauthenticated, :internal, false], + [:private, :disabled, :unauthenticated, :private, false], + + [:private, :disabled, :external, :public, false], + [:private, :disabled, :external, :internal, false], + [:private, :disabled, :external, :private, false], + + [:private, :disabled, :non_member, :public, false], + [:private, :disabled, :non_member, :internal, false], + [:private, :disabled, :non_member, :private, false], + + [:private, :disabled, :member, :public, false], + [:private, :disabled, :member, :internal, false], + [:private, :disabled, :member, :private, false], + + [:private, :disabled, :author, :public, false], + [:private, :disabled, :author, :internal, false], + [:private, :disabled, :author, :private, false] + ] + end + + with_them do + let!(:project) { create(:project, visibility_level: project_type_visibilities[project_type]) } + let!(:project_feature) { project.project_feature.update_column(:snippets_access_level, project_feature_visibilities[feature_visibility]) } + let!(:user) { users[user_type] } + let!(:snippet) { create(:project_snippet, visibility_level: snippet_type_visibilities[snippet_type], project: project, author: author) } + let!(:members) do + project.add_developer(author) + project.add_developer(member) + project.add_developer(external) if project.private? + end + + context "For #{params[:project_type]} project and #{params[:user_type]} users" do + it 'should agree with the read_project_snippet policy' do + expect(can?(user, :read_project_snippet, snippet)).to eq(outcome) + end + + it 'should return proper outcome' do + results = described_class.new(user, project: project).execute + expect(results.include?(snippet)).to eq(outcome) + end + end + + context "Without a given project and #{params[:user_type]} users" do + it 'should return proper outcome' do + results = described_class.new(user).execute + expect(results.include?(snippet)).to eq(outcome) + end + + it 'returns no snippets when the user cannot read cross project' do + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } + + snippets = described_class.new(user).execute + + expect(snippets).to be_empty + end + end + end + end + + context 'For personal snippets' do + let!(:users) do + { + unauthenticated: nil, + external: external, + non_member: create(:user), + author: author + } + end + + where(:snippet_visibility, :user_type, :outcome) do + [ + [:public, :unauthenticated, true], + [:public, :external, true], + [:public, :non_member, true], + [:public, :author, true], + + [:internal, :unauthenticated, false], + [:internal, :external, false], + [:internal, :non_member, true], + [:internal, :author, true], + + [:private, :unauthenticated, false], + [:private, :external, false], + [:private, :non_member, false], + [:private, :author, true] + ] + end + + with_them do + let!(:user) { users[user_type] } + let!(:snippet) { create(:personal_snippet, visibility_level: snippet_type_visibilities[snippet_visibility], author: author) } + + context "For personal and #{params[:snippet_visibility]} snippets with #{params[:user_type]} user" do + it 'should agree with read_personal_snippet policy' do + expect(can?(user, :read_personal_snippet, snippet)).to eq(outcome) + end + + it 'should return proper outcome' do + results = described_class.new(user).execute + expect(results.include?(snippet)).to eq(outcome) + end + + it 'should return personal snippets when the user cannot read cross project' do + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } + + results = described_class.new(user).execute + + expect(results.include?(snippet)).to eq(outcome) + end + end + end + end +end diff --git a/spec/support/shared_examples/snippet_visibility_shared_examples.rb b/spec/support/shared_examples/snippet_visibility_shared_examples.rb deleted file mode 100644 index 4f662db2120..00000000000 --- a/spec/support/shared_examples/snippet_visibility_shared_examples.rb +++ /dev/null @@ -1,306 +0,0 @@ -RSpec.shared_examples 'snippet visibility' do - using RSpec::Parameterized::TableSyntax - - # Make sure no snippets exist prior to running the test matrix - before(:context) do - DatabaseCleaner.clean_with(:truncation) - end - - set(:author) { create(:user) } - set(:member) { create(:user) } - set(:external) { create(:user, :external) } - - context "For project snippets" do - let!(:users) do - { - unauthenticated: nil, - external: external, - non_member: create(:user), - member: member, - author: author - } - end - - where(:project_type, :feature_visibility, :user_type, :snippet_type, :outcome) do - [ - # Public projects - [:public, ProjectFeature::ENABLED, :unauthenticated, Snippet::PUBLIC, true], - [:public, ProjectFeature::ENABLED, :unauthenticated, Snippet::INTERNAL, false], - [:public, ProjectFeature::ENABLED, :unauthenticated, Snippet::PRIVATE, false], - - [:public, ProjectFeature::ENABLED, :external, Snippet::PUBLIC, true], - [:public, ProjectFeature::ENABLED, :external, Snippet::INTERNAL, false], - [:public, ProjectFeature::ENABLED, :external, Snippet::PRIVATE, false], - - [:public, ProjectFeature::ENABLED, :non_member, Snippet::PUBLIC, true], - [:public, ProjectFeature::ENABLED, :non_member, Snippet::INTERNAL, true], - [:public, ProjectFeature::ENABLED, :non_member, Snippet::PRIVATE, false], - - [:public, ProjectFeature::ENABLED, :member, Snippet::PUBLIC, true], - [:public, ProjectFeature::ENABLED, :member, Snippet::INTERNAL, true], - [:public, ProjectFeature::ENABLED, :member, Snippet::PRIVATE, true], - - [:public, ProjectFeature::ENABLED, :author, Snippet::PUBLIC, true], - [:public, ProjectFeature::ENABLED, :author, Snippet::INTERNAL, true], - [:public, ProjectFeature::ENABLED, :author, Snippet::PRIVATE, true], - - [:public, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PUBLIC, false], - [:public, ProjectFeature::PRIVATE, :unauthenticated, Snippet::INTERNAL, false], - [:public, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PRIVATE, false], - - [:public, ProjectFeature::PRIVATE, :external, Snippet::PUBLIC, false], - [:public, ProjectFeature::PRIVATE, :external, Snippet::INTERNAL, false], - [:public, ProjectFeature::PRIVATE, :external, Snippet::PRIVATE, false], - - [:public, ProjectFeature::PRIVATE, :non_member, Snippet::PUBLIC, false], - [:public, ProjectFeature::PRIVATE, :non_member, Snippet::INTERNAL, false], - [:public, ProjectFeature::PRIVATE, :non_member, Snippet::PRIVATE, false], - - [:public, ProjectFeature::PRIVATE, :member, Snippet::PUBLIC, true], - [:public, ProjectFeature::PRIVATE, :member, Snippet::INTERNAL, true], - [:public, ProjectFeature::PRIVATE, :member, Snippet::PRIVATE, true], - - [:public, ProjectFeature::PRIVATE, :author, Snippet::PUBLIC, true], - [:public, ProjectFeature::PRIVATE, :author, Snippet::INTERNAL, true], - [:public, ProjectFeature::PRIVATE, :author, Snippet::PRIVATE, true], - - [:public, ProjectFeature::DISABLED, :unauthenticated, Snippet::PUBLIC, false], - [:public, ProjectFeature::DISABLED, :unauthenticated, Snippet::INTERNAL, false], - [:public, ProjectFeature::DISABLED, :unauthenticated, Snippet::PRIVATE, false], - - [:public, ProjectFeature::DISABLED, :external, Snippet::PUBLIC, false], - [:public, ProjectFeature::DISABLED, :external, Snippet::INTERNAL, false], - [:public, ProjectFeature::DISABLED, :external, Snippet::PRIVATE, false], - - [:public, ProjectFeature::DISABLED, :non_member, Snippet::PUBLIC, false], - [:public, ProjectFeature::DISABLED, :non_member, Snippet::INTERNAL, false], - [:public, ProjectFeature::DISABLED, :non_member, Snippet::PRIVATE, false], - - [:public, ProjectFeature::DISABLED, :member, Snippet::PUBLIC, false], - [:public, ProjectFeature::DISABLED, :member, Snippet::INTERNAL, false], - [:public, ProjectFeature::DISABLED, :member, Snippet::PRIVATE, false], - - [:public, ProjectFeature::DISABLED, :author, Snippet::PUBLIC, false], - [:public, ProjectFeature::DISABLED, :author, Snippet::INTERNAL, false], - [:public, ProjectFeature::DISABLED, :author, Snippet::PRIVATE, false], - - # Internal projects - [:internal, ProjectFeature::ENABLED, :unauthenticated, Snippet::PUBLIC, false], - [:internal, ProjectFeature::ENABLED, :unauthenticated, Snippet::INTERNAL, false], - [:internal, ProjectFeature::ENABLED, :unauthenticated, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::ENABLED, :external, Snippet::PUBLIC, false], - [:internal, ProjectFeature::ENABLED, :external, Snippet::INTERNAL, false], - [:internal, ProjectFeature::ENABLED, :external, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::ENABLED, :non_member, Snippet::PUBLIC, true], - [:internal, ProjectFeature::ENABLED, :non_member, Snippet::INTERNAL, true], - [:internal, ProjectFeature::ENABLED, :non_member, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::ENABLED, :member, Snippet::PUBLIC, true], - [:internal, ProjectFeature::ENABLED, :member, Snippet::INTERNAL, true], - [:internal, ProjectFeature::ENABLED, :member, Snippet::PRIVATE, true], - - [:internal, ProjectFeature::ENABLED, :author, Snippet::PUBLIC, true], - [:internal, ProjectFeature::ENABLED, :author, Snippet::INTERNAL, true], - [:internal, ProjectFeature::ENABLED, :author, Snippet::PRIVATE, true], - - [:internal, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PUBLIC, false], - [:internal, ProjectFeature::PRIVATE, :unauthenticated, Snippet::INTERNAL, false], - [:internal, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::PRIVATE, :external, Snippet::PUBLIC, false], - [:internal, ProjectFeature::PRIVATE, :external, Snippet::INTERNAL, false], - [:internal, ProjectFeature::PRIVATE, :external, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::PRIVATE, :non_member, Snippet::PUBLIC, false], - [:internal, ProjectFeature::PRIVATE, :non_member, Snippet::INTERNAL, false], - [:internal, ProjectFeature::PRIVATE, :non_member, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::PRIVATE, :member, Snippet::PUBLIC, true], - [:internal, ProjectFeature::PRIVATE, :member, Snippet::INTERNAL, true], - [:internal, ProjectFeature::PRIVATE, :member, Snippet::PRIVATE, true], - - [:internal, ProjectFeature::PRIVATE, :author, Snippet::PUBLIC, true], - [:internal, ProjectFeature::PRIVATE, :author, Snippet::INTERNAL, true], - [:internal, ProjectFeature::PRIVATE, :author, Snippet::PRIVATE, true], - - [:internal, ProjectFeature::DISABLED, :unauthenticated, Snippet::PUBLIC, false], - [:internal, ProjectFeature::DISABLED, :unauthenticated, Snippet::INTERNAL, false], - [:internal, ProjectFeature::DISABLED, :unauthenticated, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::DISABLED, :external, Snippet::PUBLIC, false], - [:internal, ProjectFeature::DISABLED, :external, Snippet::INTERNAL, false], - [:internal, ProjectFeature::DISABLED, :external, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::DISABLED, :non_member, Snippet::PUBLIC, false], - [:internal, ProjectFeature::DISABLED, :non_member, Snippet::INTERNAL, false], - [:internal, ProjectFeature::DISABLED, :non_member, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::DISABLED, :member, Snippet::PUBLIC, false], - [:internal, ProjectFeature::DISABLED, :member, Snippet::INTERNAL, false], - [:internal, ProjectFeature::DISABLED, :member, Snippet::PRIVATE, false], - - [:internal, ProjectFeature::DISABLED, :author, Snippet::PUBLIC, false], - [:internal, ProjectFeature::DISABLED, :author, Snippet::INTERNAL, false], - [:internal, ProjectFeature::DISABLED, :author, Snippet::PRIVATE, false], - - # Private projects - [:private, ProjectFeature::ENABLED, :unauthenticated, Snippet::PUBLIC, false], - [:private, ProjectFeature::ENABLED, :unauthenticated, Snippet::INTERNAL, false], - [:private, ProjectFeature::ENABLED, :unauthenticated, Snippet::PRIVATE, false], - - [:private, ProjectFeature::ENABLED, :external, Snippet::PUBLIC, true], - [:private, ProjectFeature::ENABLED, :external, Snippet::INTERNAL, true], - [:private, ProjectFeature::ENABLED, :external, Snippet::PRIVATE, true], - - [:private, ProjectFeature::ENABLED, :non_member, Snippet::PUBLIC, false], - [:private, ProjectFeature::ENABLED, :non_member, Snippet::INTERNAL, false], - [:private, ProjectFeature::ENABLED, :non_member, Snippet::PRIVATE, false], - - [:private, ProjectFeature::ENABLED, :member, Snippet::PUBLIC, true], - [:private, ProjectFeature::ENABLED, :member, Snippet::INTERNAL, true], - [:private, ProjectFeature::ENABLED, :member, Snippet::PRIVATE, true], - - [:private, ProjectFeature::ENABLED, :author, Snippet::PUBLIC, true], - [:private, ProjectFeature::ENABLED, :author, Snippet::INTERNAL, true], - [:private, ProjectFeature::ENABLED, :author, Snippet::PRIVATE, true], - - [:private, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PUBLIC, false], - [:private, ProjectFeature::PRIVATE, :unauthenticated, Snippet::INTERNAL, false], - [:private, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PRIVATE, false], - - [:private, ProjectFeature::PRIVATE, :external, Snippet::PUBLIC, true], - [:private, ProjectFeature::PRIVATE, :external, Snippet::INTERNAL, true], - [:private, ProjectFeature::PRIVATE, :external, Snippet::PRIVATE, true], - - [:private, ProjectFeature::PRIVATE, :non_member, Snippet::PUBLIC, false], - [:private, ProjectFeature::PRIVATE, :non_member, Snippet::INTERNAL, false], - [:private, ProjectFeature::PRIVATE, :non_member, Snippet::PRIVATE, false], - - [:private, ProjectFeature::PRIVATE, :member, Snippet::PUBLIC, true], - [:private, ProjectFeature::PRIVATE, :member, Snippet::INTERNAL, true], - [:private, ProjectFeature::PRIVATE, :member, Snippet::PRIVATE, true], - - [:private, ProjectFeature::PRIVATE, :author, Snippet::PUBLIC, true], - [:private, ProjectFeature::PRIVATE, :author, Snippet::INTERNAL, true], - [:private, ProjectFeature::PRIVATE, :author, Snippet::PRIVATE, true], - - [:private, ProjectFeature::DISABLED, :unauthenticated, Snippet::PUBLIC, false], - [:private, ProjectFeature::DISABLED, :unauthenticated, Snippet::INTERNAL, false], - [:private, ProjectFeature::DISABLED, :unauthenticated, Snippet::PRIVATE, false], - - [:private, ProjectFeature::DISABLED, :external, Snippet::PUBLIC, false], - [:private, ProjectFeature::DISABLED, :external, Snippet::INTERNAL, false], - [:private, ProjectFeature::DISABLED, :external, Snippet::PRIVATE, false], - - [:private, ProjectFeature::DISABLED, :non_member, Snippet::PUBLIC, false], - [:private, ProjectFeature::DISABLED, :non_member, Snippet::INTERNAL, false], - [:private, ProjectFeature::DISABLED, :non_member, Snippet::PRIVATE, false], - - [:private, ProjectFeature::DISABLED, :member, Snippet::PUBLIC, false], - [:private, ProjectFeature::DISABLED, :member, Snippet::INTERNAL, false], - [:private, ProjectFeature::DISABLED, :member, Snippet::PRIVATE, false], - - [:private, ProjectFeature::DISABLED, :author, Snippet::PUBLIC, false], - [:private, ProjectFeature::DISABLED, :author, Snippet::INTERNAL, false], - [:private, ProjectFeature::DISABLED, :author, Snippet::PRIVATE, false] - ] - end - - with_them do - let!(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel.level_value(project_type.to_s)) } - let!(:project_feature) { project.project_feature.update_column(:snippets_access_level, feature_visibility) } - let!(:user) { users[user_type] } - let!(:snippet) { create(:project_snippet, visibility_level: snippet_type, project: project, author: author) } - let!(:members) do - project.add_developer(author) - project.add_developer(member) - project.add_developer(external) if project.private? - end - - context "For #{params[:project_type]} project and #{params[:user_type]} users" do - it 'should agree with the read_project_snippet policy' do - expect(can?(user, :read_project_snippet, snippet)).to eq(outcome) - end - - it 'should return proper outcome' do - results = described_class.new(user, project: project).execute - - expect(results.include?(snippet)).to eq(outcome) - end - end - - context "Without a given project and #{params[:user_type]} users" do - it 'should return proper outcome' do - results = described_class.new(user).execute - expect(results.include?(snippet)).to eq(outcome) - end - - it 'returns no snippets when the user cannot read cross project' do - allow(Ability).to receive(:allowed?).and_call_original - allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } - - snippets = described_class.new(user).execute - - expect(snippets).to be_empty - end - end - end - end - - context 'For personal snippets' do - let!(:users) do - { - unauthenticated: nil, - external: external, - non_member: create(:user), - author: author - } - end - - where(:snippet_visibility, :user_type, :outcome) do - [ - [Snippet::PUBLIC, :unauthenticated, true], - [Snippet::PUBLIC, :external, true], - [Snippet::PUBLIC, :non_member, true], - [Snippet::PUBLIC, :author, true], - - [Snippet::INTERNAL, :unauthenticated, false], - [Snippet::INTERNAL, :external, false], - [Snippet::INTERNAL, :non_member, true], - [Snippet::INTERNAL, :author, true], - - [Snippet::PRIVATE, :unauthenticated, false], - [Snippet::PRIVATE, :external, false], - [Snippet::PRIVATE, :non_member, false], - [Snippet::PRIVATE, :author, true] - ] - end - - with_them do - let!(:user) { users[user_type] } - let!(:snippet) { create(:personal_snippet, visibility_level: snippet_visibility, author: author) } - - context "For personal and #{params[:snippet_visibility]} snippets with #{params[:user_type]} user" do - it 'should agree with read_personal_snippet policy' do - expect(can?(user, :read_personal_snippet, snippet)).to eq(outcome) - end - - it 'should return proper outcome' do - results = described_class.new(user).execute - expect(results.include?(snippet)).to eq(outcome) - end - - it 'should return personal snippets when the user cannot read cross project' do - allow(Ability).to receive(:allowed?).and_call_original - allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } - - results = described_class.new(user).execute - - expect(results.include?(snippet)).to eq(outcome) - end - end - end - end -end |