Commit ef0477e4 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch '351703-performance-issues-with-releasescontroller-and-subgroups' into 'master'

Resolve "Performance Issues with ReleasesController and subgroups"

See merge request gitlab-org/gitlab!79674
parents 955dfb36 476c4ba9
...@@ -38,19 +38,17 @@ class ReleasesFinder ...@@ -38,19 +38,17 @@ class ReleasesFinder
if parent.is_a?(Project) if parent.is_a?(Project)
Ability.allowed?(current_user, :read_release, parent) ? [parent] : [] Ability.allowed?(current_user, :read_release, parent) ? [parent] : []
elsif parent.is_a?(Group) elsif parent.is_a?(Group)
accessible_projects Ability.allowed?(current_user, :read_release, parent) ? accessible_projects : []
end end
end end
end end
def accessible_projects def accessible_projects
projects = if include_subgroups? if include_subgroups?
Project.for_group_and_its_subgroups(parent) Project.for_group_and_its_subgroups(parent)
else else
parent.projects parent.projects
end end
projects.select { |project| Ability.allowed?(current_user, :read_release, project) }
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
......
...@@ -100,6 +100,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy ...@@ -100,6 +100,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :read_group enable :read_group
enable :upload_file enable :upload_file
enable :guest_access enable :guest_access
enable :read_release
end end
rule { admin }.policy do rule { admin }.policy do
......
...@@ -6,14 +6,14 @@ RSpec.describe Groups::ReleasesController do ...@@ -6,14 +6,14 @@ RSpec.describe Groups::ReleasesController do
let(:group) { create(:group) } let(:group) { create(:group) }
let!(:project) { create(:project, :repository, :public, namespace: group) } let!(:project) { create(:project, :repository, :public, namespace: group) }
let!(:private_project) { create(:project, :repository, :private, namespace: group) } let!(:private_project) { create(:project, :repository, :private, namespace: group) }
let(:developer) { create(:user) } let(:guest) { create(:user) }
let!(:release_1) { create(:release, project: project, tag: 'v1', released_at: Time.zone.parse('2020-02-15')) } let!(:release_1) { create(:release, project: project, tag: 'v1', released_at: Time.zone.parse('2020-02-15')) }
let!(:release_2) { create(:release, project: project, tag: 'v2', released_at: Time.zone.parse('2020-02-20')) } let!(:release_2) { create(:release, project: project, tag: 'v2', released_at: Time.zone.parse('2020-02-20')) }
let!(:private_release_1) { create(:release, project: private_project, tag: 'p1', released_at: Time.zone.parse('2020-03-01')) } let!(:private_release_1) { create(:release, project: private_project, tag: 'p1', released_at: Time.zone.parse('2020-03-01')) }
let!(:private_release_2) { create(:release, project: private_project, tag: 'p2', released_at: Time.zone.parse('2020-03-05')) } let!(:private_release_2) { create(:release, project: private_project, tag: 'p2', released_at: Time.zone.parse('2020-03-05')) }
before do before do
private_project.add_developer(developer) group.add_guest(guest)
end end
describe 'GET #index' do describe 'GET #index' do
...@@ -42,7 +42,7 @@ RSpec.describe Groups::ReleasesController do ...@@ -42,7 +42,7 @@ RSpec.describe Groups::ReleasesController do
end end
it 'does not return any releases' do it 'does not return any releases' do
expect(json_response.map {|r| r['tag'] } ).to match_array(%w(v2 v1)) expect(json_response.map {|r| r['tag'] } ).to be_empty
end end
it 'returns OK' do it 'returns OK' do
...@@ -52,7 +52,7 @@ RSpec.describe Groups::ReleasesController do ...@@ -52,7 +52,7 @@ RSpec.describe Groups::ReleasesController do
context 'the user is authorized' do context 'the user is authorized' do
it "returns all group's public and private project's releases as JSON, ordered by released_at" do it "returns all group's public and private project's releases as JSON, ordered by released_at" do
sign_in(developer) sign_in(guest)
subject subject
......
...@@ -23,6 +23,16 @@ RSpec.describe ReleasesFinder do ...@@ -23,6 +23,16 @@ RSpec.describe ReleasesFinder do
end end
end end
shared_examples_for 'when the user is not part of the group' do
before do
allow(Ability).to receive(:allowed?).with(user, :read_release, group).and_return(false)
end
it 'returns no releases' do
is_expected.to be_empty
end
end
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27716 # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27716
shared_examples_for 'when tag is nil' do shared_examples_for 'when tag is nil' do
before do before do
...@@ -66,9 +76,9 @@ RSpec.describe ReleasesFinder do ...@@ -66,9 +76,9 @@ RSpec.describe ReleasesFinder do
it_behaves_like 'when the user is not part of the project' it_behaves_like 'when the user is not part of the project'
context 'when the user is a project developer' do context 'when the user is a project guest' do
before do before do
project.add_developer(user) project.add_guest(user)
end end
it 'sorts by release date' do it 'sorts by release date' do
...@@ -118,25 +128,24 @@ RSpec.describe ReleasesFinder do ...@@ -118,25 +128,24 @@ RSpec.describe ReleasesFinder do
subject { described_class.new(group, user, params).execute(**args) } subject { described_class.new(group, user, params).execute(**args) }
it_behaves_like 'when the user is not part of the project' it_behaves_like 'when the user is not part of the group'
context 'when the user is a project developer on one sibling project' do context 'when the user is a project guest on one sibling project' do
before do before do
project.add_developer(user) project.add_guest(user)
v1_0_0.update_attribute(:released_at, 3.days.ago) v1_0_0.update_attribute(:released_at, 3.days.ago)
v1_1_0.update_attribute(:released_at, 1.day.ago) v1_1_0.update_attribute(:released_at, 1.day.ago)
end end
it 'sorts by release date' do it 'does not return any releases' do
expect(subject.size).to eq(2) expect(subject.size).to eq(0)
expect(subject).to eq([v1_1_0, v1_0_0]) expect(subject).to eq([])
end end
end end
context 'when the user is a project developer on all projects' do context 'when the user is a guest on the group' do
before do before do
project.add_developer(user) group.add_guest(user)
project2.add_developer(user)
v1_0_0.update_attribute(:released_at, 3.days.ago) v1_0_0.update_attribute(:released_at, 3.days.ago)
v6.update_attribute(:released_at, 2.days.ago) v6.update_attribute(:released_at, 2.days.ago)
v1_1_0.update_attribute(:released_at, 1.day.ago) v1_1_0.update_attribute(:released_at, 1.day.ago)
...@@ -161,22 +170,21 @@ RSpec.describe ReleasesFinder do ...@@ -161,22 +170,21 @@ RSpec.describe ReleasesFinder do
let(:project2) { create(:project, :repository, namespace: subgroup) } let(:project2) { create(:project, :repository, namespace: subgroup) }
let!(:v6) { create(:release, project: project2, tag: 'v6') } let!(:v6) { create(:release, project: project2, tag: 'v6') }
it_behaves_like 'when the user is not part of the project' it_behaves_like 'when the user is not part of the group'
context 'when the user a project developer in the subgroup project' do context 'when the user a project guest in the subgroup project' do
before do before do
project2.add_developer(user) project2.add_guest(user)
end end
it 'returns only the subgroup releases' do it 'does not return any releases' do
expect(subject).to match_array([v6]) expect(subject).to match_array([])
end end
end end
context 'when the user a project developer in both projects' do context 'when the user is a guest on the group' do
before do before do
project.add_developer(user) group.add_guest(user)
project2.add_developer(user)
v6.update_attribute(:released_at, 2.days.ago) v6.update_attribute(:released_at, 2.days.ago)
end end
...@@ -201,34 +209,32 @@ RSpec.describe ReleasesFinder do ...@@ -201,34 +209,32 @@ RSpec.describe ReleasesFinder do
p3.update_attribute(:released_at, 3.days.ago) p3.update_attribute(:released_at, 3.days.ago)
end end
it_behaves_like 'when the user is not part of the project' it_behaves_like 'when the user is not part of the group'
context 'when the user a project developer in the subgroup and subsubgroup project' do context 'when the user a project guest in the subgroup and subsubgroup project' do
before do before do
project2.add_developer(user) project2.add_guest(user)
project3.add_developer(user) project3.add_guest(user)
end end
it 'returns only the subgroup and subsubgroup releases' do it 'does not return any releases' do
expect(subject).to match_array([v6, p3]) expect(subject).to match_array([])
end end
end end
context 'when the user a project developer in the subsubgroup project' do context 'when the user a project guest in the subsubgroup project' do
before do before do
project3.add_developer(user) project3.add_guest(user)
end end
it 'returns only the subsubgroup releases' do it 'does not return any releases' do
expect(subject).to match_array([p3]) expect(subject).to match_array([])
end end
end end
context 'when the user a project developer in all projects' do context 'when the user a guest on the group' do
before do before do
project.add_developer(user) group.add_guest(user)
project2.add_developer(user)
project3.add_developer(user)
end end
it 'returns all releases' do it 'returns all releases' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment