Skip to content

Commit

Permalink
Merge pull request #2027 from josephschorr/caveat-check-fix
Browse files Browse the repository at this point in the history
Ensure all resources are returned for relation check when caveats are specified
  • Loading branch information
josephschorr authored Aug 15, 2024
2 parents 4b587c0 + 20855de commit d4ef8e1
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 11 deletions.
133 changes: 124 additions & 9 deletions internal/dispatch/graph/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,14 @@ func TestCheckMetadata(t *testing.T) {

func TestCheckPermissionOverSchema(t *testing.T) {
testCases := []struct {
name string
schema string
relationships []*core.RelationTuple
resource *core.ObjectAndRelation
subject *core.ObjectAndRelation
expectedPermissionship v1.ResourceCheckResult_Membership
expectedCaveat *core.CaveatExpression
name string
schema string
relationships []*core.RelationTuple
resource *core.ObjectAndRelation
subject *core.ObjectAndRelation
expectedPermissionship v1.ResourceCheckResult_Membership
expectedCaveat *core.CaveatExpression
alternativeExpectedCaveat *core.CaveatExpression
}{
{
"basic union",
Expand All @@ -312,6 +313,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"basic intersection",
Expand All @@ -330,6 +332,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"basic exclusion",
Expand All @@ -347,6 +350,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"basic union, multiple branches",
Expand All @@ -365,6 +369,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"basic union no permission",
Expand All @@ -380,6 +385,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"basic intersection no permission",
Expand All @@ -397,6 +403,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"basic exclusion no permission",
Expand All @@ -415,6 +422,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"exclusion with multiple branches",
Expand All @@ -441,6 +449,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"intersection with multiple branches",
Expand All @@ -467,6 +476,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"exclusion with multiple branches no permission",
Expand Down Expand Up @@ -494,6 +504,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"intersection with multiple branches no permission",
Expand All @@ -519,6 +530,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"basic arrow",
Expand All @@ -541,6 +553,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"basic any arrow",
Expand All @@ -563,6 +576,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"basic all arrow negative",
Expand All @@ -585,6 +599,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"basic all arrow positive",
Expand All @@ -608,6 +623,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"basic all arrow positive with different types",
Expand Down Expand Up @@ -635,6 +651,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"basic all arrow negative over different types",
Expand Down Expand Up @@ -663,6 +680,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"basic all arrow positive over different types",
Expand Down Expand Up @@ -692,6 +710,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"all arrow for single org",
Expand All @@ -713,6 +732,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"all arrow for no orgs",
Expand All @@ -733,6 +753,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"view_by_all negative",
Expand Down Expand Up @@ -766,6 +787,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "fred", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"view_by_any positive",
Expand Down Expand Up @@ -801,6 +823,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "fred", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"view_by_any positive directly",
Expand Down Expand Up @@ -836,6 +859,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "rachel", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"caveated intersection arrow",
Expand All @@ -862,6 +886,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_CAVEATED_MEMBER,
caveatAndCtx("somecaveat", nil),
nil,
},
{
"intersection arrow with caveated member",
Expand All @@ -888,6 +913,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_CAVEATED_MEMBER,
caveatAndCtx("somecaveat", nil),
nil,
},
{
"caveated intersection arrow with caveated member",
Expand All @@ -914,6 +940,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_CAVEATED_MEMBER,
caveatAndCtx("somecaveat", nil),
nil,
},
{
"caveated intersection arrow with caveated member, different context",
Expand Down Expand Up @@ -947,6 +974,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
caveatAndCtx("anothercaveat", map[string]any{"someparam": int64(43)}),
caveatAndCtx("somecaveat", map[string]any{"someparam": int64(42)}),
),
nil,
},
{
"caveated intersection arrow with multiple caveated branches",
Expand Down Expand Up @@ -978,8 +1006,8 @@ func TestCheckPermissionOverSchema(t *testing.T) {
caveatAndCtx("somecaveat", map[string]any{"someparam": int64(41)}),
caveatAndCtx("somecaveat", map[string]any{"someparam": int64(42)}),
),
nil,
},

{
"caveated intersection arrow with multiple caveated members",
`definition user {}
Expand Down Expand Up @@ -1010,6 +1038,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
caveatAndCtx("somecaveat", map[string]any{"someparam": int64(41)}),
caveatAndCtx("somecaveat", map[string]any{"someparam": int64(42)}),
),
nil,
},
{
"caveated intersection arrow with one caveated branch",
Expand Down Expand Up @@ -1038,6 +1067,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_CAVEATED_MEMBER,
caveatAndCtx("somecaveat", map[string]any{"someparam": int64(42)}),
nil,
},
{
"caveated intersection arrow with one caveated member",
Expand Down Expand Up @@ -1066,6 +1096,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_CAVEATED_MEMBER,
caveatAndCtx("somecaveat", map[string]any{"someparam": int64(42)}),
nil,
},
{
"caveated intersection arrow multiple paths to the same subject",
Expand Down Expand Up @@ -1093,6 +1124,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_CAVEATED_MEMBER,
caveatAndCtx("somecaveat", nil),
nil,
},
{
"recursive all arrow positive result",
Expand Down Expand Up @@ -1129,6 +1161,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "fred", "..."),
v1.ResourceCheckResult_MEMBER,
nil,
nil,
},
{
"recursive all arrow negative result",
Expand Down Expand Up @@ -1165,6 +1198,7 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "tom", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"recursive all arrow negative result due to recursion missing a folder",
Expand Down Expand Up @@ -1202,6 +1236,79 @@ func TestCheckPermissionOverSchema(t *testing.T) {
ONR("user", "fred", "..."),
v1.ResourceCheckResult_NOT_MEMBER,
nil,
nil,
},
{
"caveated over multiple branches",
`
caveat somecaveat(somevalue int) {
somevalue == 42
}
definition user {}
definition role {
relation member: user
}
definition resource {
relation viewer: role#member with somecaveat
permission view = viewer
}
`,
[]*core.RelationTuple{
tuple.MustParse(`role:firstrole#member@user:tom[somecaveat:{"somevalue":40}]`),
tuple.MustParse(`role:secondrole#member@user:tom[somecaveat:{"somevalue":42}]`),
tuple.MustParse(`resource:doc1#viewer@role:firstrole#member`),
tuple.MustParse(`resource:doc1#viewer@role:secondrole#member`),
},
ONR("resource", "doc1", "view"),
ONR("user", "tom", "..."),
v1.ResourceCheckResult_CAVEATED_MEMBER,
caveatOr(
caveatAndCtx("somecaveat", map[string]any{"somevalue": int64(40)}),
caveatAndCtx("somecaveat", map[string]any{"somevalue": int64(42)}),
),
caveatOr(
caveatAndCtx("somecaveat", map[string]any{"somevalue": int64(42)}),
caveatAndCtx("somecaveat", map[string]any{"somevalue": int64(40)}),
),
},
{
"caveated over multiple branches reversed",
`
caveat somecaveat(somevalue int) {
somevalue == 42
}
definition user {}
definition role {
relation member: user
}
definition resource {
relation viewer: role#member with somecaveat
permission view = viewer
}
`,
[]*core.RelationTuple{
tuple.MustParse(`role:secondrole#member@user:tom[somecaveat:{"somevalue":42}]`),
tuple.MustParse(`role:firstrole#member@user:tom[somecaveat:{"somevalue":40}]`),
tuple.MustParse(`resource:doc1#viewer@role:secondrole#member`),
tuple.MustParse(`resource:doc1#viewer@role:firstrole#member`),
},
ONR("resource", "doc1", "view"),
ONR("user", "tom", "..."),
v1.ResourceCheckResult_CAVEATED_MEMBER,
caveatOr(
caveatAndCtx("somecaveat", map[string]any{"somevalue": int64(40)}),
caveatAndCtx("somecaveat", map[string]any{"somevalue": int64(42)}),
),
caveatOr(
caveatAndCtx("somecaveat", map[string]any{"somevalue": int64(42)}),
caveatAndCtx("somecaveat", map[string]any{"somevalue": int64(40)}),
),
},
}

Expand Down Expand Up @@ -1239,10 +1346,18 @@ func TestCheckPermissionOverSchema(t *testing.T) {

require.Equal(tc.expectedPermissionship, membership)

if tc.expectedCaveat != nil {
if tc.expectedCaveat != nil && tc.alternativeExpectedCaveat == nil {
require.NotEmpty(resp.ResultsByResourceId[tc.resource.ObjectId].Expression)
testutil.RequireProtoEqual(t, tc.expectedCaveat, resp.ResultsByResourceId[tc.resource.ObjectId].Expression, "mismatch in caveat")
}

if tc.expectedCaveat != nil && tc.alternativeExpectedCaveat != nil {
require.NotEmpty(resp.ResultsByResourceId[tc.resource.ObjectId].Expression)

if testutil.AreProtoEqual(tc.expectedCaveat, resp.ResultsByResourceId[tc.resource.ObjectId].Expression, "mismatch in caveat") != nil {
testutil.RequireProtoEqual(t, tc.alternativeExpectedCaveat, resp.ResultsByResourceId[tc.resource.ObjectId].Expression, "mismatch in caveat")
}
}
})
}
}
Expand Down
Loading

0 comments on commit d4ef8e1

Please sign in to comment.