Skip to content

Commit 7986573

Browse files
authored
feat: servicedata (#71)
* 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
1 parent 1ba6c1e commit 7986573

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2140
-1061
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
ports:
3737
- "4000:80"
3838
spicedb:
39-
image: quay.io/authzed/spicedb:v1.0.0
39+
image: authzed/spicedb:v1.32.0
4040
ports:
4141
- "8080:8080"
4242
- "50051:50051"

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ GOVERSION := $(shell go version | cut -d ' ' -f 3 | cut -d '.' -f 2)
22

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

77
install:
88
@echo "Clean up imports..."

cmd/serve.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func BuildAPIDependencies(
243243
serviceDataRepository := postgres.NewServiceDataRepository(dbc)
244244
serviceDataService := servicedata.NewService(logger, serviceDataRepository, resourceService, relationService, projectService, userService, activityService)
245245

246-
relationAdapter := adapter.NewRelation(groupService, userService, relationService)
246+
relationAdapter := adapter.NewRelation(groupService, userService, relationService, roleService)
247247

248248
dependencies := api.Deps{
249249
OrgService: organizationService,

core/group/filter.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package group
22

33
type Filter struct {
4-
OrganizationID string
4+
OrganizationID string
5+
ProjectID string
6+
ServicedataKeyResourceIDs []string
57
}

core/servicedata/service.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/goto/shield/core/user"
1616
"github.com/goto/shield/internal/schema"
1717
"github.com/goto/shield/pkg/db"
18+
"github.com/goto/shield/pkg/errors"
1819
)
1920

2021
const (
@@ -75,7 +76,7 @@ func NewService(logger log.Logger, repository Repository, resourceService Resour
7576

7677
func (s Service) CreateKey(ctx context.Context, key Key) (Key, error) {
7778
// check if key contains ':'
78-
if key.Key == "" {
79+
if key.Name == "" {
7980
return Key{}, ErrInvalidDetail
8081
}
8182

@@ -94,7 +95,7 @@ func (s Service) CreateKey(ctx context.Context, key Key) (Key, error) {
9495
key.ProjectSlug = prj.Slug
9596

9697
// create URN
97-
key.URN = key.CreateURN()
98+
key.URN = CreateURN(key.ProjectSlug, key.Name)
9899

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

163+
func (s Service) GetKeyByURN(ctx context.Context, urn string) (Key, error) {
164+
return s.repository.GetKeyByURN(ctx, urn)
165+
}
166+
162167
func (s Service) Upsert(ctx context.Context, sd ServiceData) (ServiceData, error) {
163-
if sd.Key.Key == "" {
168+
if sd.Key.Name == "" {
164169
return ServiceData{}, ErrInvalidDetail
165170
}
166171

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

178-
sd.Key.URN = sd.Key.CreateURN()
183+
sd.Key.URN = CreateURN(sd.Key.ProjectSlug, sd.Key.Name)
179184

180185
sd.Key, err = s.repository.GetKeyByURN(ctx, sd.Key.URN)
181186
if err != nil {
@@ -188,7 +193,7 @@ func (s Service) Upsert(ctx context.Context, sd ServiceData) (ServiceData, error
188193
return ServiceData{}, err
189194
}
190195
if !permission {
191-
return ServiceData{}, user.ErrInvalidEmail
196+
return ServiceData{}, errors.ErrForbidden
192197
}
193198

194199
returnedServiceData, err := s.repository.Upsert(ctx, sd)

core/servicedata/service_test.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import (
1414
"github.com/goto/shield/core/servicedata/mocks"
1515
"github.com/goto/shield/core/user"
1616
"github.com/goto/shield/internal/schema"
17+
errorsPkg "github.com/goto/shield/pkg/errors"
1718
"github.com/goto/shield/pkg/logger"
19+
1820
"github.com/stretchr/testify/assert"
1921
"github.com/stretchr/testify/mock"
2022
)
@@ -30,21 +32,21 @@ var (
3032
testProjectSlug = "test-project-slug"
3133
testKey = servicedata.Key{
3234
ProjectID: "test-project-slug",
33-
Key: "test-key",
35+
Name: "test-key",
3436
Description: "test key no 01",
3537
}
3638
testCreateKey = servicedata.Key{
3739
URN: "test-project-slug:servicedata_key:test-key",
3840
ProjectID: testProjectID,
3941
ProjectSlug: testProjectSlug,
40-
Key: "test-key",
42+
Name: "test-key",
4143
Description: "test key no 01",
4244
ResourceID: testResourceID,
4345
}
4446
testCreatedKey = servicedata.Key{
4547
URN: "test-project-slug:servicedata_key:test-key",
4648
ProjectID: testProjectID,
47-
Key: "test-key",
49+
Name: "test-key",
4850
Description: "test key no 01",
4951
ResourceID: testResourceID,
5052
}
@@ -131,7 +133,7 @@ func TestService_CreateKey(t *testing.T) {
131133
name: "CreateKeyEmpty",
132134
key: servicedata.Key{
133135
ProjectID: testKey.ProjectID,
134-
Key: "",
136+
Name: "",
135137
Description: testKey.Description,
136138
},
137139
setup: func(t *testing.T) *servicedata.Service {
@@ -183,7 +185,7 @@ func TestService_CreateKey(t *testing.T) {
183185
name: "CreateKeyInvalidProjectID",
184186
key: servicedata.Key{
185187
ProjectID: "invalid-test-project-slug",
186-
Key: testKey.Key,
188+
Name: testKey.Name,
187189
Description: testKey.Description,
188190
},
189191
@@ -366,7 +368,7 @@ func TestService_Upsert(t *testing.T) {
366368
name: "UpsertKeyEmpty",
367369
data: servicedata.ServiceData{
368370
Key: servicedata.Key{
369-
Key: "",
371+
Name: "",
370372
},
371373
},
372374
setup: func(t *testing.T) *servicedata.Service {
@@ -402,7 +404,7 @@ func TestService_Upsert(t *testing.T) {
402404
name: "UpsertInvalidProjectID",
403405
data: servicedata.ServiceData{
404406
Key: servicedata.Key{
405-
Key: testKey.Key,
407+
Name: testKey.Name,
406408
ProjectID: "invalid-test-project-slug",
407409
},
408410
},
@@ -480,7 +482,7 @@ func TestService_Upsert(t *testing.T) {
480482
testResourceID, action.Action{ID: "edit"}).Return(false, nil)
481483
return servicedata.NewService(testLogger, repository, resourceService, relationService, projectService, userService, activityService)
482484
},
483-
wantErr: user.ErrInvalidEmail,
485+
wantErr: errorsPkg.ErrForbidden,
484486
},
485487
{
486488
name: "UpsertErr",

core/servicedata/servicedata.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type Key struct {
2626
URN string
2727
ProjectID string
2828
ProjectSlug string
29-
Key string
29+
Name string
3030
Description string
3131
ResourceID string
3232
}
@@ -36,7 +36,7 @@ type ServiceData struct {
3636
NamespaceID string
3737
EntityID string
3838
Key Key
39-
Value string
39+
Value any
4040
}
4141

4242
type KeyLogData struct {
@@ -55,16 +55,16 @@ type Filter struct {
5555
Project string
5656
}
5757

58-
func (key Key) CreateURN() string {
59-
return fmt.Sprintf("%s:servicedata_key:%s", key.ProjectSlug, key.Key)
58+
func CreateURN(projectSlug, keyName string) string {
59+
return fmt.Sprintf("%s:servicedata_key:%s", projectSlug, keyName)
6060
}
6161

6262
func (key Key) ToKeyLogData() KeyLogData {
6363
return KeyLogData{
6464
Entity: auditEntityServiceDataKey,
6565
URN: key.URN,
6666
ProjectSlug: key.ProjectSlug,
67-
Key: key.Key,
67+
Key: key.Name,
6868
Description: key.Description,
6969
}
7070
}

core/user/filter.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package user
22

33
type Filter struct {
4-
Limit int32
5-
Page int32
6-
Keyword string
4+
Limit int32
5+
Page int32
6+
Keyword string
7+
ProjectID string
8+
ServiceDataKeyResourceIds []string
79
}

internal/adapter/relation.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,36 @@ package adapter
33
import (
44
"context"
55
"fmt"
6+
"slices"
67

78
"github.com/goto/shield/core/group"
89
"github.com/goto/shield/core/relation"
10+
"github.com/goto/shield/core/role"
911
"github.com/goto/shield/core/user"
1012
"github.com/goto/shield/internal/schema"
1113
"github.com/goto/shield/pkg/uuid"
1214
)
1315

16+
const WILDCARD = "*"
17+
1418
type Relation struct {
1519
groupService *group.Service
1620
userService *user.Service
1721
relationService *relation.Service
22+
roleService *role.Service
1823
}
1924

2025
func NewRelation(
2126
groupService *group.Service,
2227
userService *user.Service,
2328
relationService *relation.Service,
29+
roleService *role.Service,
2430
) *Relation {
2531
return &Relation{
2632
groupService: groupService,
2733
userService: userService,
2834
relationService: relationService,
35+
roleService: roleService,
2936
}
3037
}
3138

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

39-
if !uuid.IsValid(userID) {
46+
if userID == WILDCARD {
47+
err := a.isWildCardAllowed(ctx, rel)
48+
if err != nil {
49+
return relation.RelationV2{}, err
50+
}
51+
} else if !uuid.IsValid(userID) {
4052
fetchedUser, err := a.userService.GetByEmail(ctx, rel.Subject.ID)
4153
if err != nil {
4254
return relation.RelationV2{}, fmt.Errorf("%w: %s", relation.ErrFetchingUser, err.Error())
@@ -79,3 +91,16 @@ func (a Relation) TransformRelation(ctx context.Context, rlt relation.RelationV2
7991

8092
return rel, nil
8193
}
94+
95+
func (a Relation) isWildCardAllowed(ctx context.Context, rlt relation.RelationV2) error {
96+
roleID := rlt.Object.NamespaceID + ":" + rlt.Subject.RoleID
97+
role, err := a.roleService.Get(ctx, roleID)
98+
if err != nil {
99+
return fmt.Errorf("error fetching role: %s", err.Error())
100+
}
101+
if !slices.Contains(role.Types, schema.UserPrincipalWildcard) {
102+
return fmt.Errorf("%s does not allow wildcard for subject %s", rlt.Object.NamespaceID, rlt.Subject.Namespace)
103+
}
104+
105+
return nil
106+
}

0 commit comments

Comments
 (0)