Skip to content

Commit

Permalink
feat: list resource of a user (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
FemiNoviaLina authored Sep 17, 2024
1 parent 1c1b95d commit 206c2fd
Show file tree
Hide file tree
Showing 30 changed files with 2,902 additions and 773 deletions.
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 := "6ee59f2d0cbeedf1d5fe48adee5e5e41f54f081e"
PROTON_COMMIT := "cca99f3519d6ad94953d75083445ae5e7af00e71"

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 @@ -238,7 +238,7 @@ func BuildAPIDependencies(

resourcePGRepository := postgres.NewResourceRepository(dbc)
resourceService := resource.NewService(
logger, resourcePGRepository, resourceBlobRepository, relationService, userService, projectService, organizationService, groupService, activityService)
logger, resourcePGRepository, resourceBlobRepository, relationService, userService, projectService, organizationService, groupService, policyService, namespaceService, activityService)

serviceDataRepository := postgres.NewServiceDataRepository(dbc)
serviceDataService := servicedata.NewService(logger, serviceDataRepository, resourceService, relationService, projectService, userService, activityService)
Expand Down
29 changes: 15 additions & 14 deletions core/policy/mocks/policy_repository.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/policy/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const AuditEntity = "policy"

type Repository interface {
Get(ctx context.Context, id string) (Policy, error)
List(ctx context.Context) ([]Policy, error)
List(ctx context.Context, filter Filters) ([]Policy, error)
Upsert(ctx context.Context, pol *Policy) (string, error)
Update(ctx context.Context, pol *Policy) (string, error)
}
Expand Down
8 changes: 4 additions & 4 deletions core/policy/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ func (s Service) Get(ctx context.Context, id string) (Policy, error) {
return s.repository.Get(ctx, id)
}

func (s Service) List(ctx context.Context) ([]Policy, error) {
return s.repository.List(ctx)
func (s Service) List(ctx context.Context, filter Filters) ([]Policy, error) {
return s.repository.List(ctx, filter)
}

func (s Service) Upsert(ctx context.Context, pol *Policy) ([]Policy, error) {
Expand All @@ -58,7 +58,7 @@ func (s Service) Upsert(ctx context.Context, pol *Policy) ([]Policy, error) {
}
pol.ID = policyID

policies, err := s.repository.List(ctx)
policies, err := s.repository.List(ctx, Filters{})
if err != nil {
return []Policy{}, err
}
Expand Down Expand Up @@ -87,7 +87,7 @@ func (s Service) Update(ctx context.Context, pol *Policy) ([]Policy, error) {
}
pol.ID = policyID

policies, err := s.repository.List(ctx)
policies, err := s.repository.List(ctx, Filters{})
if err != nil {
return []Policy{}, err
}
Expand Down
2 changes: 1 addition & 1 deletion core/relation/mocks/authz_repository.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions core/resource/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ type PagedResources struct {
Resources []Resource
}

type ResourcePermissions = map[string][]string

type LogData struct {
Entity string `mapstructure:"entity"`
URN string `mapstructure:"urn"`
Expand Down
100 changes: 99 additions & 1 deletion core/resource/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/goto/shield/core/group"
"github.com/goto/shield/core/namespace"
"github.com/goto/shield/core/organization"
"github.com/goto/shield/core/policy"
"github.com/goto/shield/core/project"
"github.com/goto/shield/core/relation"
"github.com/goto/shield/core/user"
Expand All @@ -22,6 +23,8 @@ import (
const (
auditKeyResourceCreate = "resource.create"
auditKeyResourceUpdate = "resource.update"

userNamespace = schema.UserPrincipal
)

type RelationService interface {
Expand All @@ -30,10 +33,12 @@ type RelationService interface {
CheckPermission(ctx context.Context, usr user.User, resourceNS namespace.Namespace, resourceIdxa string, action action.Action) (bool, error)
BulkCheckPermission(ctx context.Context, rels []relation.Relation, acts []action.Action) ([]relation.Permission, error)
DeleteSubjectRelations(ctx context.Context, resourceType, optionalResourceID string) error
LookupResources(ctx context.Context, resourceType, permission, subjectType, subjectID string) ([]string, error)
}

type UserService interface {
FetchCurrentUser(ctx context.Context) (user.User, error)
Get(ctx context.Context, userID string) (user.User, error)
}

type ProjectService interface {
Expand All @@ -52,6 +57,14 @@ type ActivityService interface {
Log(ctx context.Context, action string, actor activity.Actor, data any) error
}

type PolicyService interface {
List(ctx context.Context, filter policy.Filters) ([]policy.Policy, error)
}

type NamespaceService interface {
List(ctx context.Context) ([]namespace.Namespace, error)
}

type Service struct {
logger log.Logger
repository Repository
Expand All @@ -61,10 +74,12 @@ type Service struct {
projectService ProjectService
organizationService OrganizationService
groupService GroupService
policyService PolicyService
namespaceService NamespaceService
activityService ActivityService
}

func NewService(logger log.Logger, repository Repository, configRepository ConfigRepository, relationService RelationService, userService UserService, projectService ProjectService, organizationService OrganizationService, groupService GroupService, activityService ActivityService) *Service {
func NewService(logger log.Logger, repository Repository, configRepository ConfigRepository, relationService RelationService, userService UserService, projectService ProjectService, organizationService OrganizationService, groupService GroupService, policyService PolicyService, namespaceService NamespaceService, activityService ActivityService) *Service {
return &Service{
logger: logger,
repository: repository,
Expand All @@ -74,6 +89,8 @@ func NewService(logger log.Logger, repository Repository, configRepository Confi
projectService: projectService,
organizationService: organizationService,
groupService: groupService,
policyService: policyService,
namespaceService: namespaceService,
activityService: activityService,
}
}
Expand Down Expand Up @@ -383,3 +400,84 @@ func (s Service) BulkCheckAuthz(ctx context.Context, resources []Resource, actio
}
return s.relationService.BulkCheckPermission(ctx, relations, actions)
}

func (s Service) ListUserResourcesByType(ctx context.Context, userID string, resourceType string) (ResourcePermissions, error) {
user, err := s.userService.Get(ctx, userID)
if err != nil {
return ResourcePermissions{}, err
}

res, err := s.listUserResources(ctx, resourceType, user)
if err != nil {
return ResourcePermissions{}, err
}

return res, nil
}

func (s Service) ListAllUserResources(ctx context.Context, userID string, resourceTypes []string) (map[string]ResourcePermissions, error) {
user, err := s.userService.Get(ctx, userID)
if err != nil {
return map[string]ResourcePermissions{}, err
}

if len(resourceTypes) == 0 {
namespaces, err := s.namespaceService.List(ctx)
if err != nil {
return map[string]ResourcePermissions{}, err
}

for _, ns := range namespaces {
if namespace.IsSystemNamespaceID(ns.ID) {
continue
}
resourceTypes = append(resourceTypes, ns.ID)
}
}

result := make(map[string]ResourcePermissions)
for _, res := range resourceTypes {
if _, ok := result[res]; !ok {
list, err := s.listUserResources(ctx, res, user)
if err != nil {
return map[string]ResourcePermissions{}, err
}
if len(list) != 0 {
result[res] = list
}
}
}

return result, nil
}

func (s Service) listUserResources(ctx context.Context, resourceType string, user user.User) (ResourcePermissions, error) {
policies, err := s.policyService.List(ctx, policy.Filters{NamespaceID: resourceType})
if err != nil {
return ResourcePermissions{}, err
}

resPermissionsMap := make(ResourcePermissions)
actMap := make(map[string]bool)
for _, policy := range policies {
action := strings.Split(policy.ActionID, ".")[0]
if _, ok := actMap[action]; ok {
continue
}
actMap[action] = true
resources, err := s.relationService.LookupResources(ctx, resourceType, action, userNamespace, user.ID)
if err != nil {
return ResourcePermissions{}, err
}

for _, r := range resources {
if _, ok := resPermissionsMap[r]; !ok {
resPermissionsMap[r] = []string{action}
} else {
resPermissionsMap[r] = append(resPermissionsMap[r], action)
}
}
}

return resPermissionsMap, nil
}
29 changes: 15 additions & 14 deletions internal/api/v1beta1/mocks/policy_service.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/api/v1beta1/mocks/relation_service.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 206c2fd

Please sign in to comment.