Skip to content

Commit

Permalink
feat: support group slug on relation creation (#12)
Browse files Browse the repository at this point in the history
* feat: support group slug on relation creation

* fix: e2e tests

* fix: e2e tests

* fix: e2e tests

* fix: e2e tests

* fix: add group slug e2e test

* feat: use mockery yaml for generating mocks

* feat: support user id and email

* feat: add tests
  • Loading branch information
mabdh authored Aug 18, 2023
1 parent 85210db commit 7e81049
Show file tree
Hide file tree
Showing 64 changed files with 1,757 additions and 868 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ build: ## build all
CGO_ENABLED=0 go build -o shield .

generate: ## run all go generate in the code base (including generating mock files)
go generate ./...
@go generate ./...
@echo " > generating mock files"
@mockery

lint: ## Run linters
golangci-lint run
Expand Down
12 changes: 8 additions & 4 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/goto/shield/core/resource"
"github.com/goto/shield/core/role"
"github.com/goto/shield/core/user"
"github.com/goto/shield/internal/adapter"
"github.com/goto/shield/internal/api"
"github.com/goto/shield/internal/schema"
"github.com/goto/shield/internal/server"
Expand Down Expand Up @@ -116,13 +117,13 @@ func StartServer(logger *log.Zap, cfg *config.Shield) error {
return err
}

deps, err := buildAPIDependencies(ctx, logger, resourceBlobRepository, dbClient, spiceDBClient)
deps, err := BuildAPIDependencies(ctx, logger, resourceBlobRepository, dbClient, spiceDBClient)
if err != nil {
return err
}

// serving proxies
cbs, cps, err := serveProxies(ctx, logger, cfg.App.IdentityProxyHeader, cfg.App.UserIDHeader, cfg.Proxy, deps.ResourceService, deps.RelationService, deps.UserService, deps.ProjectService)
cbs, cps, err := serveProxies(ctx, logger, cfg.App.IdentityProxyHeader, cfg.App.UserIDHeader, cfg.Proxy, deps.ResourceService, deps.RelationService, deps.UserService, deps.ProjectService, deps.RelationAdapter)
if err != nil {
return err
}
Expand Down Expand Up @@ -151,7 +152,7 @@ func StartServer(logger *log.Zap, cfg *config.Shield) error {
return server.Serve(ctx, logger, cfg.App, nrApp, deps)
}

func buildAPIDependencies(
func BuildAPIDependencies(
ctx context.Context,
logger log.Logger,
resourceBlobRepository *blob.ResourcesRepository,
Expand All @@ -172,7 +173,7 @@ func buildAPIDependencies(

relationPGRepository := postgres.NewRelationRepository(dbc)
relationSpiceRepository := spicedb.NewRelationRepository(sdb)
relationService := relation.NewService(relationPGRepository, relationSpiceRepository, roleService, userService)
relationService := relation.NewService(relationPGRepository, relationSpiceRepository)

groupRepository := postgres.NewGroupRepository(dbc)
groupService := group.NewService(groupRepository, relationService, userService)
Expand All @@ -194,6 +195,8 @@ func buildAPIDependencies(
userService,
projectService)

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

dependencies := api.Deps{
OrgService: organizationService,
UserService: userService,
Expand All @@ -205,6 +208,7 @@ func buildAPIDependencies(
PolicyService: policyService,
ActionService: actionService,
NamespaceService: namespaceService,
RelationAdapter: relationAdapter,
}
return dependencies, nil
}
Expand Down
13 changes: 10 additions & 3 deletions cmd/serve_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/goto/shield/core/resource"
"github.com/goto/shield/core/rule"
"github.com/goto/shield/core/user"
"github.com/goto/shield/internal/adapter"
"github.com/goto/shield/internal/api/v1beta1"
"github.com/goto/shield/internal/proxy"
"github.com/goto/shield/internal/proxy/hook"
Expand All @@ -34,12 +35,13 @@ func serveProxies(
relationService *relation.Service,
userService *user.Service,
projectService *project.Service,
relationAdapter *adapter.Relation,
) ([]func() error, []func(ctx context.Context) error, error) {
var cleanUpBlobs []func() error
var cleanUpProxies []func(ctx context.Context) error

for _, svcConfig := range cfg.Services {
hookPipeline := buildHookPipeline(logger, resourceService, relationService, identityProxyHeaderKey)
hookPipeline := buildHookPipeline(logger, resourceService, relationService, relationAdapter, identityProxyHeaderKey)

h2cProxy := proxy.NewH2c(
proxy.NewH2cRoundTripper(logger, hookPipeline),
Expand Down Expand Up @@ -74,9 +76,14 @@ func serveProxies(
return cleanUpBlobs, cleanUpProxies, nil
}

func buildHookPipeline(log log.Logger, resourceService v1beta1.ResourceService, relationService v1beta1.RelationService, identityProxyHeaderKey string) hook.Service {
func buildHookPipeline(
log log.Logger,
resourceService v1beta1.ResourceService,
relationService v1beta1.RelationService,
relationAdapter *adapter.Relation,
identityProxyHeaderKey string) hook.Service {
rootHook := hook.New()
return authz_hook.New(log, rootHook, rootHook, resourceService, relationService, identityProxyHeaderKey)
return authz_hook.New(log, rootHook, rootHook, resourceService, relationService, relationAdapter, identityProxyHeaderKey)
}

// buildPipeline builds middleware sequence
Expand Down
9 changes: 9 additions & 0 deletions core/group/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ func NewService(repository Repository, relationService RelationService, userServ
}

func (s Service) Create(ctx context.Context, grp Group) (Group, error) {
_, err := s.userService.FetchCurrentUser(ctx)
if err != nil {
return Group{}, fmt.Errorf("%w: %s", user.ErrInvalidEmail, err.Error())
}

newGroup, err := s.repository.Create(ctx, grp)
if err != nil {
return Group{}, err
Expand All @@ -60,6 +65,10 @@ func (s Service) Get(ctx context.Context, idOrSlug string) (Group, error) {
return s.repository.GetBySlug(ctx, idOrSlug)
}

func (s Service) GetBySlug(ctx context.Context, slug string) (Group, error) {
return s.repository.GetBySlug(ctx, slug)
}

func (s Service) GetByIDs(ctx context.Context, groupIDs []string) ([]Group, error) {
return s.repository.GetByIDs(ctx, groupIDs)
}
Expand Down
2 changes: 1 addition & 1 deletion core/organization/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (s Service) addAdminToOrg(ctx context.Context, user user.User, org Organiza
NamespaceID: schema.OrganizationNamespace,
},
Subject: relation.Subject{
ID: user.Email,
ID: user.ID,
Namespace: schema.UserPrincipal,
RoleID: schema.OwnerRole,
},
Expand Down
6 changes: 6 additions & 0 deletions core/project/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package project

import (
"context"
"fmt"

"github.com/goto/shield/core/action"
"github.com/goto/shield/core/namespace"
Expand Down Expand Up @@ -46,6 +47,11 @@ func (s Service) Get(ctx context.Context, idOrSlug string) (Project, error) {
}

func (s Service) Create(ctx context.Context, prj Project) (Project, error) {
_, err := s.userService.FetchCurrentUser(ctx)
if err != nil {
return Project{}, fmt.Errorf("%w: %s", user.ErrInvalidEmail, err.Error())
}

newProject, err := s.repository.Create(ctx, Project{
Name: prj.Name,
Slug: prj.Slug,
Expand Down
1 change: 1 addition & 0 deletions core/relation/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ var (
ErrCreatingRelationInStore = errors.New("error while creating relation")
ErrCreatingRelationInAuthzEngine = errors.New("error while creating relation in authz engine")
ErrFetchingUser = errors.New("error while fetching user")
ErrFetchingGroup = errors.New("error while fetching group")
)
9 changes: 0 additions & 9 deletions core/relation/relation.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/goto/shield/core/action"
"github.com/goto/shield/core/namespace"
"github.com/goto/shield/core/role"
"github.com/goto/shield/core/user"
)

type Repository interface {
Expand All @@ -27,14 +26,6 @@ type AuthzRepository interface {
AddV2(ctx context.Context, rel RelationV2) error
}

type RoleService interface {
Get(ctx context.Context, id string) (role.Role, error)
}

type UserService interface {
GetByEmail(ctx context.Context, email string) (user.User, error)
}

type Relation struct {
ID string
SubjectNamespace namespace.Namespace
Expand Down
18 changes: 1 addition & 17 deletions core/relation/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,17 @@ import (
"github.com/goto/shield/core/action"
"github.com/goto/shield/core/namespace"
"github.com/goto/shield/core/user"
"github.com/goto/shield/internal/schema"
)

type Service struct {
repository Repository
authzRepository AuthzRepository
roleService RoleService
userService UserService
}

func NewService(repository Repository, authzRepository AuthzRepository, roleService RoleService, userService UserService) *Service {
func NewService(repository Repository, authzRepository AuthzRepository) *Service {
return &Service{
repository: repository,
authzRepository: authzRepository,
roleService: roleService,
userService: userService,
}
}

Expand All @@ -31,17 +26,6 @@ func (s Service) Get(ctx context.Context, id string) (RelationV2, error) {
}

func (s Service) Create(ctx context.Context, rel RelationV2) (RelationV2, error) {
// If Principal is a user, then we will get ID for that user as Subject.ID
if rel.Subject.Namespace == schema.UserPrincipal || rel.Subject.Namespace == "user" {
fetchedUser, err := s.userService.GetByEmail(ctx, rel.Subject.ID)
if err != nil {
return RelationV2{}, fmt.Errorf("%w: %s", ErrFetchingUser, err.Error())
}

rel.Subject.Namespace = schema.UserPrincipal
rel.Subject.ID = fetchedUser.ID
}

createdRelation, err := s.repository.Create(ctx, rel)
if err != nil {
return RelationV2{}, fmt.Errorf("%w: %s", ErrCreatingRelationInStore, err.Error())
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/guides/managing-organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ A organization in Shield looks like
"name": "gotocompany",
"slug": "gotocompany",
"metadata": {
"description": "Open DataOps Foundation"
"description": "Goto company"
},
"createdAt": "2022-12-07T14:10:42.755848Z",
"updatedAt": "2022-12-07T14:10:42.755848Z"
Expand All @@ -37,7 +37,7 @@ A organization in Shield looks like
"name": "gotocompany",
"slug": "gotocompany",
"metadata": {
"description": "Open DataOps Foundation"
"description": "Goto company"
}
}'`}
</CodeBlock>
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/tour/creating-organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ curl --location --request POST 'http://localhost:8000/admin/v1beta1/organization
"name": "gotocompany",
"slug": "gotocompany",
"metadata": {
"description": "Open DataOps Foundation"
"description": "Goto company"
}
}'
```
Expand All @@ -93,7 +93,7 @@ curl --location --request POST 'http://localhost:8000/admin/v1beta1/organization
"name": "gotocompany",
"slug": "gotocompany",
"metadata": {
"description": "Open DataOps Foundation"
"description": "Goto company"
},
"createdAt": "2022-12-07T14:10:42.755848Z",
"updatedAt": "2022-12-07T14:10:42.755848Z"
Expand Down
2 changes: 1 addition & 1 deletion docs/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const darkCodeTheme = require('prism-react-renderer/themes/dracula');
},
footer: {
style: 'light',
copyright: `Open DataOps Foundation © ${new Date().getFullYear()}`,
copyright: `Gotocompany © ${new Date().getFullYear()}`,
},
prism: {
theme: lightCodeTheme,
Expand Down
15 changes: 2 additions & 13 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/jackc/pgx/v4 v4.17.2
github.com/jhump/protoreflect v1.14.0
github.com/jmoiron/sqlx v1.3.5
github.com/julienschmidt/httprouter v1.3.0
github.com/lib/pq v1.10.7
github.com/mcuadros/go-defaults v1.2.0
github.com/mitchellh/mapstructure v1.5.0
Expand Down Expand Up @@ -72,28 +73,23 @@ require (
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/charmbracelet/glamour v0.6.0 // indirect
github.com/cilium/ebpf v0.10.0 // indirect
github.com/cli/safeexec v1.0.1 // indirect
github.com/containerd/continuity v0.3.0 // indirect
github.com/cosiner/argv v0.1.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/derekparker/trie v0.0.0-20221221181808-1424fce0c981 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
github.com/frankban/quicktest v1.14.4 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-delve/delve v1.20.2 // indirect
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/cel-go v0.13.0 // indirect
github.com/google/go-dap v0.8.0 // indirect
github.com/google/pprof v0.0.0-20221219190121-3cb0bae90811 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/wire v0.5.0 // indirect
Expand All @@ -103,7 +99,6 @@ require (
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
Expand All @@ -122,7 +117,6 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/microcosm-cc/bluemonday v1.0.21 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.13.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
Expand Down Expand Up @@ -151,19 +145,14 @@ require (
github.com/subosito/gotenv v1.4.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/vektra/mockery/v2 v2.13.1 // indirect
github.com/yuin/goldmark v1.5.3 // indirect
github.com/yuin/goldmark-emoji v1.0.1 // indirect
go.starlark.net v0.0.0-20230302034142-4b1e35fe2254 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/term v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
golang.org/x/tools v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.106.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand Down
Loading

0 comments on commit 7e81049

Please sign in to comment.