summaryrefslogtreecommitdiff
path: root/vendor/github.com/authzed/spicedb/pkg/namespace
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-22 17:35:49 -0600
committermo khan <mo@mokhan.ca>2025-07-22 17:35:49 -0600
commit20ef0d92694465ac86b550df139e8366a0a2b4fa (patch)
tree3f14589e1ce6eb9306a3af31c3a1f9e1af5ed637 /vendor/github.com/authzed/spicedb/pkg/namespace
parent44e0d272c040cdc53a98b9f1dc58ae7da67752e6 (diff)
feat: connect to spicedb
Diffstat (limited to 'vendor/github.com/authzed/spicedb/pkg/namespace')
-rw-r--r--vendor/github.com/authzed/spicedb/pkg/namespace/builder.go340
-rw-r--r--vendor/github.com/authzed/spicedb/pkg/namespace/doc.go2
-rw-r--r--vendor/github.com/authzed/spicedb/pkg/namespace/mapper.go27
-rw-r--r--vendor/github.com/authzed/spicedb/pkg/namespace/metadata.go110
4 files changed, 479 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/spicedb/pkg/namespace/builder.go b/vendor/github.com/authzed/spicedb/pkg/namespace/builder.go
new file mode 100644
index 0000000..cf4c745
--- /dev/null
+++ b/vendor/github.com/authzed/spicedb/pkg/namespace/builder.go
@@ -0,0 +1,340 @@
+package namespace
+
+import (
+ "github.com/authzed/spicedb/pkg/caveats"
+ core "github.com/authzed/spicedb/pkg/proto/core/v1"
+ iv1 "github.com/authzed/spicedb/pkg/proto/impl/v1"
+ "github.com/authzed/spicedb/pkg/spiceerrors"
+)
+
+// Namespace creates a namespace definition with one or more defined relations.
+func Namespace(name string, relations ...*core.Relation) *core.NamespaceDefinition {
+ return &core.NamespaceDefinition{
+ Name: name,
+ Relation: relations,
+ }
+}
+
+// WithComment creates a namespace definition with one or more defined relations.
+func WithComment(name string, comment string, relations ...*core.Relation) *core.NamespaceDefinition {
+ nd := Namespace(name, relations...)
+ nd.Metadata, _ = AddComment(nd.Metadata, comment)
+ return nd
+}
+
+// MustRelation creates a relation definition with an optional rewrite definition.
+func MustRelation(name string, rewrite *core.UsersetRewrite, allowedDirectRelations ...*core.AllowedRelation) *core.Relation {
+ r, err := Relation(name, rewrite, allowedDirectRelations...)
+ if err != nil {
+ panic(err)
+ }
+ return r
+}
+
+// Relation creates a relation definition with an optional rewrite definition.
+func Relation(name string, rewrite *core.UsersetRewrite, allowedDirectRelations ...*core.AllowedRelation) (*core.Relation, error) {
+ var typeInfo *core.TypeInformation
+ if len(allowedDirectRelations) > 0 {
+ typeInfo = &core.TypeInformation{
+ AllowedDirectRelations: allowedDirectRelations,
+ }
+ }
+
+ rel := &core.Relation{
+ Name: name,
+ UsersetRewrite: rewrite,
+ TypeInformation: typeInfo,
+ }
+
+ switch {
+ case rewrite != nil && len(allowedDirectRelations) == 0:
+ if err := SetRelationKind(rel, iv1.RelationMetadata_PERMISSION); err != nil {
+ return nil, spiceerrors.MustBugf("failed to set relation kind: %s", err.Error())
+ }
+
+ case rewrite == nil && len(allowedDirectRelations) > 0:
+ if err := SetRelationKind(rel, iv1.RelationMetadata_RELATION); err != nil {
+ return nil, spiceerrors.MustBugf("failed to set relation kind: %s", err.Error())
+ }
+
+ default:
+ // By default we do not set a relation kind on the relation. Relations without any
+ // information, or relations with both rewrites and types are legacy relations from
+ // before the DSL schema and, as such, do not have a defined "kind".
+ }
+
+ return rel, nil
+}
+
+// MustRelationWithComment creates a relation definition with an optional rewrite definition.
+func MustRelationWithComment(name string, comment string, rewrite *core.UsersetRewrite, allowedDirectRelations ...*core.AllowedRelation) *core.Relation {
+ rel := MustRelation(name, rewrite, allowedDirectRelations...)
+ rel.Metadata, _ = AddComment(rel.Metadata, comment)
+ return rel
+}
+
+// AllowedRelation creates a relation reference to an allowed relation.
+func AllowedRelation(namespaceName string, relationName string) *core.AllowedRelation {
+ return &core.AllowedRelation{
+ Namespace: namespaceName,
+ RelationOrWildcard: &core.AllowedRelation_Relation{
+ Relation: relationName,
+ },
+ }
+}
+
+// AllowedRelationWithCaveat creates a relation reference to an allowed relation.
+func AllowedRelationWithCaveat(namespaceName string, relationName string, withCaveat *core.AllowedCaveat) *core.AllowedRelation {
+ return &core.AllowedRelation{
+ Namespace: namespaceName,
+ RelationOrWildcard: &core.AllowedRelation_Relation{
+ Relation: relationName,
+ },
+ RequiredCaveat: withCaveat,
+ }
+}
+
+// WithExpiration adds the expiration trait to the allowed relation.
+func WithExpiration(allowedRelation *core.AllowedRelation) *core.AllowedRelation {
+ return &core.AllowedRelation{
+ Namespace: allowedRelation.Namespace,
+ RelationOrWildcard: allowedRelation.RelationOrWildcard,
+ RequiredCaveat: allowedRelation.RequiredCaveat,
+ RequiredExpiration: &core.ExpirationTrait{},
+ }
+}
+
+// AllowedRelationWithExpiration creates a relation reference to an allowed relation.
+func AllowedRelationWithExpiration(namespaceName string, relationName string) *core.AllowedRelation {
+ return &core.AllowedRelation{
+ Namespace: namespaceName,
+ RelationOrWildcard: &core.AllowedRelation_Relation{
+ Relation: relationName,
+ },
+ RequiredExpiration: &core.ExpirationTrait{},
+ }
+}
+
+// AllowedRelationWithCaveatAndExpiration creates a relation reference to an allowed relation.
+func AllowedRelationWithCaveatAndExpiration(namespaceName string, relationName string, withCaveat *core.AllowedCaveat) *core.AllowedRelation {
+ return &core.AllowedRelation{
+ Namespace: namespaceName,
+ RelationOrWildcard: &core.AllowedRelation_Relation{
+ Relation: relationName,
+ },
+ RequiredExpiration: &core.ExpirationTrait{},
+ RequiredCaveat: withCaveat,
+ }
+}
+
+// AllowedPublicNamespace creates a relation reference to an allowed public namespace.
+func AllowedPublicNamespace(namespaceName string) *core.AllowedRelation {
+ return &core.AllowedRelation{
+ Namespace: namespaceName,
+ RelationOrWildcard: &core.AllowedRelation_PublicWildcard_{
+ PublicWildcard: &core.AllowedRelation_PublicWildcard{},
+ },
+ }
+}
+
+// AllowedCaveat creates a caveat reference.
+func AllowedCaveat(name string) *core.AllowedCaveat {
+ return &core.AllowedCaveat{
+ CaveatName: name,
+ }
+}
+
+// CaveatDefinition returns a new caveat definition.
+func CaveatDefinition(env *caveats.Environment, name string, expr string) (*core.CaveatDefinition, error) {
+ compiled, err := caveats.CompileCaveatWithName(env, expr, name)
+ if err != nil {
+ return nil, err
+ }
+ return CompiledCaveatDefinition(env, name, compiled)
+}
+
+// CompiledCaveatDefinition returns a new caveat definition.
+func CompiledCaveatDefinition(env *caveats.Environment, name string, compiled *caveats.CompiledCaveat) (*core.CaveatDefinition, error) {
+ if compiled == nil {
+ return nil, spiceerrors.MustBugf("compiled caveat is nil")
+ }
+
+ serialized, err := compiled.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ return &core.CaveatDefinition{
+ Name: name,
+ SerializedExpression: serialized,
+ ParameterTypes: env.EncodedParametersTypes(),
+ }, nil
+}
+
+// MustCaveatDefinition returns a new caveat definition.
+func MustCaveatDefinition(env *caveats.Environment, name string, expr string) *core.CaveatDefinition {
+ cd, err := CaveatDefinition(env, name, expr)
+ if err != nil {
+ panic(err)
+ }
+ return cd
+}
+
+// MustCaveatDefinitionWithComment returns a new caveat definition.
+func MustCaveatDefinitionWithComment(env *caveats.Environment, name string, comment string, expr string) *core.CaveatDefinition {
+ cd, err := CaveatDefinition(env, name, expr)
+ if err != nil {
+ panic(err)
+ }
+ cd.Metadata, _ = AddComment(cd.Metadata, comment)
+ return cd
+}
+
+// AllowedPublicNamespaceWithCaveat creates a relation reference to an allowed public namespace.
+func AllowedPublicNamespaceWithCaveat(namespaceName string, withCaveat *core.AllowedCaveat) *core.AllowedRelation {
+ return &core.AllowedRelation{
+ Namespace: namespaceName,
+ RelationOrWildcard: &core.AllowedRelation_PublicWildcard_{
+ PublicWildcard: &core.AllowedRelation_PublicWildcard{},
+ },
+ RequiredCaveat: withCaveat,
+ }
+}
+
+// RelationReference creates a relation reference.
+func RelationReference(namespaceName string, relationName string) *core.RelationReference {
+ return &core.RelationReference{
+ Namespace: namespaceName,
+ Relation: relationName,
+ }
+}
+
+// Union creates a rewrite definition that combines/considers usersets in all children.
+func Union(firstChild *core.SetOperation_Child, rest ...*core.SetOperation_Child) *core.UsersetRewrite {
+ return &core.UsersetRewrite{
+ RewriteOperation: &core.UsersetRewrite_Union{
+ Union: setOperation(firstChild, rest),
+ },
+ }
+}
+
+// Intersection creates a rewrite definition that returns/considers only usersets present in all children.
+func Intersection(firstChild *core.SetOperation_Child, rest ...*core.SetOperation_Child) *core.UsersetRewrite {
+ return &core.UsersetRewrite{
+ RewriteOperation: &core.UsersetRewrite_Intersection{
+ Intersection: setOperation(firstChild, rest),
+ },
+ }
+}
+
+// Exclusion creates a rewrite definition that starts with the usersets of the first child
+// and iteratively removes usersets that appear in the remaining children.
+func Exclusion(firstChild *core.SetOperation_Child, rest ...*core.SetOperation_Child) *core.UsersetRewrite {
+ return &core.UsersetRewrite{
+ RewriteOperation: &core.UsersetRewrite_Exclusion{
+ Exclusion: setOperation(firstChild, rest),
+ },
+ }
+}
+
+func setOperation(firstChild *core.SetOperation_Child, rest []*core.SetOperation_Child) *core.SetOperation {
+ children := append([]*core.SetOperation_Child{firstChild}, rest...)
+ return &core.SetOperation{
+ Child: children,
+ }
+}
+
+// Nil creates a child for a set operation that references the empty set.
+func Nil() *core.SetOperation_Child {
+ return &core.SetOperation_Child{
+ ChildType: &core.SetOperation_Child_XNil{},
+ }
+}
+
+// ComputesUserset creates a child for a set operation that follows a relation on the given starting object.
+func ComputedUserset(relation string) *core.SetOperation_Child {
+ return &core.SetOperation_Child{
+ ChildType: &core.SetOperation_Child_ComputedUserset{
+ ComputedUserset: &core.ComputedUserset{
+ Relation: relation,
+ },
+ },
+ }
+}
+
+// MustComputesUsersetWithSourcePosition creates a child for a set operation that follows a relation on the given starting object.
+func MustComputesUsersetWithSourcePosition(relation string, lineNumber uint64) *core.SetOperation_Child {
+ cu := &core.ComputedUserset{
+ Relation: relation,
+ }
+ cu.SourcePosition = &core.SourcePosition{
+ ZeroIndexedLineNumber: lineNumber,
+ ZeroIndexedColumnPosition: 0,
+ }
+
+ return &core.SetOperation_Child{
+ ChildType: &core.SetOperation_Child_ComputedUserset{
+ ComputedUserset: cu,
+ },
+ }
+}
+
+// TupleToUserset creates a child which first loads all tuples with the specific relation,
+// and then unions all children on the usersets found by following a relation on those loaded
+// tuples.
+func TupleToUserset(tuplesetRelation, usersetRelation string) *core.SetOperation_Child {
+ return &core.SetOperation_Child{
+ ChildType: &core.SetOperation_Child_TupleToUserset{
+ TupleToUserset: &core.TupleToUserset{
+ Tupleset: &core.TupleToUserset_Tupleset{
+ Relation: tuplesetRelation,
+ },
+ ComputedUserset: &core.ComputedUserset{
+ Relation: usersetRelation,
+ Object: core.ComputedUserset_TUPLE_USERSET_OBJECT,
+ },
+ },
+ },
+ }
+}
+
+// MustFunctionedTupleToUserset creates a child which first loads all tuples with the specific relation,
+// and then applies the function to all children on the usersets found by following a relation on those loaded
+// tuples.
+func MustFunctionedTupleToUserset(tuplesetRelation, functionName, usersetRelation string) *core.SetOperation_Child {
+ function := core.FunctionedTupleToUserset_FUNCTION_ANY
+
+ switch functionName {
+ case "any":
+ // already set to any
+
+ case "all":
+ function = core.FunctionedTupleToUserset_FUNCTION_ALL
+
+ default:
+ panic(spiceerrors.MustBugf("unknown function name: %s", functionName))
+ }
+
+ return &core.SetOperation_Child{
+ ChildType: &core.SetOperation_Child_FunctionedTupleToUserset{
+ FunctionedTupleToUserset: &core.FunctionedTupleToUserset{
+ Function: function,
+ Tupleset: &core.FunctionedTupleToUserset_Tupleset{
+ Relation: tuplesetRelation,
+ },
+ ComputedUserset: &core.ComputedUserset{
+ Relation: usersetRelation,
+ Object: core.ComputedUserset_TUPLE_USERSET_OBJECT,
+ },
+ },
+ },
+ }
+}
+
+// Rewrite wraps a rewrite as a set operation child of another rewrite.
+func Rewrite(rewrite *core.UsersetRewrite) *core.SetOperation_Child {
+ return &core.SetOperation_Child{
+ ChildType: &core.SetOperation_Child_UsersetRewrite{
+ UsersetRewrite: rewrite,
+ },
+ }
+}
diff --git a/vendor/github.com/authzed/spicedb/pkg/namespace/doc.go b/vendor/github.com/authzed/spicedb/pkg/namespace/doc.go
new file mode 100644
index 0000000..ab77e95
--- /dev/null
+++ b/vendor/github.com/authzed/spicedb/pkg/namespace/doc.go
@@ -0,0 +1,2 @@
+// Package namespace contains helper functions to create namespaces in a schema.
+package namespace
diff --git a/vendor/github.com/authzed/spicedb/pkg/namespace/mapper.go b/vendor/github.com/authzed/spicedb/pkg/namespace/mapper.go
new file mode 100644
index 0000000..148ca8e
--- /dev/null
+++ b/vendor/github.com/authzed/spicedb/pkg/namespace/mapper.go
@@ -0,0 +1,27 @@
+package namespace
+
+// Mapper provides an interface for creating synthetic namespace names from
+// user provided namespace names.
+type Mapper interface {
+ // Encode translates a given namespace name to an encoded namespace identifier.
+ Encode(name string) (string, error)
+
+ // Reverse translates a given namespace identifier to the user supplied namespace name.
+ Reverse(id string) (string, error)
+}
+
+type passthrough struct{}
+
+// Encode implements Mapper
+func (p passthrough) Encode(name string) (string, error) {
+ return name, nil
+}
+
+// Reverse implements Mapper
+func (p passthrough) Reverse(id string) (string, error) {
+ return id, nil
+}
+
+// PassthroughMapper is a mapper implementation which passes through the original namespace
+// names unmodified.
+var PassthroughMapper Mapper = passthrough{}
diff --git a/vendor/github.com/authzed/spicedb/pkg/namespace/metadata.go b/vendor/github.com/authzed/spicedb/pkg/namespace/metadata.go
new file mode 100644
index 0000000..5544a5c
--- /dev/null
+++ b/vendor/github.com/authzed/spicedb/pkg/namespace/metadata.go
@@ -0,0 +1,110 @@
+package namespace
+
+import (
+ "google.golang.org/protobuf/types/known/anypb"
+
+ core "github.com/authzed/spicedb/pkg/proto/core/v1"
+
+ iv1 "github.com/authzed/spicedb/pkg/proto/impl/v1"
+)
+
+// WithSourcePosition defines an interface for proto messages in core with SourcePosition information attached.
+type WithSourcePosition interface {
+ GetSourcePosition() *core.SourcePosition
+}
+
+// userDefinedMetadataTypeUrls are the type URLs of any user-defined metadata found
+// in the namespace proto. If placed here, FilterUserDefinedMetadataInPlace will remove the
+// metadata when called on the namespace.
+var userDefinedMetadataTypeUrls = map[string]struct{}{
+ "type.googleapis.com/impl.v1.DocComment": {},
+}
+
+// FilterUserDefinedMetadataInPlace removes user-defined metadata (e.g. comments) from the given namespace
+// *in place*.
+func FilterUserDefinedMetadataInPlace(nsconfig *core.NamespaceDefinition) {
+ nsconfig.Metadata = nil
+ for _, relation := range nsconfig.Relation {
+ if relation.Metadata != nil {
+ var filteredMessages []*anypb.Any
+ for _, msg := range relation.Metadata.MetadataMessage {
+ if _, ok := userDefinedMetadataTypeUrls[msg.TypeUrl]; !ok {
+ filteredMessages = append(filteredMessages, msg)
+ }
+ }
+ relation.Metadata.MetadataMessage = filteredMessages
+ }
+ }
+}
+
+// GetComments returns the comment metadata found within the given metadata message.
+func GetComments(metadata *core.Metadata) []string {
+ if metadata == nil {
+ return []string{}
+ }
+
+ comments := []string{}
+ for _, msg := range metadata.MetadataMessage {
+ var dc iv1.DocComment
+ if err := msg.UnmarshalTo(&dc); err == nil {
+ comments = append(comments, dc.Comment)
+ }
+ }
+
+ return comments
+}
+
+// AddComment adds a comment to the given metadata message.
+func AddComment(metadata *core.Metadata, comment string) (*core.Metadata, error) {
+ if metadata == nil {
+ metadata = &core.Metadata{}
+ }
+
+ var dc iv1.DocComment
+ dc.Comment = comment
+
+ encoded, err := anypb.New(&dc)
+ if err != nil {
+ return metadata, err
+ }
+
+ metadata.MetadataMessage = append(metadata.MetadataMessage, encoded)
+ return metadata, nil
+}
+
+// GetRelationKind returns the kind of the relation.
+func GetRelationKind(relation *core.Relation) iv1.RelationMetadata_RelationKind {
+ metadata := relation.Metadata
+ if metadata == nil {
+ return iv1.RelationMetadata_UNKNOWN_KIND
+ }
+
+ for _, msg := range metadata.MetadataMessage {
+ var rm iv1.RelationMetadata
+ if err := msg.UnmarshalTo(&rm); err == nil {
+ return rm.Kind
+ }
+ }
+
+ return iv1.RelationMetadata_UNKNOWN_KIND
+}
+
+// SetRelationKind sets the kind of relation.
+func SetRelationKind(relation *core.Relation, kind iv1.RelationMetadata_RelationKind) error {
+ metadata := relation.Metadata
+ if metadata == nil {
+ metadata = &core.Metadata{}
+ relation.Metadata = metadata
+ }
+
+ var rm iv1.RelationMetadata
+ rm.Kind = kind
+
+ encoded, err := anypb.New(&rm)
+ if err != nil {
+ return err
+ }
+
+ metadata.MetadataMessage = append(metadata.MetadataMessage, encoded)
+ return nil
+}