From f4214be7ed27b7c2c8dbc9782f9fcc057cc776e7 Mon Sep 17 00:00:00 2001
From: FromTheStackAndBack
 <2485302-FromTheStackAndBack@users.noreply.gitlab.com>
Date: Sat, 1 Jul 2023 03:19:20 +0000
Subject: [PATCH] Add "owned" parameter to group project listing

Changelog: fixed
---
 app/finders/group_projects_finder.rb       |  9 ++++-
 spec/finders/group_projects_finder_spec.rb | 10 +++++
 spec/requests/api/groups_spec.rb           | 44 ++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb
index 00b700a101ec6..db8a0f14fbc30 100644
--- a/app/finders/group_projects_finder.rb
+++ b/app/finders/group_projects_finder.rb
@@ -24,6 +24,7 @@
 #     with_issues_enabled: boolean
 #     with_merge_requests_enabled: boolean
 #     min_access_level: int
+#     owned: boolean
 #
 class GroupProjectsFinder < ProjectsFinder
   DEFAULT_PROJECTS_LIMIT = 100
@@ -83,7 +84,9 @@ def by_feature_availability(projects)
 
   def filter_by_visibility(relation)
     if current_user
-      if min_access_level?
+      if owned_projects?
+        relation.visible_to_user_and_access_level(current_user, Gitlab::Access::OWNER)
+      elsif min_access_level?
         relation.visible_to_user_and_access_level(current_user, params[:min_access_level])
       else
         relation.public_or_visible_to_user(current_user)
@@ -105,6 +108,10 @@ def only_owned?
     options.fetch(:only_owned, false)
   end
 
+  def owned_projects?
+    params.fetch(:owned, false)
+  end
+
   def only_shared?
     options.fetch(:only_shared, false)
   end
diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb
index 4189be94cc1f3..87e579dbeec45 100644
--- a/spec/finders/group_projects_finder_spec.rb
+++ b/spec/finders/group_projects_finder_spec.rb
@@ -87,6 +87,16 @@
       end
     end
 
+    context "owned" do
+      before do
+        root_group.add_owner(current_user)
+      end
+
+      let(:params) { { owned: true } }
+
+      it { is_expected.to match_array([private_project, public_project]) }
+    end
+
     context "all" do
       context 'with subgroups projects' do
         before do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 0fa78d213843c..7ce7435ce37d1 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -1091,6 +1091,50 @@ def make_upload_request
         end
       end
 
+      context 'with owned' do
+        let(:group) { create(:group) }
+
+        let(:project1) { create(:project, group: group) }
+        let(:project1_guest) { create(:user) }
+        let(:project1_owner) { create(:user) }
+        let(:project1_maintainer) { create(:user) }
+
+        let(:project2) { create(:project, group: group) }
+
+        before do
+          project1.add_guest(project1_guest)
+          project1.add_owner(project1_owner)
+          project1.add_maintainer(project1_maintainer)
+
+          project2_owner = project1_owner
+          project2.add_owner(project2_owner)
+        end
+
+        context "as a guest" do
+          it 'returns no projects' do
+            get api("/groups/#{group.id}/projects", project1_guest), params: { owned: true }
+            project_ids = json_response.map { |proj| proj['id'] }
+            expect(project_ids).to match_array([])
+          end
+        end
+
+        context "as a maintainer" do
+          it 'returns no projects' do
+            get api("/groups/#{group.id}/projects", project1_maintainer), params: { owned: true }
+            project_ids = json_response.map { |proj| proj['id'] }
+            expect(project_ids).to match_array([])
+          end
+        end
+
+        context "as an owner" do
+          it 'returns projects with owner access level' do
+            get api("/groups/#{group.id}/projects", project1_owner), params: { owned: true }
+            project_ids = json_response.map { |proj| proj['id'] }
+            expect(project_ids).to match_array([project1.id, project2.id])
+          end
+        end
+      end
+
       it "returns the group's projects", :aggregate_failures do
         get api("/groups/#{group1.id}/projects", user1)
 
-- 
GitLab