Commit 46def204 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'add-members-count-and-parent-id-data-on-namespaces-api' into 'master'

Add group members counting related data on namespaces API

See merge request !12497
parents 572fa2cb e8ebad15
......@@ -222,6 +222,12 @@ class Group < Namespace
User.where(id: members_with_parents.select(:user_id))
end
def users_with_descendants
members_with_descendants = GroupMember.non_request.where(source_id: descendants.pluck(:id).push(id))
User.where(id: members_with_descendants.select(:user_id))
end
def max_member_access_for_user(user)
return GroupMember::OWNER if user.admin?
......
---
title: Add group members counting and plan related data on namespaces API
merge_request:
author:
......@@ -29,22 +29,30 @@ Example response:
{
"id": 1,
"path": "user1",
"kind": "user"
"kind": "user",
"full_path": "user1"
},
{
"id": 2,
"path": "group1",
"kind": "group"
"kind": "group",
"full_path": "group1",
"parent_id": "null",
"members_count_with_descendants": 2
},
{
"id": 3,
"path": "bar",
"kind": "group",
"full_path": "foo/bar",
"parent_id": "9",
"members_count_with_descendants": 5
}
]
```
**Note**: `members_count_with_descendants` are presented only for group masters/owners.
## Search for namespace
Get all namespaces that match a string in their name or path.
......@@ -72,6 +80,8 @@ Example response:
"path": "twitter",
"kind": "group",
"full_path": "twitter",
"parent_id": "null",
"members_count_with_descendants": 2
}
]
```
......@@ -444,7 +444,15 @@ module API
end
class Namespace < Grape::Entity
expose :id, :name, :path, :kind, :full_path
expose :id, :name, :path, :kind, :full_path, :parent_id
expose :members_count_with_descendants, if: -> (namespace, opts) { expose_members_count_with_descendants?(namespace, opts) } do |namespace, _|
namespace.users_with_descendants.count
end
def expose_members_count_with_descendants?(namespace, opts)
namespace.kind == 'group' && Ability.allowed?(opts[:current_user], :admin_group, namespace)
end
end
class MemberAccess < Grape::Entity
......
......@@ -17,7 +17,7 @@ module API
namespaces = namespaces.search(params[:search]) if params[:search].present?
present paginate(namespaces), with: Entities::Namespace
present paginate(namespaces), with: Entities::Namespace, current_user: current_user
end
end
end
......
......@@ -323,6 +323,25 @@ describe Namespace, models: true do
end
end
describe '#users_with_descendants', :nested_groups do
let(:user_a) { create(:user) }
let(:user_b) { create(:user) }
let(:group) { create(:group) }
let(:nested_group) { create(:group, parent: group) }
let(:deep_nested_group) { create(:group, parent: nested_group) }
it 'returns member users on every nest level without duplication' do
group.add_developer(user_a)
nested_group.add_developer(user_b)
deep_nested_group.add_developer(user_a)
expect(group.users_with_descendants).to contain_exactly(user_a, user_b)
expect(nested_group.users_with_descendants).to contain_exactly(user_a, user_b)
expect(deep_nested_group.users_with_descendants).to contain_exactly(user_a)
end
end
describe '#user_ids_for_project_authorizations' do
it 'returns the user IDs for which to refresh authorizations' do
expect(namespace.user_ids_for_project_authorizations)
......
......@@ -15,6 +15,20 @@ describe API::Namespaces do
end
context "when authenticated as admin" do
it "returns correct attributes" do
get api("/namespaces", admin)
group_kind_json_response = json_response.find { |resource| resource['kind'] == 'group' }
user_kind_json_response = json_response.find { |resource| resource['kind'] == 'user' }
expect(response).to have_http_status(200)
expect(response).to include_pagination_headers
expect(group_kind_json_response.keys).to contain_exactly('id', 'kind', 'name', 'path', 'full_path',
'parent_id', 'members_count_with_descendants')
expect(user_kind_json_response.keys).to contain_exactly('id', 'kind', 'name', 'path', 'full_path', 'parent_id')
end
it "admin: returns an array of all namespaces" do
get api("/namespaces", admin)
......@@ -37,6 +51,27 @@ describe API::Namespaces do
end
context "when authenticated as a regular user" do
it "returns correct attributes when user can admin group" do
group1.add_owner(user)
get api("/namespaces", user)
owned_group_response = json_response.find { |resource| resource['id'] == group1.id }
expect(owned_group_response.keys).to contain_exactly('id', 'kind', 'name', 'path', 'full_path',
'parent_id', 'members_count_with_descendants')
end
it "returns correct attributes when user cannot admin group" do
group1.add_guest(user)
get api("/namespaces", user)
guest_group_response = json_response.find { |resource| resource['id'] == group1.id }
expect(guest_group_response.keys).to contain_exactly('id', 'kind', 'name', 'path', 'full_path', 'parent_id')
end
it "user: returns an array of namespaces" do
get api("/namespaces", user)
......
......@@ -698,7 +698,8 @@ describe API::Projects do
'name' => user.namespace.name,
'path' => user.namespace.path,
'kind' => user.namespace.kind,
'full_path' => user.namespace.full_path
'full_path' => user.namespace.full_path,
'parent_id' => nil
})
end
......
......@@ -734,7 +734,8 @@ describe API::V3::Projects do
'name' => user.namespace.name,
'path' => user.namespace.path,
'kind' => user.namespace.kind,
'full_path' => user.namespace.full_path
'full_path' => user.namespace.full_path,
'parent_id' => nil
})
end
......
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