github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/validationfile/blocks/relationships.go (about) 1 package blocks 2 3 import ( 4 "fmt" 5 "strings" 6 7 v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" 8 yamlv3 "gopkg.in/yaml.v3" 9 10 "github.com/authzed/spicedb/pkg/spiceerrors" 11 "github.com/authzed/spicedb/pkg/tuple" 12 ) 13 14 // ParsedRelationships is the parsed relationships in a validationfile. 15 type ParsedRelationships struct { 16 // RelationshipsString is the found string of newline-separated relationships. 17 RelationshipsString string 18 19 // SourcePosition is the position of the schema in the file. 20 SourcePosition spiceerrors.SourcePosition 21 22 // Relationships are the fully parsed relationships. 23 Relationships []*v1.Relationship 24 } 25 26 // UnmarshalYAML is a custom unmarshaller. 27 func (pr *ParsedRelationships) UnmarshalYAML(node *yamlv3.Node) error { 28 err := node.Decode(&pr.RelationshipsString) 29 if err != nil { 30 return convertYamlError(err) 31 } 32 33 relationshipsString := pr.RelationshipsString 34 if relationshipsString == "" { 35 return nil 36 } 37 38 seenTuples := map[string]bool{} 39 lines := strings.Split(relationshipsString, "\n") 40 relationships := make([]*v1.Relationship, 0, len(lines)) 41 for index, line := range lines { 42 trimmed := strings.TrimSpace(line) 43 if len(trimmed) == 0 || strings.HasPrefix(trimmed, "//") { 44 continue 45 } 46 47 tpl := tuple.Parse(trimmed) 48 if tpl == nil { 49 return spiceerrors.NewErrorWithSource( 50 fmt.Errorf("error parsing relationship `%s`", trimmed), 51 trimmed, 52 uint64(node.Line+1+(index*2)), // +1 for the key, and *2 for newlines in YAML 53 uint64(node.Column), 54 ) 55 } 56 57 _, ok := seenTuples[tuple.StringWithoutCaveat(tpl)] 58 if ok { 59 return spiceerrors.NewErrorWithSource( 60 fmt.Errorf("found repeated relationship `%s`", trimmed), 61 trimmed, 62 uint64(node.Line+1+(index*2)), // +1 for the key, and *2 for newlines in YAML 63 uint64(node.Column), 64 ) 65 } 66 seenTuples[tuple.StringWithoutCaveat(tpl)] = true 67 relationships = append(relationships, tuple.MustToRelationship(tpl)) 68 } 69 70 pr.Relationships = relationships 71 pr.SourcePosition = spiceerrors.SourcePosition{LineNumber: node.Line, ColumnPosition: node.Column} 72 return nil 73 }