| 1 |  |  | package schema | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | import ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | 	"errors" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | 	"sync" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | 	"github.com/Permify/permify/pkg/dsl/utils" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | 	base "github.com/Permify/permify/pkg/pb/base/v1" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | ) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | // LinkedSchemaGraph represents a graph of linked schema objects. The schema object contains definitions for entities, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | // relationships, and permissions, and the graph is constructed by linking objects together based on their dependencies. The | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | // graph is used by the PermissionEngine to resolve permissions and expand user sets for a given request. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | // Fields: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | //   - schema: pointer to the base.SchemaDefinition that defines the schema objects in the graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | type LinkedSchemaGraph struct { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | 	schema *base.SchemaDefinition | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | // NewLinkedGraph returns a new instance of LinkedSchemaGraph with the specified base.SchemaDefinition as its schema. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | // The schema object contains definitions for entities, relationships, and permissions, and is used to construct a graph of | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | // linked schema objects. The graph is used by the PermissionEngine to resolve permissions and expand user sets for a | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | // given request. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | // Parameters: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | //   - schema: pointer to the base.SchemaDefinition that defines the schema objects in the graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | // Returns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | //   - pointer to a new instance of LinkedSchemaGraph with the specified schema object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | func NewLinkedGraph(schema *base.SchemaDefinition) *LinkedSchemaGraph { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  | 	return &LinkedSchemaGraph{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | 		schema: schema, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  | // LinkedEntranceKind is a string type that represents the kind of LinkedEntrance object. An LinkedEntrance object defines an entry point | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  | // into the LinkedSchemaGraph, which is used to resolve permissions and expand user sets for a given request. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  | // Values: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  | //   - RelationLinkedEntrance: represents an entry point into a relationship object in the schema graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  | //   - TupleToUserSetLinkedEntrance: represents an entry point into a tuple-to-user-set object in the schema graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  | //   - ComputedUserSetLinkedEntrance: represents an entry point into a computed user set object in the schema graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  | type LinkedEntranceKind string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  | const ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  | 	RelationLinkedEntrance        LinkedEntranceKind = "relation" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  | 	TupleToUserSetLinkedEntrance  LinkedEntranceKind = "tuple_to_user_set" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  | 	ComputedUserSetLinkedEntrance LinkedEntranceKind = "computed_user_set" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  | ) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  | // LinkedEntrance represents an entry point into the LinkedSchemaGraph, which is used to resolve permissions and expand user | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  | // sets for a given request. The object contains a kind that specifies the type of entry point (e.g. relation, tuple-to-user-set), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | // an entry point reference that identifies the specific entry point in the graph, and a tuple set relation reference that | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  | // specifies the relation to use when expanding user sets for the entry point. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  | // Fields: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  | //   - Kind: LinkedEntranceKind representing the type of entry point | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  | //   - LinkedEntrance: pointer to a base.RelationReference that identifies the entry point in the schema graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  | //   - TupleSetRelation: pointer to a base.RelationReference that specifies the relation to use when expanding user sets | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  | //     for the entry point | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  | type LinkedEntrance struct { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  | 	Kind             LinkedEntranceKind | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  | 	TargetEntrance   *base.RelationReference | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  | 	TupleSetRelation string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  | // LinkedEntranceKind returns the kind of the LinkedEntrance object. The kind specifies the type of entry point (e.g. relation, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  | // tuple-to-user-set, computed user set). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  | // Returns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  | //   - LinkedEntranceKind representing the type of entry point | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  | func (re LinkedEntrance) LinkedEntranceKind() LinkedEntranceKind { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  | 	return re.Kind | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  | // RelationshipLinkedEntrances returns a slice of LinkedEntrance objects that represent entry points into the LinkedSchemaGraph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  | // for the specified target and source relations. The function recursively searches the graph for all entry points that can | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  | // be reached from the target relation through the specified source relation. The resulting entry points contain a reference | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  | // to the relation object in the schema graph and the relation used to expand user sets for the entry point. If the target or | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  | // source relation does not exist in the schema graph, the function returns an error. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  | // Parameters: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  | //   - target: pointer to a base.RelationReference that identifies the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  | //   - source: pointer to a base.RelationReference that identifies the source relation used to reach the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  | // Returns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  | //   - slice of LinkedEntrance objects that represent entry points into the LinkedSchemaGraph, or an error if the target or | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 89 |  |  | //     source relation does not exist in the schema graph | 
            
                                                                        
                            
            
                                    
            
            
                | 90 |  |  | func (g *LinkedSchemaGraph) RelationshipLinkedEntrances(targets []*base.RelationReference, source *base.RelationReference) ([]*LinkedEntrance, error) { | 
            
                                                                        
                            
            
                                    
            
            
                | 91 |  |  | 	visited := map[string]struct{}{} | 
            
                                                                        
                            
            
                                    
            
            
                | 92 |  |  | 	var mu sync.Mutex | 
            
                                                                        
                            
            
                                    
            
            
                | 93 |  |  | 	var wg sync.WaitGroup | 
            
                                                                        
                            
            
                                    
            
            
                | 94 |  |  | 	errChan := make(chan error, len(targets)) | 
            
                                                                        
                            
            
                                    
            
            
                | 95 |  |  | 	done := make(chan struct{}) | 
            
                                                                        
                            
            
                                    
            
            
                | 96 |  |  | 	totalEntries := make([]*LinkedEntrance, 0) | 
            
                                                                        
                            
            
                                    
            
            
                | 97 |  |  | 	for _, target := range targets { | 
            
                                                                        
                            
            
                                    
            
            
                | 98 |  |  | 		wg.Add(1) | 
            
                                                                        
                            
            
                                    
            
            
                | 99 |  |  | 		go func(target *base.RelationReference) { | 
            
                                                                        
                            
            
                                    
            
            
                | 100 |  |  | 			defer wg.Done() | 
            
                                                                        
                            
            
                                    
            
            
                | 101 |  |  | 			entries, err := g.findEntrance(target, source, visited, &mu) | 
            
                                                                        
                            
            
                                    
            
            
                | 102 |  |  | 			if err != nil { | 
            
                                                                        
                            
            
                                    
            
            
                | 103 |  |  | 				errChan <- err | 
            
                                                                        
                            
            
                                    
            
            
                | 104 |  |  | 			} | 
            
                                                                        
                            
            
                                    
            
            
                | 105 |  |  | 			mu.Lock() | 
            
                                                                        
                            
            
                                    
            
            
                | 106 |  |  | 			defer mu.Unlock() | 
            
                                                                        
                            
            
                                    
            
            
                | 107 |  |  | 			totalEntries = append(totalEntries, entries...) | 
            
                                                                        
                            
            
                                    
            
            
                | 108 |  |  | 		}(target) | 
            
                                                                        
                            
            
                                    
            
            
                | 109 |  |  | 	} | 
            
                                                                        
                            
            
                                    
            
            
                | 110 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 111 |  |  | 	go func() { | 
            
                                                                        
                            
            
                                    
            
            
                | 112 |  |  | 		wg.Wait() | 
            
                                                                        
                            
            
                                    
            
            
                | 113 |  |  | 		close(done) | 
            
                                                                        
                            
            
                                    
            
            
                | 114 |  |  | 	}() | 
            
                                                                        
                            
            
                                    
            
            
                | 115 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 116 |  |  | 	select { | 
            
                                                                        
                            
            
                                    
            
            
                | 117 |  |  | 	case <-done: | 
            
                                                                        
                            
            
                                    
            
            
                | 118 |  |  | 		// All goroutines finished | 
            
                                                                        
                            
            
                                    
            
            
                | 119 |  |  | 		return totalEntries, nil | 
            
                                                                        
                            
            
                                    
            
            
                | 120 |  |  | 	case err := <-errChan: | 
            
                                                                        
                            
            
                                    
            
            
                | 121 |  |  | 		// Return on the first error encountered | 
            
                                                                        
                            
            
                                    
            
            
                | 122 |  |  | 		return nil, err | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  | // findEntrance is a recursive helper function that searches the LinkedSchemaGraph for all entry points that can be reached | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  | // from the specified target relation through the specified source relation. The function uses a depth-first search to traverse | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  | // the schema graph and identify entry points, marking visited nodes in a map to avoid infinite recursion. If the target or | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  | // source relation does not exist in the schema graph, the function returns an error. If the source relation is an action | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  | // reference, the function recursively searches the graph for entry points reachable from the action child. If the source | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  | // relation is a regular relational reference, the function delegates to findRelationEntrance to search for entry points. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  | // Parameters: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  | //   - target: pointer to a base.RelationReference that identifies the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  | //   - source: pointer to a base.RelationReference that identifies the source relation used to reach the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  | //   - visited: map used to track visited nodes and avoid infinite recursion | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  | // Returns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  | //   - slice of LinkedEntrance objects that represent entry points into the LinkedSchemaGraph, or an error if the target or | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  | //     source relation does not exist in the schema graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  | func (g *LinkedSchemaGraph) findEntrance(target, source *base.RelationReference, visited map[string]struct{}, mu *sync.Mutex) ([]*LinkedEntrance, error) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  | 	key := utils.Key(target.GetType(), target.GetRelation()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  | 	mu.Lock() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  | 	mu.Lock() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  | 	if _, ok := visited[key]; ok { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  | 		mu.Unlock() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  | 		return nil, nil | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  | 	visited[key] = struct{}{} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  | 	mu.Unlock() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  | 	def, ok := g.schema.EntityDefinitions[target.GetType()] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  | 	if !ok { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  | 		return nil, errors.New("entity definition not found") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  | 	switch def.References[target.GetRelation()] { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  | 	case base.EntityDefinition_REFERENCE_PERMISSION: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  | 		permission, ok := def.Permissions[target.GetRelation()] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  | 		if !ok { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  | 			return nil, errors.New("permission not found") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  | 		child := permission.GetChild() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  | 		if child.GetRewrite() != nil { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  | 			return g.findEntranceRewrite(target, source, child.GetRewrite(), visited, mu) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  | 		return g.findEntranceLeaf(target, source, child.GetLeaf(), visited, mu) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  | 	case base.EntityDefinition_REFERENCE_ATTRIBUTE: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  | 		return nil, ErrUnimplemented | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  | 	case base.EntityDefinition_REFERENCE_RELATION: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  | 		return g.findRelationEntrance(target, source, visited, mu) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  | 	default: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  | 		return nil, ErrUnimplemented | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  | // findRelationEntrance is a helper function that searches the LinkedSchemaGraph for entry points that can be reached from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  | // the specified target relation through the specified source relation. The function only returns entry points that are directly | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  | // related to the target relation (i.e. the relation specified by the source reference is one of the relation's immediate children). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  | // The function recursively searches the children of the target relation and returns all reachable entry points. If the target | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  | // or source relation does not exist in the schema graph, the function returns an error. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  | // Parameters: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  | //   - target: pointer to a base.RelationReference that identifies the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  | //   - source: pointer to a base.RelationReference that identifies the source relation used to reach the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  | //   - visited: map used to track visited nodes and avoid infinite recursion | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  | // Returns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  | //   - slice of LinkedEntrance objects that represent entry points into the LinkedSchemaGraph, or an error if the target or | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  | //     source relation does not exist in the schema graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  | func (g *LinkedSchemaGraph) findRelationEntrance(target, source *base.RelationReference, visited map[string]struct{}, mu *sync.Mutex) ([]*LinkedEntrance, error) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  | 	var res []*LinkedEntrance | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  | 	entity, ok := g.schema.EntityDefinitions[target.GetType()] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  | 	if !ok { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  | 		return nil, errors.New("entity definition not found") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  | 	relation, ok := entity.Relations[target.GetRelation()] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  | 	if !ok { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  | 		return nil, errors.New("relation definition not found") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  | 	if IsDirectlyRelated(relation, source) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  | 		res = append(res, &LinkedEntrance{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  | 			Kind: RelationLinkedEntrance, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  | 			TargetEntrance: &base.RelationReference{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  | 				Type:     target.GetType(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  | 				Relation: target.GetRelation(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 |  |  | 			}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  | 		}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  | 	for _, rel := range relation.GetRelationReferences() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 |  |  | 		if rel.GetRelation() != "" { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 |  |  | 			entrances, err := g.findEntrance(rel, source, visited, mu) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 |  |  | 			if err != nil { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 |  |  | 				return nil, err | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  | 			res = append(res, entrances...) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 |  |  | 	return res, nil | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 |  |  | // findEntranceWithLeaf is a helper function that searches the LinkedSchemaGraph for entry points that can be reached from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 |  |  | // the specified target relation through an action reference with a leaf child. The function searches for entry points that are | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 |  |  | // reachable through a tuple-to-user-set or computed-user-set action. If the action child is a tuple-to-user-set action, the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 |  |  | // function recursively searches for entry points reachable through the child's tuple set relation and the child's computed user | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  | // set relation. If the action child is a computed-user-set action, the function recursively searches for entry points reachable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 |  |  | // through the computed user set relation. The function only returns entry points that can be reached from the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  | // using the specified source relation. If the target or source relation does not exist in the schema graph, the function returns | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  | // an error. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 |  |  | // Parameters: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 |  |  | //   - target: pointer to a base.RelationReference that identifies the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  | //   - source: pointer to a base.RelationReference that identifies the source relation used to reach the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 |  |  | //   - leaf: pointer to a base.Leaf object that represents the child of an action reference | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  | //   - visited: map used to track visited nodes and avoid infinite recursion | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  | // Returns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 |  |  | //   - slice of LinkedEntrance objects that represent entry points into the LinkedSchemaGraph, or an error if the target or | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  | //     source relation does not exist in the schema graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 |  |  | func (g *LinkedSchemaGraph) findEntranceLeaf(target, source *base.RelationReference, leaf *base.Leaf, visited map[string]struct{}, mu *sync.Mutex) ([]*LinkedEntrance, error) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 |  |  | 	switch t := leaf.GetType().(type) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  | 	case *base.Leaf_TupleToUserSet: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  | 		tupleSet := t.TupleToUserSet.GetTupleSet().GetRelation() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  | 		computedUserSet := t.TupleToUserSet.GetComputed().GetRelation() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 |  |  | 		var res []*LinkedEntrance | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  | 		entityDefinitions, exists := g.schema.EntityDefinitions[target.GetType()] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 |  |  | 		if !exists { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  | 			return nil, errors.New("entity definition not found") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 |  |  | 		relations, exists := entityDefinitions.Relations[tupleSet] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 |  |  | 		if !exists { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 |  |  | 			return nil, errors.New("relation definition not found") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 |  |  | 		for _, rel := range relations.GetRelationReferences() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 |  |  | 			if rel.GetType() == source.GetType() && source.GetRelation() == computedUserSet { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 |  |  | 				res = append(res, &LinkedEntrance{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 |  |  | 					Kind:             TupleToUserSetLinkedEntrance, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  | 					TargetEntrance:   target, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 |  |  | 					TupleSetRelation: tupleSet, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 |  |  | 				}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 |  |  | 			results, err := g.findEntrance( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 |  |  | 				&base.RelationReference{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  | 					Type:     rel.GetType(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  | 					Relation: computedUserSet, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 276 |  |  | 				}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 277 |  |  | 				source, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 278 |  |  | 				visited, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 279 |  |  | 				mu, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 280 |  |  | 			) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 281 |  |  | 			if err != nil { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 282 |  |  | 				return nil, err | 
            
                                                                                                            
                            
            
                                    
            
            
                | 283 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 284 |  |  | 			res = append(res, results...) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 285 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 286 |  |  | 		return res, nil | 
            
                                                                                                            
                            
            
                                    
            
            
                | 287 |  |  | 	case *base.Leaf_ComputedUserSet: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 288 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 289 |  |  | 		var entrances []*LinkedEntrance | 
            
                                                                                                            
                            
            
                                    
            
            
                | 290 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 291 |  |  | 		if target.GetType() == source.GetType() && t.ComputedUserSet.GetRelation() == source.GetRelation() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 292 |  |  | 			entrances = append(entrances, &LinkedEntrance{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 293 |  |  | 				Kind:           ComputedUserSetLinkedEntrance, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 294 |  |  | 				TargetEntrance: target, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 295 |  |  | 			}) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 296 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 297 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 298 |  |  | 		results, err := g.findEntrance( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 299 |  |  | 			&base.RelationReference{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 300 |  |  | 				Type:     target.GetType(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 301 |  |  | 				Relation: t.ComputedUserSet.GetRelation(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 302 |  |  | 			}, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 303 |  |  | 			source, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 304 |  |  | 			visited, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 305 |  |  | 			mu, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 306 |  |  | 		) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 307 |  |  | 		if err != nil { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 308 |  |  | 			return nil, err | 
            
                                                                                                            
                            
            
                                    
            
            
                | 309 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 310 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 311 |  |  | 		entrances = append( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 312 |  |  | 			entrances, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 313 |  |  | 			results..., | 
            
                                                                                                            
                            
            
                                    
            
            
                | 314 |  |  | 		) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 315 |  |  | 		return entrances, nil | 
            
                                                                                                            
                            
            
                                    
            
            
                | 316 |  |  | 	case *base.Leaf_ComputedAttribute: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 317 |  |  | 		return nil, ErrUnimplemented | 
            
                                                                                                            
                            
            
                                    
            
            
                | 318 |  |  | 	case *base.Leaf_Call: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 319 |  |  | 		return nil, ErrUnimplemented | 
            
                                                                                                            
                            
            
                                    
            
            
                | 320 |  |  | 	default: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 321 |  |  | 		return nil, ErrUndefinedLeafType | 
            
                                                                                                            
                            
            
                                    
            
            
                | 322 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 323 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 324 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 325 |  |  | // findEntranceWithRewrite is a helper function that searches the LinkedSchemaGraph for entry points that can be reached from | 
            
                                                                                                            
                            
            
                                    
            
            
                | 326 |  |  | // the specified target relation through an action reference with a rewrite child. The function recursively searches each child of | 
            
                                                                                                            
                            
            
                                    
            
            
                | 327 |  |  | // the rewrite and calls either findEntranceWithRewrite or findEntranceWithLeaf, depending on the child's type. The function | 
            
                                                                                                            
                            
            
                                    
            
            
                | 328 |  |  | // only returns entry points that can be reached from the target relation using the specified source relation. If the target or | 
            
                                                                                                            
                            
            
                                    
            
            
                | 329 |  |  | // source relation does not exist in the schema graph, the function returns an error. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 330 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 331 |  |  | // Parameters: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 332 |  |  | //   - target: pointer to a base.RelationReference that identifies the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 333 |  |  | //   - source: pointer to a base.RelationReference that identifies the source relation used to reach the target relation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 334 |  |  | //   - rewrite: pointer to a base.Rewrite object that represents the child of an action reference | 
            
                                                                                                            
                            
            
                                    
            
            
                | 335 |  |  | //   - visited: map used to track visited nodes and avoid infinite recursion | 
            
                                                                                                            
                            
            
                                    
            
            
                | 336 |  |  | // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 337 |  |  | // Returns: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 338 |  |  | //   - slice of LinkedEntrance objects that represent entry points into the LinkedSchemaGraph, or an error if the target or | 
            
                                                                                                            
                            
            
                                    
            
            
                | 339 |  |  | //     source relation does not exist in the schema graph | 
            
                                                                                                            
                            
            
                                    
            
            
                | 340 |  |  | func (g *LinkedSchemaGraph) findEntranceRewrite(target, source *base.RelationReference, rewrite *base.Rewrite, visited map[string]struct{}, mu *sync.Mutex) (results []*LinkedEntrance, err error) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 341 |  |  | 	var res []*LinkedEntrance | 
            
                                                                                                            
                            
            
                                    
            
            
                | 342 |  |  | 	for _, child := range rewrite.GetChildren() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 343 |  |  | 		switch child.GetType().(type) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 344 |  |  | 		case *base.Child_Rewrite: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 345 |  |  | 			results, err = g.findEntranceRewrite(target, source, child.GetRewrite(), visited, mu) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 346 |  |  | 			if err != nil { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 347 |  |  | 				return nil, err | 
            
                                                                                                            
                            
            
                                    
            
            
                | 348 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 349 |  |  | 		case *base.Child_Leaf: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 350 |  |  | 			results, err = g.findEntranceLeaf(target, source, child.GetLeaf(), visited, mu) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 351 |  |  | 			if err != nil { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 352 |  |  | 				return nil, err | 
            
                                                                                                            
                            
            
                                    
            
            
                | 353 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 354 |  |  | 		default: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 355 |  |  | 			return nil, errors.New("undefined child type") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 356 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 357 |  |  | 		res = append(res, results...) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 358 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 359 |  |  | 	return res, nil | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 360 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 361 |  |  |  |