Skip to content

Commit

Permalink
feat: servicedata (#71)
Browse files Browse the repository at this point in the history
* feat: user service data to serve metadata

* fix: should not return error if user email is missing

* chore: remove unwanted imports

* feat: get group metadata from servicedata

* feat: update APIs to use servicedata (#74)

* feat: update user API to use servicedata

* feat: update group metadata using servicedata service

* refactor: user servicedata service to serve metadata (#82)

* feat: use servicedata service to serve metadata

* feat: change value to jsonb

* refactor

* fix: e2e-test, user, group and servicedat tests

* test: fix

* test: fix

* test: fix

* lint: fix

* fix: field name

* lint: format

* fix: check permission on keys before create/update

* lint: formatting

* fix: check permission on keys before create/update

* refactor: change field name

* fix: add consistency to lookup resource

* feat: make servicedata key public (#86)

* feat: make servicedata key public

* fix: schema generator test

* test: spicedb image tab

* test: fix image repo

* test: fix image version

* test: fix command

* test: remove command flag

* test: add e2e-tests

* refactor: wildcard role check

* test: fix

* test: fix

* test: fix

* test: fix wrong response

* fix: self API

* test

* test

* test: update create group test

* test: update update group test
  • Loading branch information
ishanarya0 authored Jul 18, 2024
1 parent 1ba6c1e commit 7986573
Show file tree
Hide file tree
Showing 54 changed files with 2,140 additions and 1,061 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
ports:
- "4000:80"
spicedb:
image: quay.io/authzed/spicedb:v1.0.0
image: authzed/spicedb:v1.32.0
ports:
- "8080:8080"
- "50051:50051"
Expand Down
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
2 changes: 1 addition & 1 deletion cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func BuildAPIDependencies(
serviceDataRepository := postgres.NewServiceDataRepository(dbc)
serviceDataService := servicedata.NewService(logger, serviceDataRepository, resourceService, relationService, projectService, userService, activityService)

relationAdapter := adapter.NewRelation(groupService, userService, relationService)
relationAdapter := adapter.NewRelation(groupService, userService, relationService, roleService)

dependencies := api.Deps{
OrgService: organizationService,
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
ProjectID string
ServicedataKeyResourceIDs []string
}
15 changes: 10 additions & 5 deletions core/servicedata/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/goto/shield/core/user"
"github.com/goto/shield/internal/schema"
"github.com/goto/shield/pkg/db"
"github.com/goto/shield/pkg/errors"
)

const (
Expand Down Expand Up @@ -75,7 +76,7 @@ func NewService(logger log.Logger, repository Repository, resourceService Resour

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 All @@ -94,7 +95,7 @@ func (s Service) CreateKey(ctx context.Context, key Key) (Key, error) {
key.ProjectSlug = prj.Slug

// create URN
key.URN = key.CreateURN()
key.URN = CreateURN(key.ProjectSlug, key.Name)

// Transaction for postgres repository
// TODO find way to use transaction for spicedb
Expand Down Expand Up @@ -159,8 +160,12 @@ func (s Service) CreateKey(ctx context.Context, key Key) (Key, error) {
return createdServiceDataKey, nil
}

func (s Service) GetKeyByURN(ctx context.Context, urn string) (Key, error) {
return s.repository.GetKeyByURN(ctx, urn)
}

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

Expand All @@ -175,7 +180,7 @@ func (s Service) Upsert(ctx context.Context, sd ServiceData) (ServiceData, error
}
sd.Key.ProjectSlug = prj.Slug

sd.Key.URN = sd.Key.CreateURN()
sd.Key.URN = CreateURN(sd.Key.ProjectSlug, sd.Key.Name)

sd.Key, err = s.repository.GetKeyByURN(ctx, sd.Key.URN)
if err != nil {
Expand All @@ -188,7 +193,7 @@ func (s Service) Upsert(ctx context.Context, sd ServiceData) (ServiceData, error
return ServiceData{}, err
}
if !permission {
return ServiceData{}, user.ErrInvalidEmail
return ServiceData{}, errors.ErrForbidden
}

returnedServiceData, err := s.repository.Upsert(ctx, sd)
Expand Down
18 changes: 10 additions & 8 deletions core/servicedata/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import (
"github.com/goto/shield/core/servicedata/mocks"
"github.com/goto/shield/core/user"
"github.com/goto/shield/internal/schema"
errorsPkg "github.com/goto/shield/pkg/errors"
"github.com/goto/shield/pkg/logger"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
Expand All @@ -30,21 +32,21 @@ var (
testProjectSlug = "test-project-slug"
testKey = servicedata.Key{
ProjectID: "test-project-slug",
Key: "test-key",
Name: "test-key",
Description: "test key no 01",
}
testCreateKey = servicedata.Key{
URN: "test-project-slug:servicedata_key:test-key",
ProjectID: testProjectID,
ProjectSlug: testProjectSlug,
Key: "test-key",
Name: "test-key",
Description: "test key no 01",
ResourceID: testResourceID,
}
testCreatedKey = servicedata.Key{
URN: "test-project-slug:servicedata_key:test-key",
ProjectID: testProjectID,
Key: "test-key",
Name: "test-key",
Description: "test key no 01",
ResourceID: testResourceID,
}
Expand Down Expand Up @@ -131,7 +133,7 @@ func TestService_CreateKey(t *testing.T) {
name: "CreateKeyEmpty",
key: servicedata.Key{
ProjectID: testKey.ProjectID,
Key: "",
Name: "",
Description: testKey.Description,
},
setup: func(t *testing.T) *servicedata.Service {
Expand Down Expand Up @@ -183,7 +185,7 @@ func TestService_CreateKey(t *testing.T) {
name: "CreateKeyInvalidProjectID",
key: servicedata.Key{
ProjectID: "invalid-test-project-slug",
Key: testKey.Key,
Name: testKey.Name,
Description: testKey.Description,
},
email: "[email protected]",
Expand Down Expand Up @@ -366,7 +368,7 @@ func TestService_Upsert(t *testing.T) {
name: "UpsertKeyEmpty",
data: servicedata.ServiceData{
Key: servicedata.Key{
Key: "",
Name: "",
},
},
setup: func(t *testing.T) *servicedata.Service {
Expand Down Expand Up @@ -402,7 +404,7 @@ func TestService_Upsert(t *testing.T) {
name: "UpsertInvalidProjectID",
data: servicedata.ServiceData{
Key: servicedata.Key{
Key: testKey.Key,
Name: testKey.Name,
ProjectID: "invalid-test-project-slug",
},
},
Expand Down Expand Up @@ -480,7 +482,7 @@ func TestService_Upsert(t *testing.T) {
testResourceID, action.Action{ID: "edit"}).Return(false, nil)
return servicedata.NewService(testLogger, repository, resourceService, relationService, projectService, userService, activityService)
},
wantErr: user.ErrInvalidEmail,
wantErr: errorsPkg.ErrForbidden,
},
{
name: "UpsertErr",
Expand Down
10 changes: 5 additions & 5 deletions core/servicedata/servicedata.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Key struct {
URN string
ProjectID string
ProjectSlug string
Key string
Name string
Description string
ResourceID string
}
Expand All @@ -36,7 +36,7 @@ type ServiceData struct {
NamespaceID string
EntityID string
Key Key
Value string
Value any
}

type KeyLogData struct {
Expand All @@ -55,16 +55,16 @@ type Filter struct {
Project string
}

func (key Key) CreateURN() string {
return fmt.Sprintf("%s:servicedata_key:%s", key.ProjectSlug, key.Key)
func CreateURN(projectSlug, keyName string) string {
return fmt.Sprintf("%s:servicedata_key:%s", projectSlug, keyName)
}

func (key Key) ToKeyLogData() KeyLogData {
return KeyLogData{
Entity: auditEntityServiceDataKey,
URN: key.URN,
ProjectSlug: key.ProjectSlug,
Key: key.Key,
Key: key.Name,
Description: key.Description,
}
}
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
ProjectID string
ServiceDataKeyResourceIds []string
}
27 changes: 26 additions & 1 deletion internal/adapter/relation.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,36 @@ package adapter
import (
"context"
"fmt"
"slices"

"github.com/goto/shield/core/group"
"github.com/goto/shield/core/relation"
"github.com/goto/shield/core/role"
"github.com/goto/shield/core/user"
"github.com/goto/shield/internal/schema"
"github.com/goto/shield/pkg/uuid"
)

const WILDCARD = "*"

type Relation struct {
groupService *group.Service
userService *user.Service
relationService *relation.Service
roleService *role.Service
}

func NewRelation(
groupService *group.Service,
userService *user.Service,
relationService *relation.Service,
roleService *role.Service,
) *Relation {
return &Relation{
groupService: groupService,
userService: userService,
relationService: relationService,
roleService: roleService,
}
}

Expand All @@ -36,7 +43,12 @@ func (a Relation) TransformRelation(ctx context.Context, rlt relation.RelationV2
if rel.Subject.Namespace == schema.UserPrincipal || rel.Subject.Namespace == "user" {
userID := rel.Subject.ID

if !uuid.IsValid(userID) {
if userID == WILDCARD {
err := a.isWildCardAllowed(ctx, rel)
if err != nil {
return relation.RelationV2{}, err
}
} else if !uuid.IsValid(userID) {
fetchedUser, err := a.userService.GetByEmail(ctx, rel.Subject.ID)
if err != nil {
return relation.RelationV2{}, fmt.Errorf("%w: %s", relation.ErrFetchingUser, err.Error())
Expand Down Expand Up @@ -79,3 +91,16 @@ func (a Relation) TransformRelation(ctx context.Context, rlt relation.RelationV2

return rel, nil
}

func (a Relation) isWildCardAllowed(ctx context.Context, rlt relation.RelationV2) error {
roleID := rlt.Object.NamespaceID + ":" + rlt.Subject.RoleID
role, err := a.roleService.Get(ctx, roleID)
if err != nil {
return fmt.Errorf("error fetching role: %s", err.Error())
}
if !slices.Contains(role.Types, schema.UserPrincipalWildcard) {
return fmt.Errorf("%s does not allow wildcard for subject %s", rlt.Object.NamespaceID, rlt.Subject.Namespace)
}

return nil
}
Loading

0 comments on commit 7986573

Please sign in to comment.