Skip to content

Commit

Permalink
test: expression ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
hperl committed Jun 4, 2024
1 parent 9c2ff04 commit f430843
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 0 deletions.
6 changes: 6 additions & 0 deletions internal/check/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ func BenchmarkCheckEngine(b *testing.B) {
//go:embed testfixtures/project_opl.ts
var ProjectOPLConfig string

//go:embed testfixtures/expression_ordering_1.ts
var ExpressionOrdering1 string

//go:embed testfixtures/expression_ordering_2.ts
var ExpressionOrdering2 string

func BenchmarkComputedUsersets(b *testing.B) {
ctx := context.Background()

Expand Down
34 changes: 34 additions & 0 deletions internal/check/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ func TestEngine(t *testing.T) {
})

t.Run("case=wide tuple graph", func(t *testing.T) {
t.Parallel()
namesp, obj, access, member, users, orgs := "9234", uuid.Must(uuid.NewV4()), "access", "member", x.UUIDs(4), x.UUIDs(2)

reg := newDepsProvider(t, []*namespace.Namespace{{Name: namesp}})
Expand Down Expand Up @@ -495,6 +496,7 @@ func TestEngine(t *testing.T) {
})

t.Run("case=circular tuples", func(t *testing.T) {
t.Parallel()
sendlingerTor, odeonsplatz, centralStation, connected, namesp := uuid.NewV5(uuid.Nil, "Sendlinger Tor"), uuid.NewV5(uuid.Nil, "Odeonsplatz"), uuid.NewV5(uuid.Nil, "Central Station"), "connected", "7743"

reg := newDepsProvider(t, []*namespace.Namespace{{Name: namesp}})
Expand Down Expand Up @@ -548,6 +550,8 @@ func TestEngine(t *testing.T) {
})

t.Run("case=strict mode", func(t *testing.T) {
t.Parallel()

reg := driver.NewSqliteTestRegistry(t, false,
driver.WithOPL(ProjectOPLConfig),
driver.WithConfig(config.KeyNamespacesExperimentalStrictMode, true))
Expand Down Expand Up @@ -576,4 +580,34 @@ func TestEngine(t *testing.T) {
assert.True(t, res)
}
})

t.Run("case=bug repro", func(t *testing.T) {
t.Parallel()

for _, tc := range []struct {
name string
opl string
}{
{"expression ordering 1", ExpressionOrdering1},
{"expression ordering 2", ExpressionOrdering2},
} {
tc := tc
t.Run("opl="+tc.name, func(t *testing.T) {
t.Parallel()

reg := driver.NewSqliteTestRegistry(t, false, driver.WithOPL(ExpressionOrdering1))

insertFixtures(t, reg.RelationTupleManager(), []string{
"LegalEntityUserGroup:group_123#owners@User:user_123",
"LegalEntity:legalentity_123#owners@LegalEntityUserGroup:group_123#owners",
})

e := check.NewEngine(reg)

res, err := e.CheckIsMember(ctx, tupleFromString(t, "LegalEntity:legalentity_123#itemView@User:user_123"), 10)
require.NoError(t, err)
assert.True(t, res)
})
}
})
}
46 changes: 46 additions & 0 deletions internal/check/testfixtures/expression_ordering_1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Context, Namespace, SubjectSet } from "@ory/keto-namespace-types"

class User implements Namespace {}

class LegalEntityUserGroup implements Namespace {
related: {
// predefined roles
owners: User[]
administrators: User[]
creators: User[]
viewers: User[]
members: User[]
}
}

class BlockedUserGroup implements Namespace {
related: {
blockedUsers: User[]
}
}

class LegalEntity implements Namespace {
related: {
// pre-deifned roles
owners: SubjectSet<LegalEntityUserGroup, "owners">[]
administrators: SubjectSet<LegalEntityUserGroup, "administrators">[]
creators: SubjectSet<LegalEntityUserGroup, "creators">[]
viewers: SubjectSet<LegalEntityUserGroup, "viewers">[]
members: SubjectSet<LegalEntityUserGroup, "members">[]
blockedUsers: SubjectSet<BlockedUserGroup, "blockedUsers">[]
}

permits = {
own: (ctx: Context): boolean =>
!this.related.blockedUsers.includes(ctx.subject) &&
this.related.owners.includes(ctx.subject),

itemView: (ctx: Context): boolean =>
!this.related.blockedUsers.includes(ctx.subject) &&
(this.related.administrators.includes(ctx.subject) ||
this.related.creators.includes(ctx.subject) ||
this.related.viewers.includes(ctx.subject) ||
this.related.owners.includes(ctx.subject) || // ⚠️ move this line up and it it won't work.
this.related.members.includes(ctx.subject)),
}
}
46 changes: 46 additions & 0 deletions internal/check/testfixtures/expression_ordering_2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Context, Namespace, SubjectSet } from "@ory/keto-namespace-types"

class User implements Namespace {}

class LegalEntityUserGroup implements Namespace {
related: {
// predefined roles
owners: User[]
administrators: User[]
creators: User[]
viewers: User[]
members: User[]
}
}

class BlockedUserGroup implements Namespace {
related: {
blockedUsers: User[]
}
}

class LegalEntity implements Namespace {
related: {
// pre-deifned roles
owners: SubjectSet<LegalEntityUserGroup, "owners">[]
administrators: SubjectSet<LegalEntityUserGroup, "administrators">[]
creators: SubjectSet<LegalEntityUserGroup, "creators">[]
viewers: SubjectSet<LegalEntityUserGroup, "viewers">[]
members: SubjectSet<LegalEntityUserGroup, "members">[]
blockedUsers: SubjectSet<BlockedUserGroup, "blockedUsers">[]
}

permits = {
own: (ctx: Context): boolean =>
!this.related.blockedUsers.includes(ctx.subject) &&
this.related.owners.includes(ctx.subject),

itemView: (ctx: Context): boolean =>
!this.related.blockedUsers.includes(ctx.subject) &&
(this.related.owners.includes(ctx.subject) || // ⚠️ move this line up and it it won't work.
this.related.administrators.includes(ctx.subject) ||
this.related.creators.includes(ctx.subject) ||
this.related.viewers.includes(ctx.subject) ||
this.related.members.includes(ctx.subject)),
}
}

0 comments on commit f430843

Please sign in to comment.