Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: user servicedata service to serve metadata #82

Merged
merged 8 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ GOVERSION := $(shell go version | cut -d ' ' -f 3 | cut -d '.' -f 2)

.PHONY: build check fmt lint test test-race vet test-cover-html help install proto
.DEFAULT_GOAL := build
PROTON_COMMIT := "e8a584e192f23f999844b027d17bd738c3981973"
PROTON_COMMIT := "6ee59f2d0cbeedf1d5fe48adee5e5e41f54f081e"

install:
@echo "Clean up imports..."
Expand Down
4 changes: 3 additions & 1 deletion core/group/filter.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package group

type Filter struct {
OrganizationID string
OrganizationID string
Project string
mabdh marked this conversation as resolved.
Show resolved Hide resolved
ServicedataKeyResourceIds []string
mabdh marked this conversation as resolved.
Show resolved Hide resolved
}
4 changes: 2 additions & 2 deletions core/servicedata/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func NewService(repository Repository, resourceService ResourceService, relation

func (s Service) CreateKey(ctx context.Context, key Key) (Key, error) {
// check if key contains ':'
if key.Key == "" {
if key.Name == "" {
return Key{}, ErrInvalidDetail
}

Expand Down Expand Up @@ -138,7 +138,7 @@ func (s Service) CreateKey(ctx context.Context, key Key) (Key, error) {
}

func (s Service) Upsert(ctx context.Context, sd ServiceData) (ServiceData, error) {
if sd.Key.Key == "" {
if sd.Key.Name == "" {
return ServiceData{}, ErrInvalidDetail
}

Expand Down
6 changes: 3 additions & 3 deletions core/servicedata/servicedata.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type Key struct {
URN string
ProjectID string
ProjectSlug string
Key string
Name string
Description string
ResourceID string
}
Expand All @@ -34,7 +34,7 @@ type ServiceData struct {
NamespaceID string
EntityID string
Key Key
Value string
Value any
}

type Filter struct {
Expand All @@ -46,5 +46,5 @@ type Filter struct {
}

func (key Key) CreateURN() string {
return fmt.Sprintf("%s:servicedata_key:%s", key.ProjectSlug, key.Key)
return fmt.Sprintf("%s:servicedata_key:%s", key.ProjectSlug, key.Name)
}
8 changes: 5 additions & 3 deletions core/user/filter.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package user

type Filter struct {
Limit int32
Page int32
Keyword string
Limit int32
Page int32
Keyword string
Project string
ServiceDataKeyResourceIds []string
}
94 changes: 74 additions & 20 deletions internal/api/v1beta1/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,28 @@ func (h Handler) ListGroups(ctx context.Context, request *shieldv1beta1.ListGrou

var groups []*shieldv1beta1.Group

currentUser, err := h.userService.FetchCurrentUser(ctx)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

servicedataKeyResourceIds, err := h.relationService.LookupResources(ctx, schema.ServiceDataKeyNamespace, schema.ViewPermission, schema.UserPrincipal, currentUser.ID)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

prj, err := h.projectService.Get(ctx, h.serviceDataConfig.DefaultServiceDataProject)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

groupList, err := h.groupService.List(ctx, group.Filter{
OrganizationID: request.GetOrgId(),
OrganizationID: request.GetOrgId(),
Project: prj.ID,
ServicedataKeyResourceIds: servicedataKeyResourceIds,
})
if err != nil {
logger.Error(err.Error())
Expand All @@ -73,6 +93,17 @@ func (h Handler) CreateGroup(ctx context.Context, request *shieldv1beta1.CreateG
return nil, grpcBadBodyError
}

currentUserEmail, ok := user.GetEmailFromContext(ctx)
mabdh marked this conversation as resolved.
Show resolved Hide resolved
if !ok {
return nil, grpcUnauthenticated
}

currentUserEmail = strings.TrimSpace(currentUserEmail)
if currentUserEmail == "" {
logger.Error(ErrEmptyEmailID.Error())
return nil, grpcUnauthenticated
}

metaDataMap, err := metadata.Build(request.GetBody().GetMetadata().AsMap())
if err != nil {
logger.Error(err.Error())
Expand All @@ -83,7 +114,7 @@ func (h Handler) CreateGroup(ctx context.Context, request *shieldv1beta1.CreateG
Name: request.GetBody().GetName(),
Slug: request.GetBody().GetSlug(),
OrganizationID: request.GetBody().GetOrgId(),
Metadata: metaDataMap,
Metadata: nil,
}

if strings.TrimSpace(grp.Slug) == "" {
Expand All @@ -106,21 +137,44 @@ func (h Handler) CreateGroup(ctx context.Context, request *shieldv1beta1.CreateG
}
}

metaData, err := newGroup.Metadata.ToStructPB()
serviceDataMap := map[string]any{}
for k, v := range metaDataMap {
serviceDataResp, err := h.serviceDataService.Upsert(ctx, servicedata.ServiceData{
EntityID: newGroup.ID,
NamespaceID: groupNamespaceID,
Key: servicedata.Key{
Name: k,
ProjectID: h.serviceDataConfig.DefaultServiceDataProject,
},
Value: v,
})
if err != nil {
logger.Error(err.Error())

switch {
case errors.Is(err, user.ErrInvalidEmail), errors.Is(err, user.ErrMissingEmail):
return nil, grpcUnauthenticated
case errors.Is(err, project.ErrNotExist), errors.Is(err, servicedata.ErrInvalidDetail),
errors.Is(err, relation.ErrInvalidDetail), errors.Is(err, servicedata.ErrNotExist):
return nil, grpcBadBodyError
case errors.Is(err, errorsPkg.ErrForbidden):
return nil, status.Error(codes.PermissionDenied, fmt.Sprintf("you are not authorized to update %s key", k))
default:
return nil, grpcInternalServerError
}
}
serviceDataMap[serviceDataResp.Key.Name] = serviceDataResp.Value
}

newGroup.Metadata = metaDataMap

groupPB, err := transformGroupToPB(newGroup)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
return nil, ErrInternalServer
}

return &shieldv1beta1.CreateGroupResponse{Group: &shieldv1beta1.Group{
Id: newGroup.ID,
Name: newGroup.Name,
Slug: newGroup.Slug,
OrgId: newGroup.OrganizationID,
Metadata: metaData,
CreatedAt: timestamppb.New(newGroup.CreatedAt),
UpdatedAt: timestamppb.New(newGroup.UpdatedAt),
}}, nil
return &shieldv1beta1.CreateGroupResponse{Group: &groupPB}, nil
}

func (h Handler) GetGroup(ctx context.Context, request *shieldv1beta1.GetGroupRequest) (*shieldv1beta1.GetGroupResponse, error) {
Expand Down Expand Up @@ -157,7 +211,7 @@ func (h Handler) GetGroup(ctx context.Context, request *shieldv1beta1.GetGroupRe
} else {
metadata := map[string]any{}
for _, sd := range groupSD {
metadata[sd.Key.Key] = sd.Value
metadata[sd.Key.Name] = sd.Value
}
fetchedGroup.Metadata = metadata
}
Expand Down Expand Up @@ -190,14 +244,14 @@ func (h Handler) UpdateGroup(ctx context.Context, request *shieldv1beta1.UpdateG
Name: request.GetBody().GetName(),
Slug: request.GetBody().GetSlug(),
OrganizationID: request.GetBody().GetOrgId(),
Metadata: metaDataMap,
Metadata: nil,
})
} else {
updatedGroup, err = h.groupService.Update(ctx, group.Group{
Name: request.GetBody().GetName(),
Slug: request.GetId(),
OrganizationID: request.GetBody().GetOrgId(),
Metadata: metaDataMap,
Metadata: nil,
})
}
if err != nil {
Expand Down Expand Up @@ -227,10 +281,10 @@ func (h Handler) UpdateGroup(ctx context.Context, request *shieldv1beta1.UpdateG
EntityID: updatedGroup.ID,
NamespaceID: groupNamespaceID,
Key: servicedata.Key{
Key: k,
Name: k,
ProjectID: h.serviceDataConfig.DefaultServiceDataProject,
},
Value: v.(string),
Value: v,
})
if err != nil {
logger.Error(err.Error())
Expand All @@ -247,11 +301,11 @@ func (h Handler) UpdateGroup(ctx context.Context, request *shieldv1beta1.UpdateG
return nil, grpcInternalServerError
}
}
serviceDataMap[serviceDataResp.Key.Key] = serviceDataResp.Value
serviceDataMap[serviceDataResp.Key.Name] = serviceDataResp.Value
}

//Note: this would return only the keys that are updated in the current request
updatedGroup.Metadata = serviceDataMap
updatedGroup.Metadata = metaDataMap

groupPB, err := transformGroupToPB(updatedGroup)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/api/v1beta1/relation.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type RelationService interface {
List(ctx context.Context) ([]relation.RelationV2, error)
DeleteV2(ctx context.Context, rel relation.RelationV2) error
GetRelationByFields(ctx context.Context, rel relation.RelationV2) (relation.RelationV2, error)
LookupResources(ctx context.Context, resourceType, permission, subjectType, subjectID string) ([]string, error)
}

var grpcRelationNotFoundErr = status.Errorf(codes.NotFound, "relation doesn't exist")
Expand Down
60 changes: 41 additions & 19 deletions internal/api/v1beta1/servicedata.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (h Handler) CreateServiceDataKey(ctx context.Context, request *shieldv1beta

keyResp, err := h.serviceDataService.CreateKey(ctx, servicedata.Key{
ProjectID: requestBody.GetProject(),
Key: requestBody.GetKey(),
Name: requestBody.GetKey(),
Description: requestBody.GetDescription(),
})
if err != nil {
Expand Down Expand Up @@ -87,7 +87,13 @@ func (h Handler) UpsertUserServiceData(ctx context.Context, request *shieldv1bet
return nil, grpcBadBodyError
}

if len(requestBody.Data) > h.serviceDataConfig.MaxUpsert {
data := requestBody.GetData()
if data == nil {
return nil, grpcBadBodyError
}
sdMap := data.AsMap()

if len(sdMap) > h.serviceDataConfig.MaxUpsert {
return nil, grpcBadBodyError
}

Expand All @@ -104,13 +110,13 @@ func (h Handler) UpsertUserServiceData(ctx context.Context, request *shieldv1bet
return nil, grpcInternalServerError
}
}
serviceDataMap := map[string]string{}
for k, v := range requestBody.Data {
serviceDataMap := map[string]any{}
for k, v := range sdMap {
serviceDataResp, err := h.serviceDataService.Upsert(ctx, servicedata.ServiceData{
EntityID: userEntity.ID,
NamespaceID: userNamespaceID,
Key: servicedata.Key{
Key: k,
Name: k,
ProjectID: requestBody.Project,
},
Value: v,
Expand All @@ -128,11 +134,16 @@ func (h Handler) UpsertUserServiceData(ctx context.Context, request *shieldv1bet
return nil, grpcInternalServerError
}
}
serviceDataMap[serviceDataResp.Key.Key] = serviceDataResp.Value
serviceDataMap[serviceDataResp.Key.Name] = serviceDataResp.Value
}

serviceDataMapPB, err := structpb.NewStruct(serviceDataMap)
if err != nil {
return nil, grpcInternalServerError
}

return &shieldv1beta1.UpsertUserServiceDataResponse{
Data: serviceDataMap,
Data: serviceDataMapPB,
}, nil
}

Expand All @@ -148,7 +159,13 @@ func (h Handler) UpsertGroupServiceData(ctx context.Context, request *shieldv1be
return nil, grpcBadBodyError
}

if len(requestBody.Data) > h.serviceDataConfig.MaxUpsert {
data := requestBody.GetData()
if data == nil {
return nil, grpcBadBodyError
}
sdMap := data.AsMap()

if len(sdMap) > h.serviceDataConfig.MaxUpsert {
return nil, grpcBadBodyError
}

Expand All @@ -165,13 +182,13 @@ func (h Handler) UpsertGroupServiceData(ctx context.Context, request *shieldv1be
return nil, grpcInternalServerError
}
}
serviceDataMap := map[string]string{}
for k, v := range requestBody.Data {
serviceDataMap := map[string]any{}
for k, v := range sdMap {
serviceDataResp, err := h.serviceDataService.Upsert(ctx, servicedata.ServiceData{
EntityID: groupEntity.ID,
NamespaceID: groupNamespaceID,
Key: servicedata.Key{
Key: k,
Name: k,
ProjectID: requestBody.Project,
},
Value: v,
Expand All @@ -189,11 +206,16 @@ func (h Handler) UpsertGroupServiceData(ctx context.Context, request *shieldv1be
return nil, grpcInternalServerError
}
}
serviceDataMap[serviceDataResp.Key.Key] = serviceDataResp.Value
serviceDataMap[serviceDataResp.Key.Name] = serviceDataResp.Value
}

serviceDataMapPB, err := structpb.NewStruct(serviceDataMap)
if err != nil {
return nil, grpcInternalServerError
}

return &shieldv1beta1.UpsertGroupServiceDataResponse{
Data: serviceDataMap,
Data: serviceDataMapPB,
}, nil
}

Expand Down Expand Up @@ -313,7 +335,7 @@ func transformServiceDataKeyToPB(from servicedata.Key) (shieldv1beta1.ServiceDat
}

func transformServiceDataListToPB(from []servicedata.ServiceData) (*structpb.Struct, error) {
data := map[string]map[string]map[string]string{}
data := map[string]map[string]map[string]any{}

for _, sd := range from {
prjKey := fmt.Sprintf("%s:%s", projectNamespaceID, sd.Key.ProjectID)
Expand All @@ -322,15 +344,15 @@ func transformServiceDataListToPB(from []servicedata.ServiceData) (*structpb.Str
if ok {
ent, ok := prj[entKey]
if ok {
ent[sd.Key.Key] = sd.Value
ent[sd.Key.Name] = sd.Value
} else {
prj[entKey] = map[string]string{
sd.Key.Key: sd.Value,
prj[entKey] = map[string]any{
sd.Key.Name: sd.Value,
}
}
} else {
kv := map[string]string{sd.Key.Key: sd.Value}
data[prjKey] = map[string]map[string]string{
kv := map[string]any{sd.Key.Name: sd.Value}
data[prjKey] = map[string]map[string]any{
entKey: kv,
}
}
Expand Down
Loading
Loading