From e60f933b93aec06daabbce03802f3be05eea248f Mon Sep 17 00:00:00 2001 From: Ishan Arya Date: Thu, 4 Jul 2024 16:51:26 +0530 Subject: [PATCH] feat: make servicedata key public --- cmd/serve.go | 2 +- internal/adapter/relation.go | 21 ++++++++++++++++++- internal/schema/predefined.go | 7 ++++--- internal/store/postgres/role_repository.go | 3 ++- .../spicedb/schema_generator/generator.go | 5 +++-- test/integration_test/rest_test.go | 3 ++- 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/cmd/serve.go b/cmd/serve.go index c006e3ba4..042d61c80 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -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, diff --git a/internal/adapter/relation.go b/internal/adapter/relation.go index c222b9fb1..600cd33f0 100644 --- a/internal/adapter/relation.go +++ b/internal/adapter/relation.go @@ -2,30 +2,38 @@ package adapter import ( "context" + "errors" "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, } } @@ -36,7 +44,18 @@ 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 { + roleID := rel.Object.NamespaceID + ":" + rel.Subject.RoleID + role, err := a.roleService.Get(ctx, roleID) + if err != nil { + return relation.RelationV2{}, err + } + if !slices.Contains(role.Types, schema.UserPrincipalWildcard) { + return relation.RelationV2{}, errors.New("this does not allow wildcard") + } + } + + if !uuid.IsValid(userID) && userID != WILDCARD { fetchedUser, err := a.userService.GetByEmail(ctx, rel.Subject.ID) if err != nil { return relation.RelationV2{}, fmt.Errorf("%w: %s", relation.ErrFetchingUser, err.Error()) diff --git a/internal/schema/predefined.go b/internal/schema/predefined.go index b90cf6a07..6c29fb4d2 100644 --- a/internal/schema/predefined.go +++ b/internal/schema/predefined.go @@ -29,8 +29,9 @@ const ( MembershipPermission = "membership" // principals - UserPrincipal = "shield/user" - GroupPrincipal = "shield/group" + UserPrincipal = "shield/user" + GroupPrincipal = "shield/group" + UserPrincipalWildcard = "shield/user:*" ) var InheritedRelations = map[string]bool{ @@ -131,7 +132,7 @@ var ServiceDataKeyConfig = NamespaceConfig{ }, Roles: map[string][]string{ EditorRole: {UserPrincipal, GroupPrincipal}, - ViewerRole: {UserPrincipal, GroupPrincipal}, + ViewerRole: {UserPrincipal, GroupPrincipal, UserPrincipalWildcard}, OwnerRole: {UserPrincipal, GroupPrincipal}, }, Permissions: map[string][]string{ diff --git a/internal/store/postgres/role_repository.go b/internal/store/postgres/role_repository.go index e9a38e7ff..d0d5fe57b 100644 --- a/internal/store/postgres/role_repository.go +++ b/internal/store/postgres/role_repository.go @@ -116,7 +116,8 @@ func (r RoleRepository) Upsert(ctx context.Context, rl role.Role) (string, error "metadata": goqu.L("$5"), }).OnConflict( goqu.DoUpdate("id", goqu.Record{ - "name": goqu.L("$2"), + "types": goqu.L("$3"), + "metadata": goqu.L("$5"), }, )).Returning("id").ToSQL() if err != nil { diff --git a/internal/store/spicedb/schema_generator/generator.go b/internal/store/spicedb/schema_generator/generator.go index 7fb0ca6ab..4f1e6e35d 100644 --- a/internal/store/spicedb/schema_generator/generator.go +++ b/internal/store/spicedb/schema_generator/generator.go @@ -49,7 +49,8 @@ func GenerateSchema(namespaceConfig schema.NamespaceConfigMapType) []string { func processPrincipal(s string) string { return map[string]string{ - "shield/group": "shield/group#membership", - "shield/user": "shield/user", + "shield/group": "shield/group#membership", + "shield/user": "shield/user", + "shield/user:*": "shield/user:*", }[s] } diff --git a/test/integration_test/rest_test.go b/test/integration_test/rest_test.go index cf2292c2c..73f828691 100644 --- a/test/integration_test/rest_test.go +++ b/test/integration_test/rest_test.go @@ -15,6 +15,7 @@ import ( "github.com/goto/shield/core/project" "github.com/goto/shield/core/relation" "github.com/goto/shield/core/resource" + "github.com/goto/shield/core/role" "github.com/goto/shield/core/rule" "github.com/goto/shield/core/user" "github.com/goto/shield/internal/adapter" @@ -309,7 +310,7 @@ func buildPipeline(logger log.Logger, proxy http.Handler, ruleService *rule.Serv func hookPipeline(log log.Logger) hook.Service { rootHook := hook.New() - relationAdapter := adapter.NewRelation(&group.Service{}, &user.Service{}, &relation.Service{}) + relationAdapter := adapter.NewRelation(&group.Service{}, &user.Service{}, &relation.Service{}, &role.Service{}) return authz_hook.New(log, rootHook, rootHook, &resource.Service{}, &relation.Service{}, relationAdapter, "X-Auth-Email") }