Skip to content

Commit

Permalink
MG-2026 - Fix JSON page response key from groups to channels (abs…
Browse files Browse the repository at this point in the history
…mach#2298)

Signed-off-by: JeffMboya <[email protected]>
  • Loading branch information
JeffMboya authored Jun 26, 2024
1 parent 1893107 commit b0e37da
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 16 deletions.
6 changes: 3 additions & 3 deletions api/openapi/things.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ paths:
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
"404":
description: A non-existent entity request.
"415":
description: Missing or invalid content type.
Expand Down Expand Up @@ -1370,7 +1370,7 @@ components:
ChannelsPage:
type: object
properties:
groups:
channels:
type: array
minItems: 0
uniqueItems: true
Expand All @@ -1388,7 +1388,7 @@ components:
example: 10
description: Maximum number of items to return in one page.
required:
- groups
- channels
- total
- offset

Expand Down
2 changes: 1 addition & 1 deletion bootstrap/mocks/config_reader.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion internal/groups/api/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/absmach/magistrala/pkg/groups"
"github.com/absmach/magistrala/pkg/groups/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

var validGroupResp = groups.Group{
Expand Down Expand Up @@ -679,7 +680,7 @@ func TestListGroupsEndpoint(t *testing.T) {
tc.req.memberKind = tc.memberKind
}
repoCall := svc.On("ListGroups", context.Background(), tc.req.token, tc.req.memberKind, tc.req.memberID, tc.req.Page).Return(tc.svcResp, tc.svcErr)
resp, err := ListGroupsEndpoint(svc, tc.memberKind)(context.Background(), tc.req)
resp, err := ListGroupsEndpoint(svc, mock.Anything, tc.memberKind)(context.Background(), tc.req)
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("expected error %v to contain %v", err, tc.err))
response := resp.(groupPageRes)
Expand Down
35 changes: 34 additions & 1 deletion internal/groups/api/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/go-kit/kit/endpoint"
)

const groupTypeChannels = "channels"

func CreateGroupEndpoint(svc groups.Service, kind string) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(createGroupReq)
Expand Down Expand Up @@ -111,17 +113,23 @@ func DisableGroupEndpoint(svc groups.Service) endpoint.Endpoint {
}
}

func ListGroupsEndpoint(svc groups.Service, memberKind string) endpoint.Endpoint {
func ListGroupsEndpoint(svc groups.Service, groupType, memberKind string) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(listGroupsReq)
if memberKind != "" {
req.memberKind = memberKind
}
if err := req.validate(); err != nil {
if groupType == groupTypeChannels {
return channelPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
}
return groupPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
}
page, err := svc.ListGroups(ctx, req.token, req.memberKind, req.memberID, req.Page)
if err != nil {
if groupType == groupTypeChannels {
return channelPageRes{}, err
}
return groupPageRes{}, err
}

Expand All @@ -130,6 +138,9 @@ func ListGroupsEndpoint(svc groups.Service, memberKind string) endpoint.Endpoint
}
filterByID := req.Page.ID != ""

if groupType == groupTypeChannels {
return buildChannelsResponse(page, filterByID), nil
}
return buildGroupsResponse(page, filterByID), nil
}
}
Expand Down Expand Up @@ -284,3 +295,25 @@ func buildGroupsResponse(gp groups.Page, filterByID bool) groupPageRes {

return res
}

func buildChannelsResponse(cp groups.Page, filterByID bool) channelPageRes {
res := channelPageRes{
pageRes: pageRes{
Total: cp.Total,
Level: cp.Level,
},
Channels: []viewGroupRes{},
}

for _, channel := range cp.Groups {
if filterByID && channel.Level == 0 {
continue
}
view := viewGroupRes{
Group: channel,
}
res.Channels = append(res.Channels, view)
}

return res
}
17 changes: 17 additions & 0 deletions internal/groups/api/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ func (res groupPageRes) Empty() bool {
return false
}

type channelPageRes struct {
pageRes
Channels []viewGroupRes `json:"channels"`
}

func (res channelPageRes) Code() int {
return http.StatusOK
}

func (res channelPageRes) Headers() map[string]string {
return map[string]string{}
}

func (res channelPageRes) Empty() bool {
return false
}

type updateGroupRes struct {
groups.Group `json:",inline"`
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/sdk/go/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type ThingsPage struct {

// ChannelsPage contains list of channels in a page with proper metadata.
type ChannelsPage struct {
Channels []Channel `json:"groups"`
Channels []Channel `json:"channels"`
PageRes
}

Expand Down
8 changes: 4 additions & 4 deletions things/api/http/channels.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func groupsHandler(svc groups.Service, r *chi.Mux, logger *slog.Logger) http.Han
), "update_channel").ServeHTTP)

r.Get("/", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "users"),
gapi.ListGroupsEndpoint(svc, "channels", "users"),
gapi.DecodeListGroupsRequest,
api.EncodeResponse,
opts...,
Expand Down Expand Up @@ -139,7 +139,7 @@ func groupsHandler(svc groups.Service, r *chi.Mux, logger *slog.Logger) http.Han
// and channel service can access spiceDB and get this channel ids list with given thing id.
// Request to get list of channels to which thingID ({memberID}) belongs
r.Get("/things/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "things"),
gapi.ListGroupsEndpoint(svc, "channels", "things"),
gapi.DecodeListGroupsRequest,
api.EncodeResponse,
opts...,
Expand All @@ -151,7 +151,7 @@ func groupsHandler(svc groups.Service, r *chi.Mux, logger *slog.Logger) http.Han
// and channel service can access spiceDB and get this user ids list with given thing id.
// Request to get list of channels to which userID ({memberID}) have permission.
r.Get("/users/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "users"),
gapi.ListGroupsEndpoint(svc, "channels", "users"),
gapi.DecodeListGroupsRequest,
api.EncodeResponse,
opts...,
Expand All @@ -162,7 +162,7 @@ func groupsHandler(svc groups.Service, r *chi.Mux, logger *slog.Logger) http.Han
// and channel service can access spiceDB and get this user ids list with given user_group id.
// Request to get list of channels to which user_group_id ({memberID}) attached.
r.Get("/groups/{memberID}/channels", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "groups"),
gapi.ListGroupsEndpoint(svc, "channels", "groups"),
gapi.DecodeListGroupsRequest,
api.EncodeResponse,
opts...,
Expand Down
10 changes: 5 additions & 5 deletions users/api/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,21 @@ func groupsHandler(svc groups.Service, r *chi.Mux, logger *slog.Logger) http.Han
), "update_group").ServeHTTP)

r.Get("/", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "users"),
gapi.ListGroupsEndpoint(svc, "groups", "users"),
gapi.DecodeListGroupsRequest,
api.EncodeResponse,
opts...,
), "list_groups").ServeHTTP)

r.Get("/{groupID}/children", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "users"),
gapi.ListGroupsEndpoint(svc, "groups", "users"),
gapi.DecodeListChildrenRequest,
api.EncodeResponse,
opts...,
), "list_children").ServeHTTP)

r.Get("/{groupID}/parents", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "users"),
gapi.ListGroupsEndpoint(svc, "groups", "users"),
gapi.DecodeListParentsRequest,
api.EncodeResponse,
opts...,
Expand Down Expand Up @@ -130,14 +130,14 @@ func groupsHandler(svc groups.Service, r *chi.Mux, logger *slog.Logger) http.Han
// The ideal placeholder name should be {channelID}, but gapi.DecodeListGroupsRequest uses {memberID} as a placeholder for the ID.
// So here, we are using {memberID} as the placeholder.
r.Get("/channels/{memberID}/groups", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "channels"),
gapi.ListGroupsEndpoint(svc, "groups", "channels"),
gapi.DecodeListGroupsRequest,
api.EncodeResponse,
opts...,
), "list_groups_by_channel_id").ServeHTTP)

r.Get("/users/{memberID}/groups", otelhttp.NewHandler(kithttp.NewServer(
gapi.ListGroupsEndpoint(svc, "users"),
gapi.ListGroupsEndpoint(svc, "groups", "users"),
gapi.DecodeListGroupsRequest,
api.EncodeResponse,
opts...,
Expand Down

0 comments on commit b0e37da

Please sign in to comment.