Skip to content

Commit

Permalink
feat: integrate with mapped UUIDs
Browse files Browse the repository at this point in the history
  • Loading branch information
hperl committed Aug 1, 2022
1 parent b95019d commit ecd4805
Show file tree
Hide file tree
Showing 48 changed files with 773 additions and 820 deletions.
4 changes: 2 additions & 2 deletions cmd/expand/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ func NewExpandCmd() *cobra.Command {
return cmdx.FailSilently(cmd)
}

var tree *ketoapi.ExpandTree
var tree *ketoapi.Tree[*ketoapi.RelationTuple]
if resp.Tree != nil {
tree = (&ketoapi.ExpandTree{}).FromProto(resp.Tree)
tree = ketoapi.TreeFromProto[*ketoapi.RelationTuple](resp.Tree)
}

cmdx.PrintJSONAble(cmd, tree)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func main() {
panic(err)
}

tree := (&ketoapi.ExpandTree{}).FromProto(res.Tree)
tree := ketoapi.TreeFromProto[*ketoapi.RelationTuple](res.Tree)

enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bradleyjkemp/cupaloy/v2 v2.6.0 h1:knToPYa2xtfg42U3I6punFEjaGFKWQRXJwj0JTv4mTs=
github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
Expand Down
9 changes: 5 additions & 4 deletions internal/check/binop.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import (
"github.com/pkg/errors"

"github.com/ory/keto/internal/check/checkgroup"
"github.com/ory/keto/internal/expand"
"github.com/ory/keto/internal/relationtuple"
"github.com/ory/keto/ketoapi"
)

type binaryOperator = func(ctx context.Context, checks []checkgroup.CheckFunc) checkgroup.Result
Expand Down Expand Up @@ -52,9 +53,9 @@ func and(ctx context.Context, checks []checkgroup.CheckFunc) checkgroup.Result {
go check(childCtx, resultCh)
}

tree := &expand.Tree{
Type: expand.Intersection,
Children: []*expand.Tree{},
tree := &ketoapi.Tree[*relationtuple.RelationTuple]{
Type: ketoapi.TreeNodeIntersection,
Children: []*ketoapi.Tree[*relationtuple.RelationTuple]{},
}

for i := 0; i < len(checks); i++ {
Expand Down
18 changes: 10 additions & 8 deletions internal/check/checkgroup/definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (

"github.com/pkg/errors"

"github.com/ory/keto/internal/expand"
"github.com/ory/keto/internal/relationtuple"
"github.com/ory/keto/ketoapi"
)

type (
Expand All @@ -24,18 +24,20 @@ type (

Result struct {
Membership Membership
Tree *expand.Tree
Tree *ketoapi.Tree[*relationtuple.RelationTuple]
Err error
}

Edge struct {
Tuple relationtuple.InternalRelationTuple
Type expand.NodeType
Tuple relationtuple.RelationTuple
Type ketoapi.TreeNodeType
}

Transformation int

Membership int

tree = ketoapi.Tree[*relationtuple.RelationTuple]
)

//go:generate stringer -type Membership
Expand Down Expand Up @@ -82,15 +84,15 @@ func WithEdge(e Edge, f CheckFunc) CheckFunc {
select {
case result := <-childCh:
if result.Tree == nil {
result.Tree = &expand.Tree{
Type: expand.Leaf,
result.Tree = &ketoapi.Tree[*relationtuple.RelationTuple]{
Type: ketoapi.TreeNodeLeaf,
Tuple: &e.Tuple,
}
} else {
result.Tree = &expand.Tree{
result.Tree = &ketoapi.Tree[*relationtuple.RelationTuple]{
Type: e.Type,
Tuple: &e.Tuple,
Children: []*expand.Tree{result.Tree},
Children: []*tree{result.Tree},
}
}
resultCh <- result
Expand Down
19 changes: 10 additions & 9 deletions internal/check/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (

"github.com/ory/keto/internal/check/checkgroup"
"github.com/ory/keto/internal/driver/config"
"github.com/ory/keto/internal/expand"
"github.com/ory/keto/internal/namespace"
"github.com/ory/keto/internal/namespace/ast"
"github.com/ory/keto/internal/relationtuple"
"github.com/ory/keto/internal/x"
"github.com/ory/keto/internal/x/graph"
"github.com/ory/keto/ketoapi"
)

type (
Expand Down Expand Up @@ -81,7 +81,7 @@ func (e *Engine) CheckRelationTuple(ctx context.Context, r *RelationTuple, restD
func (e *Engine) checkExpandSubject(ctx context.Context, r *RelationTuple, restDepth int) checkgroup.CheckFunc {
if restDepth < 0 {
e.d.Logger().
WithFields(r.ToLoggerFields()).
WithField("request", r.String()).
Debug("reached max-depth, therefore this query will not be further expanded")
return checkgroup.UnknownMemberFunc
}
Expand All @@ -98,7 +98,7 @@ func (e *Engine) checkExpandSubject(ctx context.Context, r *RelationTuple, restD
err error
visited bool
innerCtx = graph.InitVisited(ctx)
query = &Query{Namespace: r.Namespace, Object: r.Object, Relation: r.Relation}
query = &Query{Namespace: &r.Namespace, Object: &r.Object, Relation: &r.Relation}
)
for {
subjects, pageToken, err = e.d.RelationTupleManager().GetRelationTuples(innerCtx, query, x.WithToken(pageToken))
Expand All @@ -114,15 +114,16 @@ func (e *Engine) checkExpandSubject(ctx context.Context, r *RelationTuple, restD
if visited {
continue
}
if s.Subject.SubjectSet() == nil || s.Subject.SubjectSet().Relation == WildcardRelation {
subjectSet, ok := s.Subject.(*relationtuple.SubjectSet)
if !ok || subjectSet.Relation == WildcardRelation {
continue
}
g.Add(e.checkIsAllowed(
innerCtx,
&RelationTuple{
Namespace: s.Subject.SubjectSet().Namespace,
Object: s.Subject.SubjectSet().Object,
Relation: s.Subject.SubjectSet().Relation,
Namespace: subjectSet.Namespace,
Object: subjectSet.Object,
Relation: subjectSet.Relation,
Subject: r.Subject,
},
restDepth-1,
Expand Down Expand Up @@ -152,8 +153,8 @@ func (e *Engine) checkDirect(ctx context.Context, r *RelationTuple, restDepth in
if rels, _, err := e.d.RelationTupleManager().GetRelationTuples(ctx, r.ToQuery()); err == nil && len(rels) > 0 {
resultCh <- checkgroup.Result{
Membership: checkgroup.IsMember,
Tree: &expand.Tree{
Type: expand.Leaf,
Tree: &ketoapi.Tree[*relationtuple.RelationTuple]{
Type: ketoapi.TreeNodeLeaf,
Tuple: r,
},
}
Expand Down
35 changes: 31 additions & 4 deletions internal/check/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/ory/keto/internal/namespace"
"github.com/ory/keto/internal/relationtuple"
"github.com/ory/keto/internal/x"
"github.com/ory/keto/ketoapi"
)

type configProvider = config.Provider
Expand All @@ -39,6 +40,33 @@ func newDepsProvider(t *testing.T, namespaces []*namespace.Namespace, pageOpts .
}
}

func toUUID(s string) uuid.UUID {
return uuid.NewV5(uuid.Nil, s)
}

func tupleFromString(t *testing.T, s string) *relationtuple.RelationTuple {
rt, err := ketoapi.FromString(s)
require.NoError(t, err)
result := &relationtuple.RelationTuple{
Namespace: rt.Namespace,
Object: toUUID(rt.Object),
Relation: rt.Relation,
}
switch {
case rt.SubjectID != nil:
result.Subject = &relationtuple.SubjectID{ID: toUUID(*rt.SubjectID)}
case rt.SubjectSet != nil:
result.Subject = &relationtuple.SubjectSet{
Namespace: rt.SubjectSet.Namespace,
Object: toUUID(rt.SubjectSet.Object),
Relation: rt.SubjectSet.Relation,
}
default:
t.Fatal("invalid tuple")
}
return result
}

func TestEngine(t *testing.T) {
ctx := context.Background()

Expand All @@ -60,8 +88,7 @@ func TestEngine(t *testing.T) {

e := check.NewEngine(reg)

userHasAccess, err := relationtuple.InternalFromString("test:object#access@user")
require.NoError(t, err)
userHasAccess := tupleFromString(t, "test:object#access@user")

// global max-depth defaults to 5
assert.Equal(t, reg.Config(ctx).MaxReadDepth(), 5)
Expand Down Expand Up @@ -423,7 +450,7 @@ func TestEngine(t *testing.T) {
e := check.NewEngine(reg)

for i, user := range users {
t.Run("user="+user, func(t *testing.T) {
t.Run("user="+user.String(), func(t *testing.T) {
t.Skip() // TODO pagination
allowed, err := e.CheckIsMember(ctx, &relationtuple.RelationTuple{
Namespace: namesp,
Expand Down Expand Up @@ -530,7 +557,7 @@ func TestEngine(t *testing.T) {

e := check.NewEngine(reg)

stations := []string{sendlingerTor, odeonsplatz, centralStation}
stations := []uuid.UUID{sendlingerTor, odeonsplatz, centralStation}
res, err := e.CheckIsMember(ctx, &relationtuple.RelationTuple{
Namespace: namesp,
Object: stations[0],
Expand Down
57 changes: 29 additions & 28 deletions internal/check/rewrites.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,24 @@ import (
"github.com/pkg/errors"

"github.com/ory/keto/internal/check/checkgroup"
"github.com/ory/keto/internal/expand"
"github.com/ory/keto/internal/namespace/ast"
"github.com/ory/keto/internal/relationtuple"
"github.com/ory/keto/internal/x"
"github.com/ory/keto/ketoapi"
)

func checkNotImplemented(_ context.Context, resultCh chan<- checkgroup.Result) {
resultCh <- checkgroup.Result{Err: errors.WithStack(errors.New("not implemented"))}
}

func toExpandNodeType(op ast.Operator) expand.NodeType {
func toTreeNodeType(op ast.Operator) ketoapi.TreeNodeType {
switch op {
case ast.OperatorOr:
return expand.Union
return ketoapi.TreeNodeUnion
case ast.OperatorAnd:
return expand.Intersection
return ketoapi.TreeNodeIntersection
default:
return expand.Union
return ketoapi.TreeNodeUnion
}
}

Expand Down Expand Up @@ -60,25 +61,25 @@ func (e *Engine) checkUsersetRewrite(
case *ast.TupleToUserset:
checks = append(checks, checkgroup.WithEdge(checkgroup.Edge{
Tuple: *tuple,
Type: expand.TupeToUserset,
Type: ketoapi.TreeNodeTupeToUserset,
}, e.checkTupleToUserset(tuple, c, restDepth)))

case *ast.ComputedUserset:
checks = append(checks, checkgroup.WithEdge(checkgroup.Edge{
Tuple: *tuple,
Type: expand.ComputedUserset,
Type: ketoapi.TreeNodeComputedUserset,
}, e.checkComputedUserset(ctx, tuple, c, restDepth)))

case *ast.UsersetRewrite:
checks = append(checks, checkgroup.WithEdge(checkgroup.Edge{
Tuple: *tuple,
Type: toExpandNodeType(c.Operation),
Type: toTreeNodeType(c.Operation),
}, e.checkUsersetRewrite(ctx, tuple, c, restDepth)))

case *ast.InvertResult:
checks = append(checks, checkgroup.WithEdge(checkgroup.Edge{
Tuple: *tuple,
Type: expand.Not,
Type: ketoapi.TreeNodeNot,
}, e.checkInverted(ctx, tuple, c, restDepth)))

default:
Expand Down Expand Up @@ -113,25 +114,25 @@ func (e *Engine) checkInverted(
case *ast.TupleToUserset:
check = checkgroup.WithEdge(checkgroup.Edge{
Tuple: *tuple,
Type: expand.TupeToUserset,
Type: ketoapi.TreeNodeTupeToUserset,
}, e.checkTupleToUserset(tuple, c, restDepth))

case *ast.ComputedUserset:
check = checkgroup.WithEdge(checkgroup.Edge{
Tuple: *tuple,
Type: expand.ComputedUserset,
Type: ketoapi.TreeNodeComputedUserset,
}, e.checkComputedUserset(ctx, tuple, c, restDepth))

case *ast.UsersetRewrite:
check = checkgroup.WithEdge(checkgroup.Edge{
Tuple: *tuple,
Type: toExpandNodeType(c.Operation),
Type: toTreeNodeType(c.Operation),
}, e.checkUsersetRewrite(ctx, tuple, c, restDepth))

case *ast.InvertResult:
check = checkgroup.WithEdge(checkgroup.Edge{
Tuple: *tuple,
Type: expand.Not,
Type: ketoapi.TreeNodeNot,
}, e.checkInverted(ctx, tuple, c, restDepth))

default:
Expand Down Expand Up @@ -228,9 +229,9 @@ func (e *Engine) checkTupleToUserset(
tuples, nextPage, err = e.d.RelationTupleManager().GetRelationTuples(
ctx,
&Query{
Namespace: tuple.Namespace,
Object: tuple.Object,
Relation: userset.Relation,
Namespace: &tuple.Namespace,
Object: &tuple.Object,
Relation: &userset.Relation,
},
x.WithToken(prevPage))
if err != nil {
Expand All @@ -239,19 +240,19 @@ func (e *Engine) checkTupleToUserset(
}

for _, t := range tuples {
if t.Subject.SubjectSet() == nil {
continue
if subjectSet, ok := t.Subject.(*relationtuple.SubjectSet); ok {
g.Add(e.checkIsAllowed(
ctx,
&RelationTuple{
Namespace: subjectSet.Namespace,
Object: subjectSet.Object,
Relation: userset.ComputedUsersetRelation,
Subject: tuple.Subject,
},
restDepth-1,
))

}
g.Add(e.checkIsAllowed(
ctx,
&RelationTuple{
Namespace: t.Subject.SubjectSet().Namespace,
Object: t.Subject.SubjectSet().Object,
Relation: userset.ComputedUsersetRelation,
Subject: tuple.Subject,
},
restDepth-1,
))
}
}
resultCh <- g.Result()
Expand Down
Loading

0 comments on commit ecd4805

Please sign in to comment.