Skip to content

Commit

Permalink
Rework Instances interface
Browse files Browse the repository at this point in the history
  • Loading branch information
oanatmaria committed Oct 26, 2023
1 parent e02c6b6 commit e8acb04
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 44 deletions.
70 changes: 51 additions & 19 deletions model/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/aserto-dev/go-directory/pkg/derr"
"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
"github.com/samber/lo"
)

//go:generate go run github.com/golang/mock/mockgen -destination=mock_instances.go -package=diff github.com/aserto-dev/azm/model/diff Instances
Expand All @@ -18,50 +19,81 @@ type Changes struct {
Relations map[string][]string
}

// Only the types of the relation instances are needed.
type RelationKind struct {
Object string
Relation string
Subject string
SubjectRelation string
}

type Instances interface {
ObjectsExist(objectType string) (bool, error)
RelationsExist(objectType, relationName string) (bool, error)
ObjectTypes() ([]string, error)
RelationTypes() ([]*RelationKind, error)
}

func (d *Diff) Validate(dv Instances) error {
var errs error
if err := d.validateObjectTypes(dv); err != nil {
var rels []*RelationKind
if len(d.Removed.Objects) > 0 {
objs, err := dv.ObjectTypes()
if err != nil {
return err
}

rels, err = dv.RelationTypes()
if err != nil {
return err
}

err = d.validateObjectTypes(objs, rels)
errs = multierror.Append(errs, err)
}

if err := d.validateRelationsTypes(dv); err != nil {
if len(d.Removed.Relations) > 0 {
var err error
if len(rels) == 0 {
rels, err = dv.RelationTypes()
if err != nil {
return err
}

}
err = d.validateRelationsTypes(rels)
errs = multierror.Append(errs, err)
}

return errs
if merr, ok := errs.(*multierror.Error); ok && len(merr.Errors) > 0 {
return errs
}

return nil
}

func (d *Diff) validateObjectTypes(dv Instances) error {
func (d *Diff) validateObjectTypes(objs []string, rels []*RelationKind) error {
var errs error
for _, objType := range d.Removed.Objects {
hasInstance, err := dv.ObjectsExist(objType)
if err != nil {
errs = multierror.Append(errs, err)
continue
_, found := lo.Find(objs, func(obj string) bool { return obj == objType })
if found {
errs = multierror.Append(errs, errors.Wrapf(derr.ErrObjectTypeInUse, "object type: %s", objType))
}
if hasInstance {
_, found = lo.Find(rels, func(rel *RelationKind) bool { return rel.Object == objType || rel.Subject == objType })
if found {
errs = multierror.Append(errs, errors.Wrapf(derr.ErrObjectTypeInUse, "object type: %s", objType))
}
}
return errs
}

func (d *Diff) validateRelationsTypes(dv Instances) error {
func (d *Diff) validateRelationsTypes(relations []*RelationKind) error {
var errs error
for objType, rels := range d.Removed.Relations {
for _, rel := range rels {
hasInstance, err := dv.RelationsExist(objType, rel)
if err != nil {
errs = multierror.Append(errs, err)
continue
}
if hasInstance {
errs = multierror.Append(errs, errors.Wrapf(derr.ErrRelationTypeInUse, "relation type: %s; object type: %s", rel, objType))
_, found := lo.Find(relations, func(rl *RelationKind) bool {
return rl.Object == objType && rl.Relation == rel
})
if found {
errs = multierror.Append(errs, errors.Wrapf(derr.ErrRelationTypeInUse, "object type: %s", objType))
}
}
}
Expand Down
18 changes: 7 additions & 11 deletions model/diff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ func TestValidateDiffWithObjectTypeDeletion(t *testing.T) {

dif := diff.Diff{Removed: diff.Changes{Objects: []string{objType}}, Added: diff.Changes{}}

mockInstances.EXPECT().ObjectsExist(objType).Return(false, nil)
mockInstances.EXPECT().ObjectTypes().Return([]string{}, nil)
mockInstances.EXPECT().RelationTypes().Return([]*diff.RelationKind{}, nil)
err := dif.Validate(mockInstances)

require.NoError(t, err)
Expand All @@ -42,8 +43,8 @@ func TestValidateDiffWith2ObjectTypeDeletion(t *testing.T) {

dif := diff.Diff{Removed: diff.Changes{Objects: objTypes}, Added: diff.Changes{}}

mockInstances.EXPECT().ObjectsExist(objTypes[0]).Return(false, nil)
mockInstances.EXPECT().ObjectsExist(objTypes[1]).Return(true, nil)
mockInstances.EXPECT().ObjectTypes().Return([]string{"user"}, nil)
mockInstances.EXPECT().RelationTypes().Return([]*diff.RelationKind{}, nil)
err := dif.Validate(mockInstances)

require.Error(t, err)
Expand All @@ -58,9 +59,8 @@ func TestValidateDiffWithRelationTypeDeletion(t *testing.T) {

dif := diff.Diff{Removed: diff.Changes{Objects: objTypes, Relations: relationTypes}, Added: diff.Changes{}}

mockInstances.EXPECT().ObjectsExist(objTypes[0]).Return(false, nil)
mockInstances.EXPECT().ObjectsExist(objTypes[1]).Return(false, nil)
mockInstances.EXPECT().RelationsExist("folder", relationTypes["folder"][0]).Return(true, nil)
mockInstances.EXPECT().ObjectTypes().Return([]string{}, nil)
mockInstances.EXPECT().RelationTypes().Return([]*diff.RelationKind{{Object: "folder", Relation: "parent_folder"}}, nil)
err := dif.Validate(mockInstances)

require.Error(t, err)
Expand All @@ -75,13 +75,9 @@ func TestValidateDiffWithObjectInstances(t *testing.T) {

dif := diff.Diff{Removed: diff.Changes{Objects: objTypes, Relations: relationTypes}, Added: diff.Changes{}}

mockInstances.EXPECT().ObjectsExist(objTypes[0]).Return(false, ErrBoom)
mockInstances.EXPECT().ObjectsExist(objTypes[1]).Return(true, nil)
mockInstances.EXPECT().RelationsExist("folder", relationTypes["folder"][0]).Return(true, nil)
mockInstances.EXPECT().ObjectTypes().Return([]string{}, ErrBoom)
err := dif.Validate(mockInstances)

require.Error(t, err)
require.Contains(t, err.Error(), derr.ErrRelationTypeInUse.Message)
require.Contains(t, err.Error(), derr.ErrObjectTypeInUse.Message)
require.Contains(t, err.Error(), ErrBoom.Error())
}
28 changes: 14 additions & 14 deletions model/diff/mock_instances.go

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

0 comments on commit e8acb04

Please sign in to comment.