diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-22 17:35:49 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-22 17:35:49 -0600 |
| commit | 20ef0d92694465ac86b550df139e8366a0a2b4fa (patch) | |
| tree | 3f14589e1ce6eb9306a3af31c3a1f9e1af5ed637 /vendor/github.com/authzed/spicedb/pkg/namespace | |
| parent | 44e0d272c040cdc53a98b9f1dc58ae7da67752e6 (diff) | |
feat: connect to spicedb
Diffstat (limited to 'vendor/github.com/authzed/spicedb/pkg/namespace')
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 +} |
