diff --git a/e2e/go.mod b/e2e/go.mod index 262e071f9a..8abeb0531d 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -3,7 +3,7 @@ module github.com/authzed/spicedb/e2e go 1.17 require ( - github.com/authzed/authzed-go v0.3.1-0.20211220220442-a36f72252b43 + github.com/authzed/authzed-go v0.4.1 github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6 github.com/authzed/spicedb v0.0.0 github.com/brianvoe/gofakeit/v6 v6.10.0 diff --git a/e2e/go.sum b/e2e/go.sum index 6323c43104..c35f77653a 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -72,8 +72,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/authzed/authzed-go v0.3.1-0.20211220220442-a36f72252b43 h1:hnMt/mitjkBq6OKGAtSxCvbQSGNy0c8sBhyPy/NIy+w= -github.com/authzed/authzed-go v0.3.1-0.20211220220442-a36f72252b43/go.mod h1:bsUniBRroq4l5WZMYLO+T9osQa/P2qMwZ+Af8zoJK8Y= +github.com/authzed/authzed-go v0.4.1 h1:EVTP1ZXGnZ8sA8Ojqi5k9Io/nsbaH7lSNqPLiUgwvPE= +github.com/authzed/authzed-go v0.4.1/go.mod h1:bsUniBRroq4l5WZMYLO+T9osQa/P2qMwZ+Af8zoJK8Y= github.com/authzed/grpcutil v0.0.0-20210913124023-cad23ae5a9e8/go.mod h1:HwO/KbRU3fWXEYHE96kvXnwxzi97tkXD1hfi5UaZ71Y= github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6 h1:izP/rEris51ZmomXb5J0ShyJKqsxTfVKDRnJz0QGbgg= github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6/go.mod h1:rqjY3zyK/YP7NID9+B2BdIRRkvnK+cdf9/qya/zaFZE= diff --git a/e2e/newenemy/newenemy_test.go b/e2e/newenemy/newenemy_test.go index a20a9c5540..977eea6313 100644 --- a/e2e/newenemy/newenemy_test.go +++ b/e2e/newenemy/newenemy_test.go @@ -57,7 +57,7 @@ definition {{.}}/resource { const ( objIDRegex = "[a-zA-Z0-9_][a-zA-Z0-9/_-]{0,127}" - namespacePrefixRegex = "[a-z][a-z0-9_]{2,62}[a-z0-9]" + namespacePrefixRegex = "[a-z][a-z0-9_]{1,62}[a-z0-9]" ) var ( diff --git a/go.mod b/go.mod index 4a64c3c288..ec9deec08b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/Masterminds/squirrel v1.5.2 github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a - github.com/authzed/authzed-go v0.3.1-0.20211220220442-a36f72252b43 + github.com/authzed/authzed-go v0.4.1 github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6 github.com/aws/aws-sdk-go v1.42.25 github.com/benbjohnson/clock v1.3.0 diff --git a/go.sum b/go.sum index dca7f4a2e9..0b59af0193 100644 --- a/go.sum +++ b/go.sum @@ -79,8 +79,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/authzed/authzed-go v0.3.1-0.20211220220442-a36f72252b43 h1:hnMt/mitjkBq6OKGAtSxCvbQSGNy0c8sBhyPy/NIy+w= -github.com/authzed/authzed-go v0.3.1-0.20211220220442-a36f72252b43/go.mod h1:bsUniBRroq4l5WZMYLO+T9osQa/P2qMwZ+Af8zoJK8Y= +github.com/authzed/authzed-go v0.4.1 h1:EVTP1ZXGnZ8sA8Ojqi5k9Io/nsbaH7lSNqPLiUgwvPE= +github.com/authzed/authzed-go v0.4.1/go.mod h1:bsUniBRroq4l5WZMYLO+T9osQa/P2qMwZ+Af8zoJK8Y= github.com/authzed/grpcutil v0.0.0-20210913124023-cad23ae5a9e8/go.mod h1:HwO/KbRU3fWXEYHE96kvXnwxzi97tkXD1hfi5UaZ71Y= github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6 h1:izP/rEris51ZmomXb5J0ShyJKqsxTfVKDRnJz0QGbgg= github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6/go.mod h1:rqjY3zyK/YP7NID9+B2BdIRRkvnK+cdf9/qya/zaFZE= diff --git a/internal/datastore/test/namespace.go b/internal/datastore/test/namespace.go index 111415cd46..4169ae0181 100644 --- a/internal/datastore/test/namespace.go +++ b/internal/datastore/test/namespace.go @@ -17,7 +17,7 @@ import ( ) var ( - testNamespace = ns.Namespace("test/test", + testNamespace = ns.Namespace("foo/bar", ns.Relation("editor", nil, ns.AllowedRelation(testUserNS.Name, "...")), ) diff --git a/internal/services/testconfigs/3letterrbac.yaml b/internal/services/testconfigs/3letterrbac.yaml new file mode 100644 index 0000000000..76edcf65c7 --- /dev/null +++ b/internal/services/testconfigs/3letterrbac.yaml @@ -0,0 +1,41 @@ +--- +namespace_configs: + - | + name: "exm/usr" + + - | + name: "exm/doc" + + relation { + name: "wri" + + type_information { + allowed_direct_relations { + namespace: "exm/usr" + relation: "..." + } + } + } + + relation { + name: "red" + + userset_rewrite { + union { + child { _this {} } + child { computed_userset { relation: "wri" } } + } + } + + type_information { + allowed_direct_relations { + namespace: "exm/usr" + relation: "..." + } + } + } + +validation_tuples: + - "exm/doc:firstdoc#wri@exm/usr:tom#..." + - "exm/doc:firstdoc#red@exm/usr:fred#..." + - "exm/doc:seconddoc#red@exm/usr:tom#..." diff --git a/internal/services/v0/developer_test.go b/internal/services/v0/developer_test.go index 3b6a58a38d..a2f177a2d1 100644 --- a/internal/services/v0/developer_test.go +++ b/internal/services/v0/developer_test.go @@ -108,11 +108,11 @@ func TestEditCheck(t *testing.T) { }, { "invalid namespace name", - `definition foo {}`, + `definition fo {}`, []*v0.RelationTuple{}, []*v0.RelationTuple{}, &v0.DeveloperError{ - Message: "parse error in `schema`, line 1, column 1: error in object definition foo: invalid NamespaceDefinition.Name: value does not match regex pattern \"^([a-z][a-z0-9_]{2,62}[a-z0-9]/)?[a-z][a-z0-9_]{2,62}[a-z0-9]$\"", + Message: "parse error in `schema`, line 1, column 1: error in object definition fo: invalid NamespaceDefinition.Name: value does not match regex pattern \"^([a-z][a-z0-9_]{1,62}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$\"", Kind: v0.DeveloperError_SCHEMA_ISSUE, Source: v0.DeveloperError_SCHEMA, Line: 1, @@ -732,7 +732,7 @@ func TestDeveloperValidateONR(t *testing.T) { require.NoError(err) require.Equal(1, len(resp.RequestErrors)) require.Equal(&v0.DeveloperError{ - Message: "invalid RelationTuple.ObjectAndRelation: embedded message failed validation | caused by: invalid ObjectAndRelation.Relation: value does not match regex pattern \"^(\\\\.\\\\.\\\\.|[a-z][a-z0-9_]{2,62}[a-z0-9])$\"", + Message: "invalid RelationTuple.ObjectAndRelation: embedded message failed validation | caused by: invalid ObjectAndRelation.Relation: value does not match regex pattern \"^(\\\\.\\\\.\\\\.|[a-z][a-z0-9_]{1,62}[a-z0-9])$\"", Kind: v0.DeveloperError_PARSE_ERROR, Source: v0.DeveloperError_RELATIONSHIP, Context: `document:somedoc#writerIsNotValid@user:jimmy`, diff --git a/pkg/schemadsl/compiler/compiler_test.go b/pkg/schemadsl/compiler/compiler_test.go index 8b4c93ecf1..9179bf2818 100644 --- a/pkg/schemadsl/compiler/compiler_test.go +++ b/pkg/schemadsl/compiler/compiler_test.go @@ -48,23 +48,23 @@ func TestCompile(t *testing.T) { { "empty def", &someTenant, - `definition empty {}`, + `definition def {}`, "", []*v0.NamespaceDefinition{ - namespace.Namespace("sometenant/empty"), + namespace.Namespace("sometenant/def"), }, }, { "simple def", &someTenant, `definition simple { - relation foos: bars; + relation foo: bar; }`, "", []*v0.NamespaceDefinition{ namespace.Namespace("sometenant/simple", - namespace.Relation("foos", nil, - namespace.AllowedRelation("sometenant/bars", "..."), + namespace.Relation("foo", nil, + namespace.AllowedRelation("sometenant/bar", "..."), ), ), }, @@ -413,17 +413,17 @@ func TestCompile(t *testing.T) { { "invalid definition name", nil, - `definition someTenant/foo {}`, - "parse error in `invalid definition name`, line 1, column 1: error in object definition someTenant/foo: invalid NamespaceDefinition.Name: value does not match regex pattern \"^([a-z][a-z0-9_]{2,62}[a-z0-9]/)?[a-z][a-z0-9_]{2,62}[a-z0-9]$\"", + `definition someTenant/fo {}`, + "parse error in `invalid definition name`, line 1, column 1: error in object definition someTenant/fo: invalid NamespaceDefinition.Name: value does not match regex pattern \"^([a-z][a-z0-9_]{1,62}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$\"", []*v0.NamespaceDefinition{}, }, { "invalid relation name", nil, `definition some_tenant/foos { - relation bar: some_tenant/foos + relation ab: some_tenant/foos }`, - "parse error in `invalid relation name`, line 2, column 5: error in relation bar: invalid Relation.Name: value does not match regex pattern \"^[a-z][a-z0-9_]{2,62}[a-z0-9]$\"", + "parse error in `invalid relation name`, line 2, column 5: error in relation ab: invalid Relation.Name: value does not match regex pattern \"^[a-z][a-z0-9_]{1,62}[a-z0-9]$\"", []*v0.NamespaceDefinition{}, }, { diff --git a/pkg/tuple/tuple.go b/pkg/tuple/tuple.go index 1585938c30..2c077a5118 100644 --- a/pkg/tuple/tuple.go +++ b/pkg/tuple/tuple.go @@ -19,10 +19,10 @@ const ( ) const ( - namespaceNameExpr = "([a-z][a-z0-9_]{2,61}[a-z0-9]/)?[a-z][a-z0-9_]{2,62}[a-z0-9]" + namespaceNameExpr = "([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]" resourceIDExpr = "[a-zA-Z0-9_][a-zA-Z0-9/_-]{0,127}" subjectIDExpr = "([a-zA-Z0-9_][a-zA-Z0-9/_-]{0,127})|\\*" - relationExpr = "[a-z][a-z0-9_]{2,62}[a-z0-9]" + relationExpr = "[a-z][a-z0-9_]{1,62}[a-z0-9]" ) var onrExpr = fmt.Sprintf( diff --git a/pkg/validation/identifiers.go b/pkg/validation/identifiers.go deleted file mode 100644 index 3320386792..0000000000 --- a/pkg/validation/identifiers.go +++ /dev/null @@ -1,69 +0,0 @@ -package validation - -import ( - "errors" - "fmt" - "regexp" -) - -const identifier = "[a-z][a-z0-9_]{2,62}[a-z0-9]" - -var ( - // ObjectNameRegex is the regular expression used to validate the object IDs. - ObjectNameRegex = regexp.MustCompile("^[a-zA-Z0-9/_-]{2,64}$") - - // RelationNameRegex is the regular expression used to validate the names of relations. - RelationNameRegex = regexp.MustCompile(fmt.Sprintf(`^(\.\.\.|%s)$`, identifier)) - - // NamespaceRegex is the regular expression used to validate namespace names. - NamespaceRegex = regexp.MustCompile(fmt.Sprintf("^(%s/)?%s$", identifier, identifier)) - - // NamespaceRegex is the regular expression used to validate namespace names - // that require tenant slugs. - NamespaceWithTenantRegex = regexp.MustCompile(fmt.Sprintf("^(%s)/(%s)$", identifier, identifier)) - - ErrInvalidObjectName = errors.New("invalid object name") - ErrInvalidRelationName = errors.New("invalid relation name") - ErrInvalidNamespaceName = errors.New("invalid namespace name") -) - -// ObjectName validates that the string provided is a valid object name. -func ObjectName(name string) error { - matched := ObjectNameRegex.MatchString(name) - if !matched { - return ErrInvalidObjectName - } - - return nil -} - -// RelationName validates that the string provided is a valid relation name. -func RelationName(name string) error { - matched := RelationNameRegex.MatchString(name) - if !matched { - return ErrInvalidRelationName - } - - return nil -} - -// NamespaceName validates that the string provided is a valid namespace name. -func NamespaceName(name string) error { - matched := NamespaceRegex.MatchString(name) - if !matched { - return ErrInvalidNamespaceName - } - - return nil -} - -// NamespaceNameWithTenant validates that the string provided is a valid namespace -// name and contains a tenant component. -func NamespaceNameWithTenant(name string) error { - matched := NamespaceWithTenantRegex.MatchString(name) - if !matched { - return ErrInvalidNamespaceName - } - - return nil -} diff --git a/pkg/validation/identifiers_test.go b/pkg/validation/identifiers_test.go deleted file mode 100644 index 6754246bf9..0000000000 --- a/pkg/validation/identifiers_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package validation - -import ( - "fmt" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestRelationName(t *testing.T) { - testCases := []struct { - name string - expectedError error - }{ - {"", ErrInvalidRelationName}, - {"...", nil}, - {"foo", ErrInvalidRelationName}, - {"bar", ErrInvalidRelationName}, - {"foo1", nil}, - {"bar1", nil}, - {"ab", ErrInvalidRelationName}, - {"Foo1", ErrInvalidRelationName}, - {"foo_bar", nil}, - {"foo_bar_", ErrInvalidRelationName}, - {"foo/bar", ErrInvalidRelationName}, - {"foo/b", ErrInvalidRelationName}, - {"Foo/bar", ErrInvalidRelationName}, - {"foo/bar/baz", ErrInvalidRelationName}, - {strings.Repeat("f", 3), ErrInvalidRelationName}, - {strings.Repeat("f", 4), nil}, - {strings.Repeat("\u0394", 4), ErrInvalidRelationName}, - {strings.Repeat("\n", 4), ErrInvalidRelationName}, - {strings.Repeat("_", 4), ErrInvalidRelationName}, - {strings.Repeat("-", 4), ErrInvalidRelationName}, - {strings.Repeat("/", 4), ErrInvalidRelationName}, - {strings.Repeat("\\", 4), ErrInvalidRelationName}, - {strings.Repeat("f", 64), nil}, - {strings.Repeat("f", 65), ErrInvalidRelationName}, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - require := require.New(t) - - require.Equal(tc.expectedError, RelationName(tc.name)) - }) - } -} - -func TestNamespaceName(t *testing.T) { - testCases := []struct { - name string - expectedError error - expectedRequireTenant error - }{ - {"", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"...", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"foo", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"bar", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"foo1", nil, ErrInvalidNamespaceName}, - {"bar1", nil, ErrInvalidNamespaceName}, - {"ab", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"Foo1", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"foo_bar", nil, ErrInvalidNamespaceName}, - {"foo_bar_", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"foo/bar", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"foo/b", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"Foo/bar", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {"foo/bar/baz", ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("f", 3), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("f", 4), nil, ErrInvalidNamespaceName}, - {strings.Repeat("\u0394", 4), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("\n", 4), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("_", 4), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("-", 4), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("/", 4), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("\\", 4), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("f", 64), nil, ErrInvalidNamespaceName}, - {fmt.Sprintf("%s/%s", strings.Repeat("f", 63), strings.Repeat("f", 63)), nil, nil}, - {fmt.Sprintf("%s/%s", strings.Repeat("f", 64), strings.Repeat("f", 64)), nil, nil}, - {fmt.Sprintf("%s/%s", strings.Repeat("f", 65), strings.Repeat("f", 64)), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {fmt.Sprintf("%s/%s", strings.Repeat("f", 64), strings.Repeat("f", 65)), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - {strings.Repeat("f", 65), ErrInvalidNamespaceName, ErrInvalidNamespaceName}, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - require := require.New(t) - - require.Equal(tc.expectedError, NamespaceName(tc.name)) - require.Equal(tc.expectedRequireTenant, NamespaceNameWithTenant(tc.name)) - }) - } -} diff --git a/pkg/validation/namespace_test.go b/pkg/validation/namespace_test.go deleted file mode 100644 index 6be8cfef8c..0000000000 --- a/pkg/validation/namespace_test.go +++ /dev/null @@ -1,256 +0,0 @@ -package validation - -import ( - "testing" - - v0 "github.com/authzed/authzed-go/proto/authzed/api/v0" - "github.com/stretchr/testify/require" - - ns "github.com/authzed/spicedb/pkg/namespace" -) - -func TestNamespaceValidation(t *testing.T) { - testCases := []struct { - name string - expectError bool - config *v0.NamespaceDefinition - }{ - {"empty", true, &v0.NamespaceDefinition{}}, - {"simple", false, ns.Namespace("user")}, - {"full", false, ns.Namespace( - "document", - ns.Relation("owner", nil), - ns.Relation("editor", ns.Union( - ns.This(), - ns.ComputedUserset("owner"), - )), - ns.Relation("parent", nil), - ns.Relation("lock", nil), - ns.Relation("viewer", ns.Union( - ns.This(), - ns.ComputedUserset("editor"), - ns.TupleToUserset("parent", "viewer"), - )), - )}, - {"working intersection", false, ns.Namespace( - "document", - ns.Relation("editor", ns.Intersection( - ns.This(), - ns.ComputedUserset("owner"), - )), - )}, - {"working exclusion", false, ns.Namespace( - "document", - ns.Relation("editor", ns.Exclusion( - ns.This(), - ns.ComputedUserset("owner"), - )), - )}, - {"bad relation name", true, ns.Namespace( - "document", - ns.Relation("a", nil), - )}, - {"bad rewrite", true, ns.Namespace( - "document", - ns.Relation("editor", &v0.UsersetRewrite{}), - )}, - {"nil union", true, ns.Namespace( - "document", - ns.Relation("editor", &v0.UsersetRewrite{ - RewriteOperation: &v0.UsersetRewrite_Union{}, - }), - )}, - {"no children", true, ns.Namespace( - "document", - ns.Relation("editor", &v0.UsersetRewrite{ - RewriteOperation: &v0.UsersetRewrite_Union{ - Union: &v0.SetOperation{}, - }, - }), - )}, - {"empty child", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_TupleToUserset{}, - }, - )), - )}, - {"nil child pointer", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - nil, - )), - )}, - {"nil child", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{}, - )), - )}, - {"bad ttu", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_TupleToUserset{ - TupleToUserset: &v0.TupleToUserset{}, - }, - }, - )), - )}, - {"ttu missing tupleset", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_TupleToUserset{ - TupleToUserset: &v0.TupleToUserset{ - ComputedUserset: &v0.ComputedUserset{ - Object: v0.ComputedUserset_TUPLE_USERSET_OBJECT, - Relation: "admin", - }, - }, - }, - }, - )), - )}, - {"ttu missing rewrite", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_TupleToUserset{ - TupleToUserset: &v0.TupleToUserset{ - Tupleset: &v0.TupleToUserset_Tupleset{ - Relation: "parent", - }, - }, - }, - }, - )), - )}, - {"ttu bad relation", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_TupleToUserset{ - TupleToUserset: &v0.TupleToUserset{ - Tupleset: &v0.TupleToUserset_Tupleset{ - Relation: "", - }, - ComputedUserset: &v0.ComputedUserset{ - Object: v0.ComputedUserset_TUPLE_USERSET_OBJECT, - Relation: "admin", - }, - }, - }, - }, - )), - )}, - {"ttu bad computed relation", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_TupleToUserset{ - TupleToUserset: &v0.TupleToUserset{ - Tupleset: &v0.TupleToUserset_Tupleset{ - Relation: "parent", - }, - ComputedUserset: &v0.ComputedUserset{ - Object: v0.ComputedUserset_TUPLE_USERSET_OBJECT, - Relation: "", - }, - }, - }, - }, - )), - )}, - {"ttu nil computed relation", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_TupleToUserset{ - TupleToUserset: &v0.TupleToUserset{ - Tupleset: &v0.TupleToUserset_Tupleset{ - Relation: "parent", - }, - ComputedUserset: &v0.ComputedUserset{ - Object: v0.ComputedUserset_TUPLE_USERSET_OBJECT, - }, - }, - }, - }, - )), - )}, - {"empty cu", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_ComputedUserset{}, - }, - )), - )}, - {"cu empty relation", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_ComputedUserset{ - ComputedUserset: &v0.ComputedUserset{}, - }, - }, - )), - )}, - {"cu bad relation name", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_ComputedUserset{ - ComputedUserset: &v0.ComputedUserset{ - Relation: "ab", - }, - }, - }, - )), - )}, - {"cu bad object type", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_ComputedUserset{ - ComputedUserset: &v0.ComputedUserset{ - Relation: "admin", - Object: 3, - }, - }, - }, - )), - )}, - {"child nil rewrite", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_UsersetRewrite{}, - }, - )), - )}, - {"child bad rewrite", true, ns.Namespace( - "document", - ns.Relation("viewer", ns.Union( - &v0.SetOperation_Child{ - ChildType: &v0.SetOperation_Child_UsersetRewrite{ - UsersetRewrite: &v0.UsersetRewrite{}, - }, - }, - )), - )}, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - err := tc.config.Validate() - if tc.expectError { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -}