Skip to content

Commit

Permalink
fix: #681 visited map for recursive schema walker
Browse files Browse the repository at this point in the history
  • Loading branch information
tolgaOzen committed Sep 18, 2023
1 parent b34427a commit d600078
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
19 changes: 18 additions & 1 deletion internal/schema/walker.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ package schema
import (
"errors"

"github.com/Permify/permify/pkg/dsl/utils"
base "github.com/Permify/permify/pkg/pb/base/v1"
)

// Walker is a struct used for traversing a schema
type Walker struct {
schema *base.SchemaDefinition

// map used to track visited nodes and avoid infinite recursion
visited map[string]struct{}
}

// NewWalker is a constructor for the Walker struct
func NewWalker(schema *base.SchemaDefinition) *Walker {
return &Walker{
schema: schema,
schema: schema,
visited: make(map[string]struct{}),
}
}

Expand All @@ -23,6 +28,18 @@ func (w *Walker) Walk(
entityType string,
permission string,
) error {
// Generate a unique key for the entityType and permission combination
key := utils.Key(entityType, permission)

// Check if the entity-permission combination has already been visited
if _, ok := w.visited[key]; ok {
// If already visited, exit early to avoid redundant processing or infinite recursion
return nil
}

// Mark the entity-permission combination as visited
w.visited[key] = struct{}{}

// Lookup the entity definition in the schema
def, ok := w.schema.EntityDefinitions[entityType]
if !ok {
Expand Down
42 changes: 42 additions & 0 deletions internal/schema/walker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,47 @@ var _ = Describe("walker", func() {

Expect(err).Should(Equal(ErrUnimplemented))
})

It("Case 3", func() {
sch, err := parser.NewParser(`
entity user {}
entity tag {
relation assignee @department
permission view_document = assignee.view_document
}
entity document {
relation owner @department
permission edit = owner.edit_document
permission view = owner.view_document or owner.peek_document
}
entity department {
relation parent @department
relation admin @user
relation viewer @user
relation assigned_tag @tag
permission peek_document = assigned_tag.view_document or parent.peek_document
permission edit_document = admin or parent.edit_document
permission view_document = viewer or admin or parent.view_document
}
`).Parse()

Expect(err).ShouldNot(HaveOccurred())

c := compiler.NewCompiler(true, sch)
e, r, err := c.Compile()

Expect(err).ShouldNot(HaveOccurred())

w := NewWalker(NewSchemaFromEntityAndRuleDefinitions(e, r))

err = w.Walk("document", "view")

Expect(err).ShouldNot(HaveOccurred())
})
})
})

0 comments on commit d600078

Please sign in to comment.