diff options
Diffstat (limited to 'vendor/github.com/authzed/spicedb/pkg/validationfile/blocks/assertions.go')
| -rw-r--r-- | vendor/github.com/authzed/spicedb/pkg/validationfile/blocks/assertions.go | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/spicedb/pkg/validationfile/blocks/assertions.go b/vendor/github.com/authzed/spicedb/pkg/validationfile/blocks/assertions.go new file mode 100644 index 0000000..56c4e6c --- /dev/null +++ b/vendor/github.com/authzed/spicedb/pkg/validationfile/blocks/assertions.go @@ -0,0 +1,147 @@ +package blocks + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/ccoveille/go-safecast" + yamlv3 "gopkg.in/yaml.v3" + + "github.com/authzed/spicedb/pkg/spiceerrors" + "github.com/authzed/spicedb/pkg/tuple" +) + +// Assertions represents assertions defined in the validation file. +type Assertions struct { + // AssertTrue is the set of relationships to assert true. + AssertTrue []Assertion `yaml:"assertTrue"` + + // AssertCaveated is the set of relationships to assert that are caveated. + AssertCaveated []Assertion `yaml:"assertCaveated"` + + // AssertFalse is the set of relationships to assert false. + AssertFalse []Assertion `yaml:"assertFalse"` + + // SourcePosition is the position of the assertions in the file. + SourcePosition spiceerrors.SourcePosition +} + +// Assertion is a parsed assertion. +type Assertion struct { + // RelationshipWithContextString is the string form of the assertion, including optional context. + // Forms: + // `document:firstdoc#view@user:tom` + // `document:seconddoc#view@user:sarah with {"some":"contexthere"}` + RelationshipWithContextString string + + // Relationship is the parsed relationship on which the assertion is being + // run. + Relationship tuple.Relationship + + // CaveatContext is the caveat context for the assertion, if any. + CaveatContext map[string]any + + // SourcePosition is the position of the assertion in the file. + SourcePosition spiceerrors.SourcePosition +} + +type internalAssertions struct { + // AssertTrue is the set of relationships to assert true. + AssertTrue []Assertion `yaml:"assertTrue"` + + // AssertCaveated is the set of relationships to assert that are caveated. + AssertCaveated []Assertion `yaml:"assertCaveated"` + + // AssertFalse is the set of relationships to assert false. + AssertFalse []Assertion `yaml:"assertFalse"` +} + +// UnmarshalYAML is a custom unmarshaller. +func (a *Assertions) UnmarshalYAML(node *yamlv3.Node) error { + ia := internalAssertions{} + if err := node.Decode(&ia); err != nil { + return convertYamlError(err) + } + + a.AssertTrue = ia.AssertTrue + a.AssertFalse = ia.AssertFalse + a.AssertCaveated = ia.AssertCaveated + a.SourcePosition = spiceerrors.SourcePosition{LineNumber: node.Line, ColumnPosition: node.Column} + return nil +} + +// UnmarshalYAML is a custom unmarshaller. +func (a *Assertion) UnmarshalYAML(node *yamlv3.Node) error { + relationshipWithContextString := "" + + if err := node.Decode(&relationshipWithContextString); err != nil { + return convertYamlError(err) + } + + trimmed := strings.TrimSpace(relationshipWithContextString) + + line, err := safecast.ToUint64(node.Line) + if err != nil { + return err + } + column, err := safecast.ToUint64(node.Column) + if err != nil { + return err + } + + // Check for caveat context. + parts := strings.SplitN(trimmed, " with ", 2) + if len(parts) == 0 { + return spiceerrors.NewWithSourceError( + fmt.Errorf("error parsing assertion `%s`", trimmed), + trimmed, + line, + column, + ) + } + + relationship, err := tuple.Parse(strings.TrimSpace(parts[0])) + if err != nil { + return spiceerrors.NewWithSourceError( + fmt.Errorf("error parsing relationship in assertion `%s`: %w", trimmed, err), + trimmed, + line, + column, + ) + } + + a.Relationship = relationship + + if len(parts) == 2 { + caveatContextMap := make(map[string]any, 0) + err := json.Unmarshal([]byte(parts[1]), &caveatContextMap) + if err != nil { + return spiceerrors.NewWithSourceError( + fmt.Errorf("error parsing caveat context in assertion `%s`: %w", trimmed, err), + trimmed, + line, + column, + ) + } + + a.CaveatContext = caveatContextMap + } + + a.RelationshipWithContextString = relationshipWithContextString + a.SourcePosition = spiceerrors.SourcePosition{LineNumber: node.Line, ColumnPosition: node.Column} + return nil +} + +// ParseAssertionsBlock parses the given contents as an assertions block. +func ParseAssertionsBlock(contents []byte) (*Assertions, error) { + a := internalAssertions{} + if err := yamlv3.Unmarshal(contents, &a); err != nil { + return nil, convertYamlError(err) + } + return &Assertions{ + AssertTrue: a.AssertTrue, + AssertCaveated: a.AssertCaveated, + AssertFalse: a.AssertFalse, + }, nil +} |
