diff --git a/go.mod b/go.mod index db9f047..868caa5 100644 --- a/go.mod +++ b/go.mod @@ -55,6 +55,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/cel-go v0.21.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/subcommands v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect @@ -82,11 +83,13 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect + golang.org/x/mod v0.20.0 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.24.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 545e876..21d8d22 100644 --- a/go.sum +++ b/go.sum @@ -105,6 +105,7 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -238,6 +239,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -317,6 +320,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/data/LocalSpiceDbContainer.go b/internal/data/LocalSpiceDbContainer.go index b3a3107..eacf733 100644 --- a/internal/data/LocalSpiceDbContainer.go +++ b/internal/data/LocalSpiceDbContainer.go @@ -201,7 +201,7 @@ func (l *LocalSpiceDbContainer) Close() { } // CheckForRelationship returns true if the given subject has the given relationship to the given resource, otherwise false -func CheckForRelationship(client *authzed.Client, subjectID string, subjectType string, subjectRelationship string, relationship string, resourceType string, resourceID string) bool { +func CheckForRelationship(client *authzed.Client, resourceType string, resourceID string, relationship string, subjectType string, subjectID string, subjectRelationship string) bool { ctx := context.TODO() resp, err := client.ReadRelationships(ctx, &v1.ReadRelationshipsRequest{ Consistency: &v1.Consistency{Requirement: &v1.Consistency_FullyConsistent{FullyConsistent: true}}, diff --git a/internal/data/spicedb.go b/internal/data/spicedb.go index 9d53836..c846587 100644 --- a/internal/data/spicedb.go +++ b/internal/data/spicedb.go @@ -16,6 +16,7 @@ import ( v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/authzed-go/v1" "github.com/authzed/grpcutil" + kerrors "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/log" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -240,8 +241,14 @@ func (s *SpiceDbRepository) ReadRelationships(ctx context.Context, filter *apiV1 } } + relationshipFilter, err := createSpiceDbRelationshipFilter(filter) + + if err != nil { + return nil, nil, kerrors.BadRequest("SpiceDb request validation", err.Error()).WithCause(err) + } + req := &v1.ReadRelationshipsRequest{ - RelationshipFilter: createSpiceDbRelationshipFilter(filter), + RelationshipFilter: relationshipFilter, OptionalLimit: limit, OptionalCursor: cursor, } @@ -297,9 +304,15 @@ func (s *SpiceDbRepository) ReadRelationships(ctx context.Context, filter *apiV1 } func (s *SpiceDbRepository) DeleteRelationships(ctx context.Context, filter *apiV1beta1.RelationTupleFilter) error { - req := &v1.DeleteRelationshipsRequest{RelationshipFilter: createSpiceDbRelationshipFilter(filter)} + relationshipFilter, err := createSpiceDbRelationshipFilter(filter) + + if err != nil { + return kerrors.BadRequest("SpiceDb request validation", err.Error()).WithCause(err) + } + + req := &v1.DeleteRelationshipsRequest{RelationshipFilter: relationshipFilter} - _, err := s.client.DeleteRelationships(ctx, req) + _, err = s.client.DeleteRelationships(ctx, req) // TODO: we have not specified an option in our API to allow partial deletions, so currently it's all or nothing if err != nil { @@ -362,29 +375,49 @@ func (s *SpiceDbRepository) IsBackendAvailable() error { return fmt.Errorf("error connecting to backend") } -func createSpiceDbRelationshipFilter(filter *apiV1beta1.RelationTupleFilter) *v1.RelationshipFilter { +func createSpiceDbRelationshipFilter(filter *apiV1beta1.RelationTupleFilter) (*v1.RelationshipFilter, error) { + // spicedb specific internal validation to reflect spicedb limitations whereby namespace and objectType must be both + // be set if either of them is set in a filter + if filter.GetResourceNamespace() != "" && filter.GetResourceType() == "" { + return nil, fmt.Errorf("due to a spicedb limitation, if resource namespace is specified then resource type must also be specified") + } + if filter.GetResourceNamespace() == "" && filter.GetResourceType() != "" { + return nil, fmt.Errorf("due to a spicedb limitation, if resource type is specified then resource namespace must also be specified") + } + + resourceType := &apiV1beta1.ObjectType{Namespace: filter.GetResourceNamespace(), Name: filter.GetResourceType()} spiceDbRelationshipFilter := &v1.RelationshipFilter{ - ResourceType: filter.GetResourceType(), + ResourceType: kesselTypeToSpiceDBType(resourceType), OptionalResourceId: filter.GetResourceId(), OptionalRelation: filter.GetRelation(), } if filter.GetSubjectFilter() != nil { - subjectFilter := &v1.SubjectFilter{ - SubjectType: filter.GetSubjectFilter().GetSubjectType(), - OptionalSubjectId: filter.GetSubjectFilter().GetSubjectId(), + subjectFilter := filter.GetSubjectFilter() + + if subjectFilter.GetSubjectNamespace() != "" && subjectFilter.GetSubjectType() == "" { + return nil, fmt.Errorf("due to a spicedb limitation, if subject namespace is specified in subjectFilter then subject type must also be specified") + } + if subjectFilter.GetSubjectNamespace() == "" && subjectFilter.GetSubjectType() != "" { + return nil, fmt.Errorf("due to a spicedb limitation, if subject type is specified in subjectFilter then subject namespace must also be specified") + } + + subjectType := &apiV1beta1.ObjectType{Namespace: subjectFilter.GetSubjectNamespace(), Name: subjectFilter.GetSubjectType()} + spiceDbSubjectFilter := &v1.SubjectFilter{ + SubjectType: kesselTypeToSpiceDBType(subjectType), + OptionalSubjectId: subjectFilter.GetSubjectId(), } - if filter.GetSubjectFilter().GetRelation() != "" { - subjectFilter.OptionalRelation = &v1.SubjectFilter_RelationFilter{ - Relation: filter.GetSubjectFilter().GetRelation(), + if subjectFilter.GetRelation() != "" { + spiceDbSubjectFilter.OptionalRelation = &v1.SubjectFilter_RelationFilter{ + Relation: subjectFilter.GetRelation(), } } - spiceDbRelationshipFilter.OptionalSubjectFilter = subjectFilter + spiceDbRelationshipFilter.OptionalSubjectFilter = spiceDbSubjectFilter } - return spiceDbRelationshipFilter + return spiceDbRelationshipFilter, nil } func spicedbTypeToKesselType(spicedbType string) *apiV1beta1.ObjectType { diff --git a/internal/data/spicedb_test.go b/internal/data/spicedb_test.go index 222030c..9cd7e2d 100644 --- a/internal/data/spicedb_test.go +++ b/internal/data/spicedb_test.go @@ -48,11 +48,11 @@ func TestCreateRelationship(t *testing.T) { spiceDbRepo, err := container.CreateSpiceDbRepository() assert.NoError(t, err) - preExisting := CheckForRelationship(spiceDbRepo.client, "bob", "rbac/user", "", "member", "rbac/group", "bob_club") + preExisting := CheckForRelationship(spiceDbRepo.client, "rbac/group", "bob_club", "member", "rbac/user", "bob", "") assert.False(t, preExisting) rels := []*apiV1beta1.Relationship{ - createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club"), + createRelationship("rbac", "group", "bob_club", "member", "rbac", "user", "bob", ""), } touch := biz.TouchSemantics(false) @@ -60,7 +60,7 @@ func TestCreateRelationship(t *testing.T) { err = spiceDbRepo.CreateRelationships(ctx, rels, touch) assert.NoError(t, err) - exists := CheckForRelationship(spiceDbRepo.client, "bob", "rbac/user", "", "member", "rbac/group", "bob_club") + exists := CheckForRelationship(spiceDbRepo.client, "rbac/group", "bob_club", "member", "rbac/user", "bob", "") assert.True(t, exists) } @@ -71,11 +71,11 @@ func TestSecondCreateRelationshipFailsWithTouchFalse(t *testing.T) { spiceDbRepo, err := container.CreateSpiceDbRepository() assert.NoError(t, err) - preExisting := CheckForRelationship(spiceDbRepo.client, "bob", "rbac/user", "", "member", "rbac/group", "bob_club") + preExisting := CheckForRelationship(spiceDbRepo.client, "rbac/group", "bob_club", "member", "rbac/user", "bob", "") assert.False(t, preExisting) rels := []*apiV1beta1.Relationship{ - createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club"), + createRelationship("rbac", "group", "bob_club", "member", "rbac", "user", "bob", ""), } touch := biz.TouchSemantics(false) @@ -87,7 +87,7 @@ func TestSecondCreateRelationshipFailsWithTouchFalse(t *testing.T) { assert.Error(t, err) assert.Equal(t, status.Convert(err).Code(), codes.AlreadyExists) - exists := CheckForRelationship(spiceDbRepo.client, "bob", "rbac/user", "", "member", "rbac/group", "bob_club") + exists := CheckForRelationship(spiceDbRepo.client, "rbac/group", "bob_club", "member", "rbac/user", "bob", "") assert.True(t, exists) } @@ -98,11 +98,11 @@ func TestSecondCreateRelationshipSucceedsWithTouchTrue(t *testing.T) { spiceDbRepo, err := container.CreateSpiceDbRepository() assert.NoError(t, err) - preExisting := CheckForRelationship(spiceDbRepo.client, "bob", "rbac/user", "", "member", "rbac/group", "bob_club") + preExisting := CheckForRelationship(spiceDbRepo.client, "rbac/group", "bob_club", "member", "rbac/user", "bob", "") assert.False(t, preExisting) rels := []*apiV1beta1.Relationship{ - createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club"), + createRelationship("rbac", "group", "bob_club", "member", "rbac", "user", "bob", ""), } touch := biz.TouchSemantics(false) @@ -115,7 +115,7 @@ func TestSecondCreateRelationshipSucceedsWithTouchTrue(t *testing.T) { err = spiceDbRepo.CreateRelationships(ctx, rels, touch) assert.NoError(t, err) - exists := CheckForRelationship(spiceDbRepo.client, "bob", "rbac/user", "", "member", "rbac/group", "bob_club") + exists := CheckForRelationship(spiceDbRepo.client, "rbac/group", "bob_club", "member", "rbac/user", "bob", "") assert.True(t, exists) } @@ -144,6 +144,44 @@ func TestIsBackendUnavailable(t *testing.T) { assert.Error(t, err) } +func TestDoesNotCreateRelationshipWithSlashInSubjectType(t *testing.T) { + t.Parallel() + + ctx := context.Background() + spiceDbRepo, err := container.CreateSpiceDbRepository() + assert.NoError(t, err) + + badSubjectType := "special/user" + + rels := []*apiV1beta1.Relationship{ + createRelationship("rbac", "group", "bob_club", "member", "rbac", badSubjectType, "bob", ""), + } + + touch := biz.TouchSemantics(false) + + err = spiceDbRepo.CreateRelationships(ctx, rels, touch) + assert.Error(t, err) +} + +func TestDoesNotCreateRelationshipWithSlashInObjectType(t *testing.T) { + t.Parallel() + + ctx := context.Background() + spiceDbRepo, err := container.CreateSpiceDbRepository() + assert.NoError(t, err) + + badResourceType := "my/group" + + rels := []*apiV1beta1.Relationship{ + createRelationship("rbac", badResourceType, "bob_club", "member", "rbac", "user", "bob", ""), + } + + touch := biz.TouchSemantics(false) + + err = spiceDbRepo.CreateRelationships(ctx, rels, touch) + assert.Error(t, err) +} + func TestCreateRelationshipFailsWithBadSubjectType(t *testing.T) { t.Parallel() @@ -151,10 +189,10 @@ func TestCreateRelationshipFailsWithBadSubjectType(t *testing.T) { spiceDbRepo, err := container.CreateSpiceDbRepository() assert.NoError(t, err) - badSubjectType := simple_type("not_a_user") + badSubjectType := "not_a_user" rels := []*apiV1beta1.Relationship{ - createRelationship("bob", badSubjectType, "", "member", simple_type("group"), "bob_club"), + createRelationship("rbac", "group", "bob_club", "member", "rbac", badSubjectType, "bob", ""), } touch := biz.TouchSemantics(false) @@ -163,7 +201,7 @@ func TestCreateRelationshipFailsWithBadSubjectType(t *testing.T) { assert.Error(t, err) assert.Equal(t, status.Convert(err).Code(), codes.FailedPrecondition) assert.Contains(t, err.Error(), - fmt.Sprintf("object definition `%s/%s` not found", badSubjectType.GetNamespace(), badSubjectType.GetName())) + fmt.Sprintf("object definition `%s/%s` not found", "rbac", badSubjectType)) } func TestCreateRelationshipFailsWithBadObjectType(t *testing.T) { @@ -173,10 +211,10 @@ func TestCreateRelationshipFailsWithBadObjectType(t *testing.T) { spiceDbRepo, err := container.CreateSpiceDbRepository() assert.NoError(t, err) - badObjectType := simple_type("not_an_object") + badObjectType := "not_an_object" rels := []*apiV1beta1.Relationship{ - createRelationship("bob", simple_type("user"), "", "member", badObjectType, "bob_club"), + createRelationship("rbac", badObjectType, "bob_club", "member", "rbac", "user", "bob", ""), } touch := biz.TouchSemantics(false) @@ -185,10 +223,122 @@ func TestCreateRelationshipFailsWithBadObjectType(t *testing.T) { assert.Error(t, err) assert.Equal(t, status.Convert(err).Code(), codes.FailedPrecondition) assert.Contains(t, err.Error(), - fmt.Sprintf("object definition `%s/%s` not found", badObjectType.GetNamespace(), badObjectType.GetName())) + fmt.Sprintf("object definition `%s/%s` not found", "rbac", badObjectType)) } +func TestSupportedNsTypeTupleFilterCombinationsInReadRelationships(t *testing.T) { + t.Parallel() + + ctx := context.Background() + spiceDbRepo, err := container.CreateSpiceDbRepository() + if !assert.NoError(t, err) { + return + } + + assert.NoError(t, err) + + _, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ + ResourceId: pointerize("bob_club"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), + SubjectFilter: &apiV1beta1.SubjectFilter{ + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), + }, + }, 0, "") + + assert.Error(t, err) + + _, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + Relation: pointerize("member"), + SubjectFilter: &apiV1beta1.SubjectFilter{ + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), + }, + }, 0, "") + + assert.Error(t, err) + + _, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), + SubjectFilter: &apiV1beta1.SubjectFilter{ + SubjectId: pointerize("bob"), + SubjectType: pointerize("user"), + }, + }, 0, "") + + assert.Error(t, err) + + _, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), + SubjectFilter: &apiV1beta1.SubjectFilter{ + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + }, + }, 0, "") + + assert.Error(t, err) + + _, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), + SubjectFilter: &apiV1beta1.SubjectFilter{ + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), + }, + }, 0, "") + + assert.NoError(t, err) + + _, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ + ResourceId: pointerize("bob_club"), + Relation: pointerize("member"), + SubjectFilter: &apiV1beta1.SubjectFilter{ + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), + }, + }, 0, "") + + assert.NoError(t, err) + + _, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), + SubjectFilter: &apiV1beta1.SubjectFilter{ + SubjectId: pointerize("bob"), + }, + }, 0, "") + + assert.NoError(t, err) + + _, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ + ResourceId: pointerize("bob_club"), + Relation: pointerize("member"), + SubjectFilter: &apiV1beta1.SubjectFilter{ + SubjectId: pointerize("bob"), + }, + }, 0, "") + + assert.NoError(t, err) +} + func TestWriteAndReadBackRelationships(t *testing.T) { t.Parallel() @@ -200,7 +350,7 @@ func TestWriteAndReadBackRelationships(t *testing.T) { assert.NoError(t, err) rels := []*apiV1beta1.Relationship{ - createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club"), + createRelationship("rbac", "group", "bob_club", "member", "rbac", "user", "bob", ""), } err = spiceDbRepo.CreateRelationships(ctx, rels, biz.TouchSemantics(true)) @@ -209,12 +359,14 @@ func TestWriteAndReadBackRelationships(t *testing.T) { } readRelChan, _, err := spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &apiV1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }, 0, "") @@ -237,7 +389,7 @@ func TestWriteReadBackDeleteAndReadBackRelationships(t *testing.T) { assert.NoError(t, err) rels := []*apiV1beta1.Relationship{ - createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club"), + createRelationship("rbac", "group", "bob_club", "member", "rbac", "user", "bob", ""), } err = spiceDbRepo.CreateRelationships(ctx, rels, biz.TouchSemantics(true)) @@ -246,12 +398,14 @@ func TestWriteReadBackDeleteAndReadBackRelationships(t *testing.T) { } readRelChan, _, err := spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &apiV1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }, 0, "") @@ -263,12 +417,14 @@ func TestWriteReadBackDeleteAndReadBackRelationships(t *testing.T) { assert.Equal(t, 1, len(readrels)) err = spiceDbRepo.DeleteRelationships(ctx, &apiV1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &apiV1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }) @@ -277,12 +433,14 @@ func TestWriteReadBackDeleteAndReadBackRelationships(t *testing.T) { } readRelChan, _, err = spiceDbRepo.ReadRelationships(ctx, &apiV1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &apiV1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }, 0, "") @@ -310,11 +468,11 @@ func TestSpiceDbRepository_CheckPermission(t *testing.T) { //role_binding:rb_test#subject@user:bob //role:rl1#view_the_thing@user:* rels := []*apiV1beta1.Relationship{ - createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club"), - createRelationship("rb_test", simple_type("role_binding"), "", "user_grant", simple_type("workspace"), "test"), - createRelationship("rl1", simple_type("role"), "", "granted", simple_type("role_binding"), "rb_test"), - createRelationship("bob", simple_type("user"), "", "subject", simple_type("role_binding"), "rb_test"), - createRelationship("*", simple_type("user"), "", "view_the_thing", simple_type("role"), "rl1"), + createRelationship("rbac", "group", "bob_club", "member", "rbac", "user", "bob", ""), + createRelationship("rbac", "workspace", "test", "user_grant", "rbac", "role_binding", "rb_test", ""), + createRelationship("rbac", "role_binding", "rb_test", "granted", "rbac", "role", "rl1", ""), + createRelationship("rbac", "role_binding", "rb_test", "subject", "rbac", "user", "bob", ""), + createRelationship("rbac", "role", "rl1", "view_the_thing", "rbac", "user", "*", ""), } err = spiceDbRepo.CreateRelationships(ctx, rels, biz.TouchSemantics(true)) @@ -324,14 +482,18 @@ func TestSpiceDbRepository_CheckPermission(t *testing.T) { subject := &apiV1beta1.SubjectReference{ Subject: &apiV1beta1.ObjectReference{ - Type: simple_type("user"), - Id: "bob", + Type: &apiV1beta1.ObjectType{ + Name: "user", Namespace: "rbac", + }, + Id: "bob", }, } resource := &apiV1beta1.ObjectReference{ - Type: simple_type("workspace"), - Id: "test", + Type: &apiV1beta1.ObjectType{ + Name: "workspace", Namespace: "rbac", + }, + Id: "test", } // zed permission check workspace:test view_the_thing user:bob --explain check := apiV1beta1.CheckRequest{ @@ -351,12 +513,14 @@ func TestSpiceDbRepository_CheckPermission(t *testing.T) { //Remove // role_binding:rb_test#subject@user:bob err = spiceDbRepo.DeleteRelationships(ctx, &apiV1beta1.RelationTupleFilter{ - ResourceId: pointerize("rb_test"), - ResourceType: pointerize("rbac/role_binding"), - Relation: pointerize("subject"), + ResourceId: pointerize("rb_test"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("role_binding"), + Relation: pointerize("subject"), SubjectFilter: &apiV1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }) if !assert.NoError(t, err) { @@ -380,19 +544,17 @@ func TestSpiceDbRepository_CheckPermission(t *testing.T) { assert.Equal(t, &checkResponsev2, resp2) } -func simple_type(typename string) *apiV1beta1.ObjectType { - return &apiV1beta1.ObjectType{Name: typename, Namespace: "rbac"} -} - func pointerize(value string) *string { //Used to turn string literals into pointers return &value } -func createRelationship(subjectId string, subjectType *apiV1beta1.ObjectType, subjectRelationship string, relationship string, objectType *apiV1beta1.ObjectType, objectId string) *apiV1beta1.Relationship { +func createRelationship(resourceNamespace string, resourceType string, resourceId string, relationship string, subjectNamespace string, subjectType string, subjectId string, subjectRelationship string) *apiV1beta1.Relationship { subject := &apiV1beta1.SubjectReference{ Subject: &apiV1beta1.ObjectReference{ - Type: subjectType, - Id: subjectId, + Type: &apiV1beta1.ObjectType{ + Name: subjectType, Namespace: subjectNamespace, + }, + Id: subjectId, }, } @@ -401,8 +563,10 @@ func createRelationship(subjectId string, subjectType *apiV1beta1.ObjectType, su } resource := &apiV1beta1.ObjectReference{ - Type: objectType, - Id: objectId, + Type: &apiV1beta1.ObjectType{ + Name: resourceType, Namespace: resourceNamespace, + }, + Id: resourceId, } return &apiV1beta1.Relationship{ diff --git a/internal/service/lookup_test.go b/internal/service/lookup_test.go index 6d40932..d10aa62 100644 --- a/internal/service/lookup_test.go +++ b/internal/service/lookup_test.go @@ -29,9 +29,9 @@ func TestLookupService_LookupSubjects_NoResults(t *testing.T) { responseCollector := NewLookup_SubjectsServerStub(ctx) err = service.LookupSubjects(&v1beta1.LookupSubjectsRequest{ - SubjectType: simple_type("user"), + SubjectType: rbac_ns_type("user"), Relation: "view", - Resource: &v1beta1.ObjectReference{Type: simple_type("thing"), Id: "thing1"}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("thing"), Id: "thing1"}, }, responseCollector) assert.NoError(t, err) results := responseCollector.GetResponses() @@ -53,7 +53,7 @@ func TestLookupService_LookupResources_NoResults(t *testing.T) { responseCollector := NewLookup_ResourcesServerStub(ctx) err = service.LookupResources(&v1beta1.LookupResourcesRequest{ - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("workspace"), Id: "default"}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("workspace"), Id: "default"}}, Relation: "view_the_thing", ResourceType: &v1beta1.ObjectType{ Name: "workspace", @@ -82,9 +82,9 @@ func TestLookupService_LookupSubjects_OneResult(t *testing.T) { responseCollector := NewLookup_SubjectsServerStub(ctx) err = service.LookupSubjects(&v1beta1.LookupSubjectsRequest{ - SubjectType: simple_type("user"), + SubjectType: rbac_ns_type("user"), Relation: "view", - Resource: &v1beta1.ObjectReference{Type: simple_type("thing"), Id: "thing1"}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("thing"), Id: "thing1"}, }, responseCollector) assert.NoError(t, err) ids := responseCollector.GetIDs() @@ -106,7 +106,7 @@ func TestLookupService_LookupResources_OneResult(t *testing.T) { responseCollector := NewLookup_ResourcesServerStub(ctx) err = service.LookupResources(&v1beta1.LookupResourcesRequest{ - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("workspace"), Id: "default"}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("workspace"), Id: "default"}}, Relation: "workspace", ResourceType: &v1beta1.ObjectType{ Name: "thing", @@ -132,11 +132,11 @@ func TestLookupService_LookupResources_TwoResults(t *testing.T) { container.WaitForQuantizationInterval() service := createLookupService(spicedb) - //&v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("role_binding"), Id: "default_viewers"}} + //&v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("role_binding"), Id: "default_viewers"}} responseCollector := NewLookup_ResourcesServerStub(ctx) err = service.LookupResources(&v1beta1.LookupResourcesRequest{ - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("user"), Id: "u1"}}, - //Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("workspace"), Id: "default"}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("user"), Id: "u1"}}, + //Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("workspace"), Id: "default"}}, Relation: "subject", ResourceType: &v1beta1.ObjectType{ Name: "role_binding", @@ -167,9 +167,9 @@ func TestLookupService_LookupSubjects_TwoResults(t *testing.T) { responseCollector := NewLookup_SubjectsServerStub(ctx) err = service.LookupSubjects(&v1beta1.LookupSubjectsRequest{ - SubjectType: simple_type("user"), + SubjectType: rbac_ns_type("user"), Relation: "view", - Resource: &v1beta1.ObjectReference{Type: simple_type("thing"), Id: "thing1"}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("thing"), Id: "thing1"}, }, responseCollector) assert.NoError(t, err) ids := responseCollector.GetIDs() @@ -189,9 +189,9 @@ func createLookupService(spicedb *data.SpiceDbRepository) *LookupService { func seedThingInDefaultWorkspace(ctx context.Context, spicedb *data.SpiceDbRepository, thing string) error { return spicedb.CreateRelationships(ctx, []*v1beta1.Relationship{ { - Resource: &v1beta1.ObjectReference{Type: simple_type("thing"), Id: thing}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("thing"), Id: thing}, Relation: "workspace", - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("workspace"), Id: "default"}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("workspace"), Id: "default"}}, }, }, biz.TouchSemantics(true)) } @@ -199,29 +199,29 @@ func seedThingInDefaultWorkspace(ctx context.Context, spicedb *data.SpiceDbRepos func seedUserWithViewThingInDefaultWorkspace(ctx context.Context, spicedb *data.SpiceDbRepository, user string) error { return spicedb.CreateRelationships(ctx, []*v1beta1.Relationship{ { - Resource: &v1beta1.ObjectReference{Type: simple_type("role"), Id: "viewers"}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("role"), Id: "viewers"}, Relation: "view_the_thing", - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("user"), Id: "*"}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("user"), Id: "*"}}, }, { - Resource: &v1beta1.ObjectReference{Type: simple_type("role_binding"), Id: "default_viewers"}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("role_binding"), Id: "default_viewers"}, Relation: "subject", - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("user"), Id: user}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("user"), Id: user}}, }, { - Resource: &v1beta1.ObjectReference{Type: simple_type("role_binding"), Id: "default_viewers_two"}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("role_binding"), Id: "default_viewers_two"}, Relation: "subject", - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("user"), Id: user}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("user"), Id: user}}, }, { - Resource: &v1beta1.ObjectReference{Type: simple_type("role_binding"), Id: "default_viewers"}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("role_binding"), Id: "default_viewers"}, Relation: "granted", - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("role"), Id: "viewers"}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("role"), Id: "viewers"}}, }, { - Resource: &v1beta1.ObjectReference{Type: simple_type("workspace"), Id: "default"}, + Resource: &v1beta1.ObjectReference{Type: rbac_ns_type("workspace"), Id: "default"}, Relation: "user_grant", - Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: simple_type("role_binding"), Id: "default_viewers"}}, + Subject: &v1beta1.SubjectReference{Subject: &v1beta1.ObjectReference{Type: rbac_ns_type("role_binding"), Id: "default_viewers"}}, }, }, biz.TouchSemantics(true)) } diff --git a/internal/service/relationships_test.go b/internal/service/relationships_test.go index 5768ab8..ef0fdea 100644 --- a/internal/service/relationships_test.go +++ b/internal/service/relationships_test.go @@ -47,7 +47,7 @@ func TestRelationshipsService_CreateRelationships(t *testing.T) { err, relationshipsService := setup(t) assert.NoError(t, err) ctx := context.Background() - expected := createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club") + expected := createRelationship(rbac_ns_type("group"), "bob_club", "member", rbac_ns_type("user"), "bob", "") req := &v1beta1.CreateTuplesRequest{ Tuples: []*v1beta1.Relationship{ @@ -58,12 +58,14 @@ func TestRelationshipsService_CreateRelationships(t *testing.T) { assert.NoError(t, err) readReq := &v1beta1.ReadTuplesRequest{Filter: &v1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &v1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }, } @@ -92,7 +94,7 @@ func TestRelationshipsService_CreateRelationshipsWithTouchFalse(t *testing.T) { assert.NoError(t, err) ctx := context.Background() - expected := createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club") + expected := createRelationship(rbac_ns_type("group"), "bob_club", "member", rbac_ns_type("user"), "bob", "") req := &v1beta1.CreateTuplesRequest{ Tuples: []*v1beta1.Relationship{ expected, @@ -102,12 +104,14 @@ func TestRelationshipsService_CreateRelationshipsWithTouchFalse(t *testing.T) { assert.NoError(t, err) readReq := &v1beta1.ReadTuplesRequest{Filter: &v1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &v1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }, } @@ -152,8 +156,8 @@ func TestRelationshipsService_CreateRelationshipsWithBadSubjectType(t *testing.T err, relationshipsService := setup(t) assert.NoError(t, err) ctx := context.Background() - badSubjectType := simple_type("not_a_user") - expected := createRelationship("bob", badSubjectType, "", "member", simple_type("group"), "bob_club") + badSubjectType := rbac_ns_type("not_a_user") + expected := createRelationship(rbac_ns_type("group"), "bob_club", "member", badSubjectType, "bob", "") req := &v1beta1.CreateTuplesRequest{ Tuples: []*v1beta1.Relationship{ expected, @@ -171,8 +175,8 @@ func TestRelationshipsService_CreateRelationshipsWithBadObjectType(t *testing.T) err, relationshipsService := setup(t) assert.NoError(t, err) ctx := context.Background() - badObjectType := simple_type("not_an_object") - expected := createRelationship("bob", simple_type("user"), "", "member", badObjectType, "bob_club") + badObjectType := rbac_ns_type("not_an_object") + expected := createRelationship(badObjectType, "bob_club", "member", rbac_ns_type("user"), "bob", "") req := &v1beta1.CreateTuplesRequest{ Tuples: []*v1beta1.Relationship{ expected, @@ -190,7 +194,7 @@ func TestRelationshipsService_DeleteRelationships(t *testing.T) { err, relationshipsService := setup(t) assert.NoError(t, err) - expected := createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club") + expected := createRelationship(rbac_ns_type("group"), "bob_club", "member", rbac_ns_type("user"), "bob", "") ctx := context.Background() req := &v1beta1.CreateTuplesRequest{ @@ -202,24 +206,28 @@ func TestRelationshipsService_DeleteRelationships(t *testing.T) { assert.NoError(t, err) delreq := &v1beta1.DeleteTuplesRequest{Filter: &v1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &v1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }} _, err = relationshipsService.DeleteTuples(ctx, delreq) assert.NoError(t, err) readReq := &v1beta1.ReadTuplesRequest{Filter: &v1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &v1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }, } @@ -272,7 +280,7 @@ func TestRelationshipsService_ReadRelationships(t *testing.T) { deleteRelationshipsUsecase := biz.NewDeleteRelationshipsUsecase(spiceDbRepository, logger) relationshipsService := NewRelationshipsService(logger, createRelationshipsUsecase, readRelationshipsUsecase, deleteRelationshipsUsecase) - expected := createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club") + expected := createRelationship(rbac_ns_type("group"), "bob_club", "member", rbac_ns_type("user"), "bob", "") reqCr := &v1beta1.CreateTuplesRequest{ Tuples: []*v1beta1.Relationship{ @@ -283,12 +291,14 @@ func TestRelationshipsService_ReadRelationships(t *testing.T) { assert.NoError(t, err) req := &v1beta1.ReadTuplesRequest{Filter: &v1beta1.RelationTupleFilter{ - ResourceId: pointerize("bob_club"), - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceId: pointerize("bob_club"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &v1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }, } @@ -322,8 +332,8 @@ func TestRelationshipsService_ReadRelationships_Paginated(t *testing.T) { deleteRelationshipsUsecase := biz.NewDeleteRelationshipsUsecase(spiceDbRepository, logger) relationshipsService := NewRelationshipsService(logger, createRelationshipsUsecase, readRelationshipsUsecase, deleteRelationshipsUsecase) - expected1 := createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "bob_club") - expected2 := createRelationship("bob", simple_type("user"), "", "member", simple_type("group"), "other_bob_club") + expected1 := createRelationship(rbac_ns_type("group"), "bob_club", "member", rbac_ns_type("user"), "bob", "") + expected2 := createRelationship(rbac_ns_type("group"), "other_bob_club", "member", rbac_ns_type("user"), "bob", "") reqCr := &v1beta1.CreateTuplesRequest{ Tuples: []*v1beta1.Relationship{ @@ -336,11 +346,13 @@ func TestRelationshipsService_ReadRelationships_Paginated(t *testing.T) { container.WaitForQuantizationInterval() req := &v1beta1.ReadTuplesRequest{Filter: &v1beta1.RelationTupleFilter{ - ResourceType: pointerize("rbac/group"), - Relation: pointerize("member"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + Relation: pointerize("member"), SubjectFilter: &v1beta1.SubjectFilter{ - SubjectId: pointerize("bob"), - SubjectType: pointerize("rbac/user"), + SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), }, }, Pagination: &v1beta1.RequestPagination{ @@ -370,7 +382,7 @@ func TestRelationshipsService_ReadRelationships_Paginated(t *testing.T) { assert.NoError(t, err) } -func simple_type(typename string) *v1beta1.ObjectType { +func rbac_ns_type(typename string) *v1beta1.ObjectType { return &v1beta1.ObjectType{Name: typename, Namespace: "rbac"} } @@ -378,7 +390,7 @@ func pointerize(value string) *string { //Used to turn string literals into poin return &value } -func createRelationship(subjectId string, subjectType *v1beta1.ObjectType, subjectRelationship string, relationship string, objectType *v1beta1.ObjectType, objectId string) *v1beta1.Relationship { +func createRelationship(objectType *v1beta1.ObjectType, objectId string, relationship string, subjectType *v1beta1.ObjectType, subjectId string, subjectRelationship string) *v1beta1.Relationship { subject := &v1beta1.SubjectReference{ Subject: &v1beta1.ObjectReference{ Type: subjectType, diff --git a/test/kessel_test.go b/test/kessel_test.go index 95b209b..96b3f82 100644 --- a/test/kessel_test.go +++ b/test/kessel_test.go @@ -141,12 +141,14 @@ func TestKesselAPIGRPC_DeleteTuples(t *testing.T) { _, err = client.DeleteTuples(context.Background(), &v1beta1.DeleteTuplesRequest{ Filter: &v1beta1.RelationTupleFilter{ - ResourceType: pointerize("rbac/group"), - ResourceId: pointerize("bob_club"), - Relation: pointerize("member"), + ResourceNamespace: pointerize("rbac"), + ResourceType: pointerize("group"), + ResourceId: pointerize("bob_club"), + Relation: pointerize("member"), SubjectFilter: &v1beta1.SubjectFilter{ - SubjectType: pointerize("rbac/user"), - SubjectId: pointerize("bob"), + SubjectNamespace: pointerize("rbac"), + SubjectType: pointerize("user"), + SubjectId: pointerize("bob"), }, }, })