diff --git a/groups/api/http/endpoint_test.go b/groups/api/http/endpoint_test.go index 537dc8ccc0..a322b91cd9 100644 --- a/groups/api/http/endpoint_test.go +++ b/groups/api/http/endpoint_test.go @@ -1066,7 +1066,7 @@ func TestRetrieveGroupHierarchyEndpoint(t *testing.T) { gs, svc, authn := newGroupsServer() defer gs.Close() - retrieveHierarchRes := groups.HierarchyPage{ + retrieveHierarchyRes := groups.HierarchyPage{ Groups: []groups.Group{validGroupResp}, HierarchyPageMeta: groups.HierarchyPageMeta{ Level: 1, @@ -1075,6 +1075,15 @@ func TestRetrieveGroupHierarchyEndpoint(t *testing.T) { }, } + treeHierarchyRes := groups.HierarchyPage{ + Groups: []groups.Group{validGroupResp}, + HierarchyPageMeta: groups.HierarchyPageMeta{ + Level: 1, + Direction: -1, + Tree: true, + }, + } + cases := []struct { desc string token string @@ -1100,7 +1109,23 @@ func TestRetrieveGroupHierarchyEndpoint(t *testing.T) { Direction: -1, Tree: false, }, - svcRes: retrieveHierarchRes, + svcRes: retrieveHierarchyRes, + svcErr: nil, + status: http.StatusOK, + err: nil, + }, + { + desc: "retrieve group hierarchy successfully with tree", + token: validToken, + domainID: validID, + groupID: validID, + query: "level=1&dir=-1&tree=true", + pageMeta: groups.HierarchyPageMeta{ + Level: 1, + Direction: -1, + Tree: true, + }, + svcRes: treeHierarchyRes, svcErr: nil, status: http.StatusOK, err: nil, diff --git a/groups/api/http/endpoints.go b/groups/api/http/endpoints.go index 4197c98e0b..c41b87df0f 100644 --- a/groups/api/http/endpoints.go +++ b/groups/api/http/endpoints.go @@ -200,6 +200,9 @@ func retrieveGroupHierarchyEndpoint(svc groups.Service) endpoint.Endpoint { if err != nil { return retrieveGroupHierarchyRes{}, err } + if req.HierarchyPageMeta.Tree { + return buildGroupsResponseTree(hp), nil + } groups := []viewGroupRes{} for _, g := range hp.Groups { @@ -342,3 +345,42 @@ func toViewGroupRes(group groups.Group) viewGroupRes { } return view } + +func buildGroupsResponseTree(page groups.HierarchyPage) retrieveGroupHierarchyRes { + groupsMap := map[string]*groups.Group{} + parentsMap := map[string][]*groups.Group{} + for i := range page.Groups { + if _, ok := groupsMap[page.Groups[i].ID]; !ok { + groupsMap[page.Groups[i].ID] = &page.Groups[i] + parentsMap[page.Groups[i].ID] = make([]*groups.Group, 0) + } + } + + for _, group := range groupsMap { + if children, ok := parentsMap[group.Parent]; ok { + children = append(children, group) + parentsMap[group.Parent] = children + } + } + + res := retrieveGroupHierarchyRes{ + Level: page.Level, + Direction: page.Direction, + Groups: []viewGroupRes{}, + } + + for _, group := range groupsMap { + if children, ok := parentsMap[group.ID]; ok { + group.Children = children + } + } + + for _, group := range groupsMap { + view := toViewGroupRes(*group) + if children, ok := parentsMap[group.Parent]; len(children) == 0 || !ok { + res.Groups = append(res.Groups, view) + } + } + + return res +}