Commit 9417a122 authored by Max Woolf's avatar Max Woolf

Merge branch '28902_add_visible_only_option' into 'master'

Add "shared_visible_only" option to project's groups API

See merge request gitlab-org/gitlab!61118
parents 62ec1d02 561233ab
......@@ -7,6 +7,7 @@
# current_user - which user is requesting groups
# params:
# with_shared: boolean (optional)
# shared_visible_only: boolean (optional)
# shared_min_access_level: integer (optional)
# skip_groups: array of integers (optional)
#
......@@ -37,25 +38,35 @@ module Projects
Ability.allowed?(current_user, :read_project, project)
end
# rubocop: disable CodeReuse/ActiveRecord
def all_groups
groups = []
groups << project.group.self_and_ancestors if project.group
groups += [project.group.self_and_ancestors] if project.group
groups += with_shared_groups if params[:with_shared]
return [Group.none] if groups.compact.empty?
if params[:with_shared]
shared_groups = project.invited_groups
groups
end
if params[:shared_min_access_level]
shared_groups = shared_groups.where(
'project_group_links.group_access >= ?', params[:shared_min_access_level]
)
end
def with_shared_groups
shared_groups = project.invited_groups
shared_groups = apply_min_access_level(shared_groups)
groups << shared_groups
if params[:shared_visible_only]
[
shared_groups.public_to_user(current_user),
shared_groups.for_authorized_group_members(current_user&.id)
]
else
[shared_groups]
end
end
groups << Group.none if groups.compact.empty?
groups
# rubocop: disable CodeReuse/ActiveRecord
def apply_min_access_level(groups)
return groups unless params[:shared_min_access_level]
groups.where('project_group_links.group_access >= ?', params[:shared_min_access_level])
end
# rubocop: enable CodeReuse/ActiveRecord
......
---
title: Add shared_visible_only option to project's groups API
merge_request: 61118
author:
type: added
......@@ -1072,6 +1072,7 @@ GET /projects/:id/groups
| `skip_groups` | array of integers | **{dotted-circle}** No | Skip the group IDs passed. |
| `with_shared` | boolean | **{dotted-circle}** No | Include projects shared with this group. Default is `false`. |
| `shared_min_access_level` | integer | **{dotted-circle}** No | Limit to shared groups with at least this [access level](members.md#valid-access-levels). |
| `shared_visible_only` | boolean | **{dotted-circle}** No | Limit to shared groups user has access to. |
```json
[
......
......@@ -618,6 +618,8 @@ module API
optional :skip_groups, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of group ids to exclude from list'
optional :with_shared, type: Boolean, default: false,
desc: 'Include shared groups'
optional :shared_visible_only, type: Boolean, default: false,
desc: 'Limit to shared groups user has access to'
optional :shared_min_access_level, type: Integer, values: Gitlab::Access.all_values,
desc: 'Limit returned shared groups by minimum access level to the project'
use :pagination
......
......@@ -8,7 +8,7 @@ RSpec.describe Projects::GroupsFinder do
let_it_be(:root_group) { create(:group, :public) }
let_it_be(:project_group) { create(:group, :public, parent: root_group) }
let_it_be(:shared_group_with_dev_access) { create(:group, :private, parent: root_group) }
let_it_be(:shared_group_with_reporter_access) { create(:group, :private) }
let_it_be(:shared_group_with_reporter_access) { create(:group, :public) }
let_it_be(:public_project) { create(:project, :public, group: project_group) }
let_it_be(:private_project) { create(:project, :private, group: project_group) }
......@@ -53,6 +53,24 @@ RSpec.describe Projects::GroupsFinder do
is_expected.to match_array([project_group, root_group, shared_group_with_dev_access])
end
end
context 'when shared_visible_only is on' do
let(:params) { super().merge(shared_visible_only: true) }
it 'returns ancestor and public shared groups' do
is_expected.to match_array([project_group, root_group, shared_group_with_reporter_access])
end
context 'when user has access to the private shared group' do
before do
shared_group_with_dev_access.add_guest(current_user)
end
it 'returns ancestor and shared groups user has access to' do
is_expected.to match_array([project_group, root_group, shared_group_with_reporter_access, shared_group_with_dev_access])
end
end
end
end
context 'when skip group option is on' do
......@@ -74,6 +92,19 @@ RSpec.describe Projects::GroupsFinder do
it 'returns ancestor groups for this project' do
is_expected.to match_array([project_group, root_group])
end
context 'when visible shared groups are requested' do
let(:params) do
{
with_shared: true,
shared_visible_only: true
}
end
it 'returns ancestor groups and public shared groups for this project' do
is_expected.to match_array([project_group, root_group, shared_group_with_reporter_access])
end
end
end
end
end
......
......@@ -1683,7 +1683,7 @@ RSpec.describe API::Projects do
let_it_be(:root_group) { create(:group, :public, name: 'root group') }
let_it_be(:project_group) { create(:group, :public, parent: root_group, name: 'project group') }
let_it_be(:shared_group_with_dev_access) { create(:group, :private, parent: root_group, name: 'shared group') }
let_it_be(:shared_group_with_reporter_access) { create(:group, :private) }
let_it_be(:shared_group_with_reporter_access) { create(:group, :public) }
let_it_be(:private_project) { create(:project, :private, group: project_group) }
let_it_be(:public_project) { create(:project, :public, group: project_group) }
......@@ -1765,6 +1765,14 @@ RSpec.describe API::Projects do
end
end
context 'when shared_visible_only is on' do
let(:params) { super().merge(shared_visible_only: true) }
it_behaves_like 'successful groups response' do
let(:expected_groups) { [root_group, project_group, shared_group_with_reporter_access] }
end
end
context 'when search by shared group name' do
let(:params) { super().merge(search: 'shared') }
......
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