diff --git a/pkg/go/graph/graph.go b/pkg/go/graph/graph.go index 286e9b4f..c4823474 100644 --- a/pkg/go/graph/graph.go +++ b/pkg/go/graph/graph.go @@ -83,7 +83,8 @@ func (g *AuthorizationModelGraph) Reversed() (*AuthorizationModelGraph, error) { if !ok { return nil, fmt.Errorf("%w: could not cast to AuthorizationModelEdge", ErrBuildingGraph) } - graphBuilder.AddEdge(nextLine.To(), nextLine.From(), casted.edgeType, casted.conditionedOn) + newEdge := graphBuilder.AddEdge(nextLine.To(), nextLine.From(), casted.edgeType, casted.tuplesetRelation, "") + newEdge.conditions = casted.conditions } } diff --git a/pkg/go/graph/graph_builder.go b/pkg/go/graph/graph_builder.go index 207b8e97..8bf40608 100644 --- a/pkg/go/graph/graph_builder.go +++ b/pkg/go/graph/graph_builder.go @@ -46,7 +46,7 @@ func parseModel(model *openfgav1.AuthorizationModel) (*multi.DirectedGraph, Node }) for _, typeDef := range sortedTypeDefs { - graphBuilder.GetOrAddNode(typeDef.GetType(), typeDef.GetType(), SpecificType) + graphBuilder.getOrAddNode(typeDef.GetType(), typeDef.GetType(), SpecificType) // sort relations by name to guarantee stable output sortedRelations := make([]string, 0, len(typeDef.GetRelations())) @@ -58,7 +58,7 @@ func parseModel(model *openfgav1.AuthorizationModel) (*multi.DirectedGraph, Node for _, relation := range sortedRelations { uniqueLabel := fmt.Sprintf("%s#%s", typeDef.GetType(), relation) - parentNode := graphBuilder.GetOrAddNode(uniqueLabel, uniqueLabel, SpecificTypeAndRelation) + parentNode := graphBuilder.getOrAddNode(uniqueLabel, uniqueLabel, SpecificTypeAndRelation) rewrite := typeDef.GetRelations()[relation] checkRewrite(graphBuilder, parentNode, model, rewrite, typeDef, relation) } @@ -107,11 +107,11 @@ func checkRewrite(graphBuilder *AuthorizationModelGraphBuilder, parentNode *Auth } operatorNode := fmt.Sprintf("%s:%s", operator, ulid.Make().String()) - operatorNodeParent := graphBuilder.GetOrAddNode(operatorNode, operator, OperatorNode) + operatorNodeParent := graphBuilder.getOrAddNode(operatorNode, operator, OperatorNode) // add one edge "operator" -> "relation that defined the operator" // Note: if this is a composition of operators, operationNode will be nil and this edge won't be added. - graphBuilder.AddEdge(operatorNodeParent, parentNode, RewriteEdge, "") + graphBuilder.AddEdge(operatorNodeParent, parentNode, RewriteEdge, "", "") for _, child := range children { checkRewrite(graphBuilder, operatorNodeParent, model, child, typeDef, relation) } @@ -129,28 +129,24 @@ func parseThis(graphBuilder *AuthorizationModelGraphBuilder, parentNode graph.No if directlyRelatedDef.GetRelationOrWildcard() == nil { // direct assignment to concrete type assignableType := directlyRelatedDef.GetType() - curNode = graphBuilder.GetOrAddNode(assignableType, assignableType, SpecificType) + curNode = graphBuilder.getOrAddNode(assignableType, assignableType, SpecificType) } if directlyRelatedDef.GetWildcard() != nil { // direct assignment to wildcard assignableWildcard := directlyRelatedDef.GetType() + ":*" - curNode = graphBuilder.GetOrAddNode(assignableWildcard, assignableWildcard, SpecificTypeWildcard) + curNode = graphBuilder.getOrAddNode(assignableWildcard, assignableWildcard, SpecificTypeWildcard) } if directlyRelatedDef.GetRelation() != "" { // direct assignment to userset assignableUserset := directlyRelatedDef.GetType() + "#" + directlyRelatedDef.GetRelation() - curNode = graphBuilder.GetOrAddNode(assignableUserset, assignableUserset, SpecificTypeAndRelation) + curNode = graphBuilder.getOrAddNode(assignableUserset, assignableUserset, SpecificTypeAndRelation) } - if graphBuilder.HasEdge(curNode, parentNode, DirectEdge, "") { - // de-dup types that are conditioned, e.g. if define viewer: [user, user with condX] - // we only draw one edge from user to x#viewer - continue - } - - graphBuilder.AddEdge(curNode, parentNode, DirectEdge, "") + // de-dup types that are conditioned, e.g. if define viewer: [user, user with condX] + // we only draw one edge from user to x#viewer, but with two conditions: none and condX + graphBuilder.upsertEdge(curNode, parentNode, DirectEdge, "", directlyRelatedDef.GetCondition()) } } @@ -158,13 +154,13 @@ func parseComputed(graphBuilder *AuthorizationModelGraphBuilder, parentNode *Aut nodeType := RewriteEdge // e.g. define x: y. Here y is the rewritten relation rewrittenNodeName := fmt.Sprintf("%s#%s", typeDef.GetType(), relation) - newNode := graphBuilder.GetOrAddNode(rewrittenNodeName, rewrittenNodeName, SpecificTypeAndRelation) + newNode := graphBuilder.getOrAddNode(rewrittenNodeName, rewrittenNodeName, SpecificTypeAndRelation) // new edge from y to x if parentNode.nodeType == SpecificTypeAndRelation && newNode.nodeType == SpecificTypeAndRelation { nodeType = ComputedEdge } - graphBuilder.AddEdge(newNode, parentNode, nodeType, "") + graphBuilder.AddEdge(newNode, parentNode, nodeType, "", "") } func parseTupleToUserset(graphBuilder *AuthorizationModelGraphBuilder, parentNode graph.Node, model *openfgav1.AuthorizationModel, typeDef *openfgav1.TypeDefinition, rewrite *openfgav1.TupleToUserset) { @@ -188,16 +184,22 @@ func parseTupleToUserset(graphBuilder *AuthorizationModelGraphBuilder, parentNod } rewrittenNodeName := fmt.Sprintf("%s#%s", tuplesetType, computedRelation) - nodeSource := graphBuilder.GetOrAddNode(rewrittenNodeName, rewrittenNodeName, SpecificTypeAndRelation) - conditionedOnNodeName := fmt.Sprintf("%s#%s", typeDef.GetType(), tuplesetRelation) + nodeSource := graphBuilder.getOrAddNode(rewrittenNodeName, rewrittenNodeName, SpecificTypeAndRelation) + typeTuplesetRelation := fmt.Sprintf("%s#%s", typeDef.GetType(), tuplesetRelation) - // new edge from "xxx#admin" to "yyy#viewer" conditioned on "yyy#parent" - graphBuilder.AddEdge(nodeSource, parentNode, TTUEdge, conditionedOnNodeName) + if graphBuilder.hasEdge(nodeSource, parentNode, TTUEdge, typeTuplesetRelation) { + // de-dup types that are conditioned, e.g. if define viewer: [user, user with condX] + // we only draw one edge from user to x#viewer + continue + } + + // new edge from "xxx#admin" to "yyy#viewer" tuplesetRelation on "yyy#parent" + graphBuilder.upsertEdge(nodeSource, parentNode, TTUEdge, typeTuplesetRelation, relatedType.GetCondition()) } } -func (g *AuthorizationModelGraphBuilder) GetOrAddNode(uniqueLabel, label string, nodeType NodeType) *AuthorizationModelNode { - if existingNode := g.GetNodeFor(uniqueLabel); existingNode != nil { +func (g *AuthorizationModelGraphBuilder) getOrAddNode(uniqueLabel, label string, nodeType NodeType) *AuthorizationModelNode { + if existingNode := g.getNodeByLabel(uniqueLabel); existingNode != nil { return existingNode } @@ -215,7 +217,7 @@ func (g *AuthorizationModelGraphBuilder) GetOrAddNode(uniqueLabel, label string, return newNode } -func (g *AuthorizationModelGraphBuilder) GetNodeFor(uniqueLabel string) *AuthorizationModelNode { +func (g *AuthorizationModelGraphBuilder) getNodeByLabel(uniqueLabel string) *AuthorizationModelNode { id, ok := g.ids[uniqueLabel] if !ok { return nil @@ -229,31 +231,55 @@ func (g *AuthorizationModelGraphBuilder) GetNodeFor(uniqueLabel string) *Authori return authModelNode } -func (g *AuthorizationModelGraphBuilder) AddEdge(from, to graph.Node, edgeType EdgeType, conditionedOn string) *AuthorizationModelEdge { +func (g *AuthorizationModelGraphBuilder) AddEdge(from, to graph.Node, edgeType EdgeType, tuplesetRelation string, condition string) *AuthorizationModelEdge { if from == nil || to == nil { return nil } + if condition == "" { + condition = NoCond + } + conditions := []string{condition} l := g.NewLine(from, to) - newLine := &AuthorizationModelEdge{Line: l, edgeType: edgeType, conditionedOn: conditionedOn} + newLine := &AuthorizationModelEdge{Line: l, edgeType: edgeType, tuplesetRelation: tuplesetRelation, conditions: conditions} g.SetLine(newLine) return newLine } -func (g *AuthorizationModelGraphBuilder) HasEdge(from, to graph.Node, edgeType EdgeType, conditionedOn string) bool { +func (g *AuthorizationModelGraphBuilder) upsertEdge(from, to graph.Node, edgeType EdgeType, tuplesetRelation string, condition string) { if from == nil || to == nil { - return false + return } iter := g.Lines(from.ID(), to.ID()) for iter.Next() { l := iter.Line() - edge, ok := l.(*AuthorizationModelEdge) - if !ok { - return false + edge, _ := l.(*AuthorizationModelEdge) + if edge.edgeType == edgeType && edge.tuplesetRelation == tuplesetRelation { + for _, cond := range edge.conditions { + if cond == condition { + return + } + } + edge.conditions = append(edge.conditions, condition) + return } - if edge.edgeType == edgeType && edge.conditionedOn == conditionedOn { + } + + g.AddEdge(from, to, edgeType, tuplesetRelation, condition) +} + +func (g *AuthorizationModelGraphBuilder) hasEdge(from, to graph.Node, edgeType EdgeType, tuplesetRelation string) bool { + if from == nil || to == nil { + return false + } + + iter := g.Lines(from.ID(), to.ID()) + for iter.Next() { + l := iter.Line() + edge, _ := l.(*AuthorizationModelEdge) + if edge.edgeType == edgeType && edge.tuplesetRelation == tuplesetRelation { return true } } diff --git a/pkg/go/graph/graph_builder_test.go b/pkg/go/graph/graph_builder_test.go index 1711c95e..76e586cd 100644 --- a/pkg/go/graph/graph_builder_test.go +++ b/pkg/go/graph/graph_builder_test.go @@ -287,6 +287,71 @@ rankdir=BT 2 -> 1 [label=direct]; 4 -> 3 [headlabel="(document#parent)"]; 5 -> 4 [label=direct]; +}`, + }, + `tuple_to_userset_conditional`: { + model: ` + model + schema 1.1 + type user + type document + relations + define parentt: [folder, folder with condX] + define viewer: admin from parentt + type folder + relations + define admin: [user] + condition condX (x:int) { + x > 0 + }`, + expectedOutput: `digraph { +graph [ +rankdir=BT +]; + +// Node definitions. +0 [label=document]; +1 [label="document#parentt"]; +2 [label=folder]; +3 [label="document#viewer"]; +4 [label="folder#admin"]; +5 [label=user]; + +// Edge definitions. +2 -> 1 [label=direct]; +4 -> 3 [headlabel="(document#parentt)"]; +5 -> 4 [label=direct]; +}`, + }, + `userset_conditional`: { + model: ` + model + schema 1.1 + type folder + relations + define viewer: [group#member, group#member with condX] + type group + relations + define member: [user] + type user + condition condX (x:int) { + x > 0 + }`, + expectedOutput: `digraph { +graph [ +rankdir=BT +]; + +// Node definitions. +0 [label=folder]; +1 [label="folder#viewer"]; +2 [label="group#member"]; +3 [label=group]; +4 [label=user]; + +// Edge definitions. +2 -> 1 [label=direct]; +4 -> 2 [label=direct]; }`, }, `tuple_to_userset_recursive`: { diff --git a/pkg/go/graph/graph_edge.go b/pkg/go/graph/graph_edge.go index e094fab1..2d6402a1 100644 --- a/pkg/go/graph/graph_edge.go +++ b/pkg/go/graph/graph_edge.go @@ -12,6 +12,12 @@ const ( RewriteEdge EdgeType = 1 TTUEdge EdgeType = 2 ComputedEdge EdgeType = 3 + // When an edge does not have cond in the model, it will have a condition with value none. + // This is required to differentiate when an edge need to support condition and no condition + // like define rel1: [user, user with condX], in this case the edge will have [none, condX] + // or an edge needs to support only condition like define rel1: [user with condX], the edge will have [condX] + // in the case the edge does not have any condition like define rel1: [user], the edge will have [none]. + NoCond string = "none" ) type AuthorizationModelEdge struct { @@ -21,7 +27,15 @@ type AuthorizationModelEdge struct { edgeType EdgeType // only when edgeType == TTUEdge - conditionedOn string + tuplesetRelation string + + // conditions on the edge. This is a flattened graph with dedupx edges, + // if you have a node with multiple edges to another node will be deduplicate and instead + // only one edge but with multiple conditions, + // define rel1: [user, user with condX] + // then the node rel1 will have an edge pointing to the node user and with two conditions + // one that will be none and another one that will be condX + conditions []string } var _ encoding.Attributer = (*AuthorizationModelEdge)(nil) @@ -30,12 +44,12 @@ func (n *AuthorizationModelEdge) EdgeType() EdgeType { return n.edgeType } -// ConditionedOn returns the TTU relation. For example, relation +// TuplesetRelation returns the TTU relation. For example, relation // define viewer: viewer from parent // gives the graph "document#viewer" -> "document#viewer" and the edge // is conditioned on "document#parent". -func (n *AuthorizationModelEdge) ConditionedOn() string { - return n.conditionedOn +func (n *AuthorizationModelEdge) TuplesetRelation() string { + return n.tuplesetRelation } func (n *AuthorizationModelEdge) Attributes() []encoding.Attribute { @@ -55,7 +69,7 @@ func (n *AuthorizationModelEdge) Attributes() []encoding.Attribute { }, } case TTUEdge: - headLabelAttrValue := n.conditionedOn + headLabelAttrValue := n.tuplesetRelation if headLabelAttrValue == "" { headLabelAttrValue = "missing" } diff --git a/pkg/go/graph/graph_edge_test.go b/pkg/go/graph/graph_edge_test.go index 2f8f9b04..3aae8df8 100644 --- a/pkg/go/graph/graph_edge_test.go +++ b/pkg/go/graph/graph_edge_test.go @@ -41,5 +41,5 @@ func TestEdgeConditionedOn(t *testing.T) { edge, ok := edges.Line().(*AuthorizationModelEdge) require.True(t, ok) - require.Equal(t, "document#parent", edge.ConditionedOn()) + require.Equal(t, "document#parent", edge.TuplesetRelation()) } diff --git a/pkg/go/graph/weighted_graph.go b/pkg/go/graph/weighted_graph.go index 5f8a9285..9b2af40f 100644 --- a/pkg/go/graph/weighted_graph.go +++ b/pkg/go/graph/weighted_graph.go @@ -57,11 +57,14 @@ func (wg *WeightedAuthorizationModelGraph) AddNode(uniqueLabel, label string, no wg.nodes[uniqueLabel] = &WeightedAuthorizationModelNode{uniqueLabel: uniqueLabel, label: label, nodeType: nodeType, wildcards: wildcards} } -func (wg *WeightedAuthorizationModelGraph) AddEdge(fromID, toID string, edgeType EdgeType, condition string) { +func (wg *WeightedAuthorizationModelGraph) AddEdge(fromID, toID string, edgeType EdgeType, tuplesetRelation string, conditions []string) { wildcards := make([]string, 0) fromNode := wg.nodes[fromID] toNode := wg.nodes[toID] - edge := &WeightedAuthorizationModelEdge{from: fromNode, to: toNode, edgeType: edgeType, conditionedOn: condition, wildcards: wildcards} + if len(conditions) == 0 { + conditions = []string{NoCond} + } + edge := &WeightedAuthorizationModelEdge{from: fromNode, to: toNode, edgeType: edgeType, tuplesetRelation: tuplesetRelation, wildcards: wildcards, conditions: conditions} wg.edges[fromID] = append(wg.edges[fromID], edge) } diff --git a/pkg/go/graph/weighted_graph_builder.go b/pkg/go/graph/weighted_graph_builder.go index a6a0b7bf..5de35aae 100644 --- a/pkg/go/graph/weighted_graph_builder.go +++ b/pkg/go/graph/weighted_graph_builder.go @@ -64,7 +64,7 @@ func (wgb *WeightedAuthorizationModelGraphBuilder) Build(model *openfgav1.Author if !ok { return nil, fmt.Errorf("%w: could not cast %v to AuthorizationModelNode", ErrBuildingGraph, castedEdge.To()) } - wb.AddEdge(castedFromNode.uniqueLabel, castedToNode.uniqueLabel, castedEdge.edgeType, castedEdge.conditionedOn) + wb.AddEdge(castedFromNode.uniqueLabel, castedToNode.uniqueLabel, castedEdge.edgeType, castedEdge.tuplesetRelation, castedEdge.conditions) } } diff --git a/pkg/go/graph/weighted_graph_builder_test.go b/pkg/go/graph/weighted_graph_builder_test.go index 2f1f5b36..7cb8bb99 100644 --- a/pkg/go/graph/weighted_graph_builder_test.go +++ b/pkg/go/graph/weighted_graph_builder_test.go @@ -484,3 +484,104 @@ func TestValidGraphModel(t *testing.T) { require.NoError(t, err) require.Equal(t, 3, graph.nodes["job#can_read"].weights["user"]) } + +func TestValidConditionalGraphModel(t *testing.T) { + t.Parallel() + model := ` + model + schema 1.1 + type user + type role + relations + define assignee: [user] + type permission + relations + define assignee: [role#assignee, role#assignee with condX] + define member: [user, permission#member, permission#member with condX] + type job + relations + define can_read: assignee from permission + define can_view: [user] or can_view from owner + define owner: [job, job with condX] + define permission: [permission, permission with condX] + condition condX (x:int) { + x > 0 + } + ` + authorizationModel := language.MustTransformDSLToProto(model) + wgb := NewWeightedAuthorizationModelGraphBuilder() + graph, err := wgb.Build(authorizationModel) + require.NoError(t, err) + require.Len(t, graph.nodes, 12) + require.Len(t, graph.edges, 8) + edges, _ := graph.GetEdgesFromNode(graph.nodes["permission#assignee"]) + require.Len(t, edges, 1) + conditions := edges[0].conditions + require.Empty(t, edges[0].tuplesetRelation) + require.Len(t, conditions, 2) + edges, _ = graph.GetEdgesFromNode(graph.nodes["job#can_read"]) + require.Len(t, edges, 1) + conditions = edges[0].conditions + require.Len(t, conditions, 1) + require.Equal(t, "job#permission", edges[0].tuplesetRelation) + edges, _ = graph.GetEdgesFromNode(graph.nodes["job#permission"]) + require.Len(t, edges, 1) + conditions = edges[0].conditions + require.Len(t, conditions, 2) + require.Equal(t, "", edges[0].tuplesetRelation) + edges, _ = graph.GetEdgesFromNode(graph.nodes["role#assignee"]) + require.Len(t, edges, 1) + conditions = edges[0].conditions + require.Len(t, conditions, 1) + require.Equal(t, "", edges[0].tuplesetRelation) + edges, _ = graph.GetEdgesFromNode(graph.nodes["permission#member"]) + require.Len(t, edges, 2) + var recursiveEdge *WeightedAuthorizationModelEdge + var userEdge *WeightedAuthorizationModelEdge + if edges[0].weights["user"] == Infinite { + recursiveEdge = edges[0] + userEdge = edges[1] + } else { + recursiveEdge = edges[1] + userEdge = edges[0] + } + conditions = recursiveEdge.conditions + require.Len(t, conditions, 2) + require.Equal(t, "", recursiveEdge.tuplesetRelation) + conditions = userEdge.conditions + require.Len(t, conditions, 1) + require.Equal(t, "", userEdge.tuplesetRelation) + edges, _ = graph.GetEdgesFromNode(graph.nodes["job#owner"]) + require.Len(t, edges, 1) + conditions = edges[0].conditions + require.Len(t, conditions, 2) + require.Equal(t, "", edges[0].tuplesetRelation) + edges, _ = graph.GetEdgesFromNode(graph.nodes["job#can_view"]) + require.Len(t, edges, 1) + conditions = edges[0].conditions + require.Len(t, conditions, 1) + require.Equal(t, "", edges[0].tuplesetRelation) + edges, _ = graph.GetEdgesFromNode(edges[0].to) // OR node + require.Len(t, edges, 2) + if edges[0].weights["user"] == Infinite { + recursiveEdge = edges[0] + userEdge = edges[1] + } else { + recursiveEdge = edges[1] + userEdge = edges[0] + } + conditions = recursiveEdge.conditions + require.Len(t, conditions, 1) + require.Equal(t, "job#owner", recursiveEdge.tuplesetRelation) + conditions = userEdge.conditions + require.Len(t, conditions, 1) + require.Equal(t, "", userEdge.tuplesetRelation) + + require.Equal(t, 2, graph.nodes["permission#assignee"].weights["user"]) + require.Equal(t, 3, graph.nodes["job#can_read"].weights["user"]) + require.Equal(t, 1, graph.nodes["role#assignee"].weights["user"]) + require.Equal(t, 1, graph.nodes["job#permission"].weights["permission"]) + require.Equal(t, Infinite, graph.nodes["permission#member"].weights["user"]) + require.Equal(t, Infinite, graph.nodes["job#can_view"].weights["user"]) + require.Equal(t, 1, graph.nodes["job#owner"].weights["job"]) +} diff --git a/pkg/go/graph/weighted_graph_edge.go b/pkg/go/graph/weighted_graph_edge.go index 50c4e5f1..ee8c366a 100644 --- a/pkg/go/graph/weighted_graph_edge.go +++ b/pkg/go/graph/weighted_graph_edge.go @@ -1,12 +1,19 @@ package graph type WeightedAuthorizationModelEdge struct { - weights map[string]int - edgeType EdgeType - conditionedOn string - from *WeightedAuthorizationModelNode - to *WeightedAuthorizationModelNode - wildcards []string // e.g. "user". This means that in the direction of this edge there is a path to node user:* + weights map[string]int + edgeType EdgeType + tuplesetRelation string // only present when the edgeType is a TTUEdge + from *WeightedAuthorizationModelNode + to *WeightedAuthorizationModelNode + wildcards []string // e.g. "user". This means that in the direction of this edge there is a path to node user:* + // conditions on the edge. This is a flattened graph with dedupx edges, + // if you have a node with multiple edges to another node will be deduplicate and instead + // only one edge but with multiple conditions, + // define rel1: [user, user with condX] + // then the node rel1 will have an edge pointing to the node user and with two conditions + // one that will be none and another one that will be condX + conditions []string } // GetWeights returns the entire weights map. @@ -25,9 +32,14 @@ func (edge *WeightedAuthorizationModelEdge) GetEdgeType() EdgeType { return edge.edgeType } -// GetConditionedOn returns the conditionedOn field, e.g. "document#parent". -func (edge *WeightedAuthorizationModelEdge) GetConditionedOn() string { - return edge.conditionedOn +// GetTuplesetRelation returns the tuplesetRelation field, e.g. "document#parent". +func (edge *WeightedAuthorizationModelEdge) GetTuplesetRelation() string { + return edge.tuplesetRelation +} + +// GetConditions returns the conditions field, e.g. "none, condX". +func (edge *WeightedAuthorizationModelEdge) GetConditions() []string { + return edge.conditions } // GetFrom returns the from node. diff --git a/pkg/go/graph/weighted_graph_test.go b/pkg/go/graph/weighted_graph_test.go index 5a57f762..81a579d5 100644 --- a/pkg/go/graph/weighted_graph_test.go +++ b/pkg/go/graph/weighted_graph_test.go @@ -34,20 +34,20 @@ func TestValidWeight1OneTerminalType(t *testing.T) { graph.AddNode("user", "user", SpecificType) graph.AddNode("user:*", "user:*", SpecificTypeWildcard) - graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "") - graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "user", DirectEdge, "") - graph.AddEdge("state-member", "user", DirectEdge, "") - graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "") - graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "") - graph.AddEdge("state-owner-and", "user", DirectEdge, "") - graph.AddEdge("state-approved_member", "user:*", DirectEdge, "") - graph.AddEdge("state-can_apply", "state-can_apply-or", RewriteEdge, "") - graph.AddEdge("state-can_apply-or", "state-can_apply-but", RewriteEdge, "") - graph.AddEdge("state-can_apply-or", "state-owner", ComputedEdge, "") - graph.AddEdge("state-can_apply-but", "state-approved_member", ComputedEdge, "") - graph.AddEdge("state-can_apply-but", "state-can_view", ComputedEdge, "") + graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "user", DirectEdge, "", nil) + graph.AddEdge("state-member", "user", DirectEdge, "", nil) + graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "", nil) + graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "", nil) + graph.AddEdge("state-owner-and", "user", DirectEdge, "", nil) + graph.AddEdge("state-approved_member", "user:*", DirectEdge, "", nil) + graph.AddEdge("state-can_apply", "state-can_apply-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_apply-or", "state-can_apply-but", RewriteEdge, "", nil) + graph.AddEdge("state-can_apply-or", "state-owner", ComputedEdge, "", nil) + graph.AddEdge("state-can_apply-but", "state-approved_member", ComputedEdge, "", nil) + graph.AddEdge("state-can_apply-but", "state-can_view", ComputedEdge, "", nil) err := graph.AssignWeights() require.NoError(t, err) @@ -107,13 +107,13 @@ func TestInvalidWeight1WithAndModelCycle(t *testing.T) { graph.AddNode("state-owner-and", IntersectionOperator, OperatorNode) graph.AddNode("user", "user", SpecificType) - graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "") - graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "user", DirectEdge, "") - graph.AddEdge("state-member", "user", DirectEdge, "") - graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "") - graph.AddEdge("state-owner-and", "state-can_view", ComputedEdge, "") + graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "user", DirectEdge, "", nil) + graph.AddEdge("state-member", "user", DirectEdge, "", nil) + graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "", nil) + graph.AddEdge("state-owner-and", "state-can_view", ComputedEdge, "", nil) require.Empty(t, graph.nodes["state-can_view"].wildcards) require.Empty(t, graph.nodes["state-can_view-or"].wildcards) @@ -153,20 +153,20 @@ func TestValidWeight1MultipleTerminalTypes(t *testing.T) { graph.AddNode("user", "user", SpecificType) graph.AddNode("employee", "employee", SpecificType) - graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "") - graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "user", DirectEdge, "") - graph.AddEdge("state-member", "user", DirectEdge, "") - graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "") - graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "") - graph.AddEdge("state-owner-and", "employee", DirectEdge, "") - graph.AddEdge("state-approved_member", "employee", DirectEdge, "") - graph.AddEdge("state-can_apply", "state-can_apply-or", RewriteEdge, "") - graph.AddEdge("state-can_apply-or", "state-can_apply-but", RewriteEdge, "") - graph.AddEdge("state-can_apply-or", "state-member", ComputedEdge, "") - graph.AddEdge("state-can_apply-but", "state-approved_member", ComputedEdge, "") - graph.AddEdge("state-can_apply-but", "state-can_view", ComputedEdge, "") + graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "user", DirectEdge, "", nil) + graph.AddEdge("state-member", "user", DirectEdge, "", nil) + graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "", nil) + graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "", nil) + graph.AddEdge("state-owner-and", "employee", DirectEdge, "", nil) + graph.AddEdge("state-approved_member", "employee", DirectEdge, "", nil) + graph.AddEdge("state-can_apply", "state-can_apply-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_apply-or", "state-can_apply-but", RewriteEdge, "", nil) + graph.AddEdge("state-can_apply-or", "state-member", ComputedEdge, "", nil) + graph.AddEdge("state-can_apply-but", "state-approved_member", ComputedEdge, "", nil) + graph.AddEdge("state-can_apply-but", "state-can_view", ComputedEdge, "", nil) err := graph.AssignWeights() require.NoError(t, err) @@ -228,15 +228,15 @@ func TestInvalidWeight1NotMatchingTerminalTypes(t *testing.T) { graph.AddNode("user", "user", SpecificType) graph.AddNode("employee", "employee", SpecificType) - graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "") - graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "user", DirectEdge, "") - graph.AddEdge("state-member", "user", DirectEdge, "") - graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "") - graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "") - graph.AddEdge("state-owner-and", "employee", DirectEdge, "") - graph.AddEdge("state-approved_member", "user", DirectEdge, "") + graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "user", DirectEdge, "", nil) + graph.AddEdge("state-member", "user", DirectEdge, "", nil) + graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "", nil) + graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "", nil) + graph.AddEdge("state-owner-and", "employee", DirectEdge, "", nil) + graph.AddEdge("state-approved_member", "user", DirectEdge, "", nil) err := graph.AssignWeights() require.ErrorIs(t, err, ErrInvalidModel) @@ -277,21 +277,21 @@ func TestValidWeight2TTUOneTerminalType(t *testing.T) { graph.AddNode("transition-can_apply", "can_apply", SpecificTypeAndRelation) graph.AddNode("transition-can_apply-and", IntersectionOperator, OperatorNode) - graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "") - graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "user", DirectEdge, "") - graph.AddEdge("state-member", "user:*", DirectEdge, "") - graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "") - graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "") - graph.AddEdge("state-owner-and", "user", DirectEdge, "") - graph.AddEdge("state-approved_member", "user", DirectEdge, "") - graph.AddEdge("transition-start", "state", DirectEdge, "") - graph.AddEdge("transition-end", "state", DirectEdge, "") - graph.AddEdge("transition-can_apply", "transition-can_apply-and", RewriteEdge, "") - graph.AddEdge("transition-can_apply-and", "user", DirectEdge, "") - graph.AddEdge("transition-can_apply-and", "state-can_view", TTUEdge, "transition-start") - graph.AddEdge("transition-can_apply-and", "state-can_view", TTUEdge, "transition-end") + graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "user", DirectEdge, "", nil) + graph.AddEdge("state-member", "user:*", DirectEdge, "", nil) + graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "", nil) + graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "", nil) + graph.AddEdge("state-owner-and", "user", DirectEdge, "", nil) + graph.AddEdge("state-approved_member", "user", DirectEdge, "", nil) + graph.AddEdge("transition-start", "state", DirectEdge, "", nil) + graph.AddEdge("transition-end", "state", DirectEdge, "", nil) + graph.AddEdge("transition-can_apply", "transition-can_apply-and", RewriteEdge, "", nil) + graph.AddEdge("transition-can_apply-and", "user", DirectEdge, "", nil) + graph.AddEdge("transition-can_apply-and", "state-can_view", TTUEdge, "transition-start", nil) + graph.AddEdge("transition-can_apply-and", "state-can_view", TTUEdge, "transition-end", nil) err := graph.AssignWeights() require.NoError(t, err) @@ -358,17 +358,17 @@ func TestValidWeight2UserSetOneTerminalType(t *testing.T) { graph.AddNode("user:*", "user:*", SpecificTypeWildcard) graph.AddNode("transition-can_apply", "can_apply", SpecificTypeAndRelation) - graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "") - graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "user", DirectEdge, "") - graph.AddEdge("state-member", "user:*", DirectEdge, "") - graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "") - graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "") - graph.AddEdge("state-owner-and", "user", DirectEdge, "") - graph.AddEdge("state-approved_member", "user", DirectEdge, "") - graph.AddEdge("transition-can_apply", "user", DirectEdge, "") - graph.AddEdge("transition-can_apply", "state-can_view", DirectEdge, "") + graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-owner", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "user", DirectEdge, "", nil) + graph.AddEdge("state-member", "user:*", DirectEdge, "", nil) + graph.AddEdge("state-owner", "state-owner-and", RewriteEdge, "", nil) + graph.AddEdge("state-owner-and", "state-approved_member", ComputedEdge, "", nil) + graph.AddEdge("state-owner-and", "user", DirectEdge, "", nil) + graph.AddEdge("state-approved_member", "user", DirectEdge, "", nil) + graph.AddEdge("transition-can_apply", "user", DirectEdge, "", nil) + graph.AddEdge("transition-can_apply", "state-can_view", DirectEdge, "", nil) err := graph.AssignWeights() require.NoError(t, err) @@ -433,16 +433,16 @@ func TestValidWeight2MultipleTerminalType(t *testing.T) { graph.AddNode("license-active_member", "active_member", SpecificTypeAndRelation) graph.AddNode("license-owner", "owner", SpecificTypeAndRelation) - graph.AddEdge("company-member", "user", DirectEdge, "") - graph.AddEdge("company-owner", "user", DirectEdge, "") - graph.AddEdge("company-approved_member", "company-approved_member-or", RewriteEdge, "") - graph.AddEdge("company-approved_member-or", "company-member", DirectEdge, "") - graph.AddEdge("company-approved_member-or", "company-owner", ComputedEdge, "") - graph.AddEdge("group-approved_member", "employee", DirectEdge, "") - graph.AddEdge("license-active_member", "company-approved_member", TTUEdge, "company-owner") - graph.AddEdge("license-active_member", "group-approved_member", TTUEdge, "company-owner") - graph.AddEdge("license-owner", "company", DirectEdge, "") - graph.AddEdge("license-owner", "group", DirectEdge, "") + graph.AddEdge("company-member", "user", DirectEdge, "", nil) + graph.AddEdge("company-owner", "user", DirectEdge, "", nil) + graph.AddEdge("company-approved_member", "company-approved_member-or", RewriteEdge, "", nil) + graph.AddEdge("company-approved_member-or", "company-member", DirectEdge, "", nil) + graph.AddEdge("company-approved_member-or", "company-owner", ComputedEdge, "", nil) + graph.AddEdge("group-approved_member", "employee", DirectEdge, "", nil) + graph.AddEdge("license-active_member", "company-approved_member", TTUEdge, "company-owner", nil) + graph.AddEdge("license-active_member", "group-approved_member", TTUEdge, "company-owner", nil) + graph.AddEdge("license-owner", "company", DirectEdge, "", nil) + graph.AddEdge("license-owner", "group", DirectEdge, "", nil) err := graph.AssignWeights() require.NoError(t, err) @@ -491,11 +491,11 @@ func TestInvalidWeight2ModelCycle(t *testing.T) { graph.AddNode("company-approved_member-or", UnionOperator, OperatorNode) graph.AddNode("user", "user", SpecificType) - graph.AddEdge("company-member", "user", DirectEdge, "") - graph.AddEdge("company-owner", "company-approved_member", ComputedEdge, "") - graph.AddEdge("company-approved_member", "company-approved_member-or", RewriteEdge, "") - graph.AddEdge("company-approved_member-or", "company-member", DirectEdge, "") - graph.AddEdge("company-approved_member-or", "company-owner", ComputedEdge, "") + graph.AddEdge("company-member", "user", DirectEdge, "", nil) + graph.AddEdge("company-owner", "company-approved_member", ComputedEdge, "", nil) + graph.AddEdge("company-approved_member", "company-approved_member-or", RewriteEdge, "", nil) + graph.AddEdge("company-approved_member-or", "company-member", DirectEdge, "", nil) + graph.AddEdge("company-approved_member-or", "company-owner", ComputedEdge, "", nil) err := graph.AssignWeights() require.ErrorIs(t, err, ErrModelCycle) @@ -522,13 +522,13 @@ func TestInvalidWeight2ButNotMistmatchType(t *testing.T) { graph.AddNode("company-can_execute-but", ExclusionOperator, OperatorNode) graph.AddNode("user", "user", SpecificType) - graph.AddEdge("company-member", "user", DirectEdge, "") - graph.AddEdge("company-executive", "employee", DirectEdge, "") - graph.AddEdge("company-approved_member", "user", DirectEdge, "") - graph.AddEdge("company-approved_member", "company-member", DirectEdge, "") - graph.AddEdge("company-can_execute", "company-can_execute-but", RewriteEdge, "") - graph.AddEdge("company-can_execute-but", "company-executive", ComputedEdge, "") - graph.AddEdge("company-can_execute-but", "company-approved_member", ComputedEdge, "") + graph.AddEdge("company-member", "user", DirectEdge, "", nil) + graph.AddEdge("company-executive", "employee", DirectEdge, "", nil) + graph.AddEdge("company-approved_member", "user", DirectEdge, "", nil) + graph.AddEdge("company-approved_member", "company-member", DirectEdge, "", nil) + graph.AddEdge("company-can_execute", "company-can_execute-but", RewriteEdge, "", nil) + graph.AddEdge("company-can_execute-but", "company-executive", ComputedEdge, "", nil) + graph.AddEdge("company-can_execute-but", "company-approved_member", ComputedEdge, "", nil) err := graph.AssignWeights() require.ErrorIs(t, err, ErrInvalidModel) @@ -562,18 +562,18 @@ func TestValidTupleCycle(t *testing.T) { graph.AddNode("user", "user", SpecificType) graph.AddNode("employee", "employee", SpecificType) - graph.AddEdge("document-rel4", "document-rel4-or", RewriteEdge, "") - graph.AddEdge("document-rel4-or", "document-rel6", ComputedEdge, "") - graph.AddEdge("document-rel4-or", "document-rel7", ComputedEdge, "") - graph.AddEdge("document-rel6", "document-rel1", DirectEdge, "") - graph.AddEdge("document-rel7", "document-rel4", DirectEdge, "") - graph.AddEdge("document-rel1", "document-rel1-or", RewriteEdge, "") - graph.AddEdge("document-rel1-or", "document-rel2", ComputedEdge, "") - graph.AddEdge("document-rel1-or", "document-rel3", ComputedEdge, "") - graph.AddEdge("document-rel1-or", "document-rel4", ComputedEdge, "") - graph.AddEdge("document-rel2", "user", DirectEdge, "") - graph.AddEdge("document-rel3", "document-rel5", ComputedEdge, "") - graph.AddEdge("document-rel5", "employee", DirectEdge, "") + graph.AddEdge("document-rel4", "document-rel4-or", RewriteEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel6", ComputedEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel7", ComputedEdge, "", nil) + graph.AddEdge("document-rel6", "document-rel1", DirectEdge, "", nil) + graph.AddEdge("document-rel7", "document-rel4", DirectEdge, "", nil) + graph.AddEdge("document-rel1", "document-rel1-or", RewriteEdge, "", nil) + graph.AddEdge("document-rel1-or", "document-rel2", ComputedEdge, "", nil) + graph.AddEdge("document-rel1-or", "document-rel3", ComputedEdge, "", nil) + graph.AddEdge("document-rel1-or", "document-rel4", ComputedEdge, "", nil) + graph.AddEdge("document-rel2", "user", DirectEdge, "", nil) + graph.AddEdge("document-rel3", "document-rel5", ComputedEdge, "", nil) + graph.AddEdge("document-rel5", "employee", DirectEdge, "", nil) Infinite := math.MaxInt32 err := graph.AssignWeights() @@ -635,20 +635,20 @@ func TestInvalidTupleCycleWithInterceptionOfTerminalTypes(t *testing.T) { graph.AddNode("user", "user", SpecificType) graph.AddNode("employee", "employee", SpecificType) - graph.AddEdge("document-rel4", "document-rel4-and", RewriteEdge, "") - graph.AddEdge("document-rel4-and", "document-rel4-or", RewriteEdge, "") - graph.AddEdge("document-rel4-and", "document-rel5", ComputedEdge, "") - graph.AddEdge("document-rel4-or", "document-rel6", ComputedEdge, "") - graph.AddEdge("document-rel4-or", "document-rel7", ComputedEdge, "") - graph.AddEdge("document-rel6", "document-rel1", DirectEdge, "") - graph.AddEdge("document-rel7", "document-rel4", DirectEdge, "") - graph.AddEdge("document-rel1", "document-rel1-or", RewriteEdge, "") - graph.AddEdge("document-rel1-or", "document-rel2", ComputedEdge, "") - graph.AddEdge("document-rel1-or", "document-rel3", ComputedEdge, "") - graph.AddEdge("document-rel1-or", "document-rel4", ComputedEdge, "") - graph.AddEdge("document-rel2", "user", DirectEdge, "") - graph.AddEdge("document-rel3", "document-rel5", ComputedEdge, "") - graph.AddEdge("document-rel5", "employee", DirectEdge, "") + graph.AddEdge("document-rel4", "document-rel4-and", RewriteEdge, "", nil) + graph.AddEdge("document-rel4-and", "document-rel4-or", RewriteEdge, "", nil) + graph.AddEdge("document-rel4-and", "document-rel5", ComputedEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel6", ComputedEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel7", ComputedEdge, "", nil) + graph.AddEdge("document-rel6", "document-rel1", DirectEdge, "", nil) + graph.AddEdge("document-rel7", "document-rel4", DirectEdge, "", nil) + graph.AddEdge("document-rel1", "document-rel1-or", RewriteEdge, "", nil) + graph.AddEdge("document-rel1-or", "document-rel2", ComputedEdge, "", nil) + graph.AddEdge("document-rel1-or", "document-rel3", ComputedEdge, "", nil) + graph.AddEdge("document-rel1-or", "document-rel4", ComputedEdge, "", nil) + graph.AddEdge("document-rel2", "user", DirectEdge, "", nil) + graph.AddEdge("document-rel3", "document-rel5", ComputedEdge, "", nil) + graph.AddEdge("document-rel5", "employee", DirectEdge, "", nil) err := graph.AssignWeights() require.ErrorIs(t, err, ErrContrainstTupleCycle) @@ -681,21 +681,21 @@ func TestValidTupleCycleWithInterceptionNotInCycle(t *testing.T) { graph.AddNode("user", "user", SpecificType) graph.AddNode("employee", "employee", SpecificType) - graph.AddEdge("document-rel4", "document-rel4-or", RewriteEdge, "") - graph.AddEdge("document-rel4-or", "document-rel6", ComputedEdge, "") - graph.AddEdge("document-rel4-or", "document-rel7", ComputedEdge, "") - graph.AddEdge("document-rel4-or", "document-rel5", ComputedEdge, "") - graph.AddEdge("document-rel6", "employee", DirectEdge, "") - graph.AddEdge("document-rel7", "document-rel4", DirectEdge, "") - graph.AddEdge("document-rel1", "document-rel1-and", RewriteEdge, "") - graph.AddEdge("document-rel1-and", "document-rel2", ComputedEdge, "") - graph.AddEdge("document-rel1-and", "document-rel3", ComputedEdge, "") - graph.AddEdge("document-rel1-and", "document-rel4", ComputedEdge, "") - graph.AddEdge("document-rel2", "user", DirectEdge, "") - graph.AddEdge("document-rel3", "user", DirectEdge, "") - graph.AddEdge("document-rel3", "employee", DirectEdge, "") - graph.AddEdge("document-rel5", "user", DirectEdge, "") - graph.AddEdge("document-rel6", "employee", DirectEdge, "") + graph.AddEdge("document-rel4", "document-rel4-or", RewriteEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel6", ComputedEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel7", ComputedEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel5", ComputedEdge, "", nil) + graph.AddEdge("document-rel6", "employee", DirectEdge, "", nil) + graph.AddEdge("document-rel7", "document-rel4", DirectEdge, "", nil) + graph.AddEdge("document-rel1", "document-rel1-and", RewriteEdge, "", nil) + graph.AddEdge("document-rel1-and", "document-rel2", ComputedEdge, "", nil) + graph.AddEdge("document-rel1-and", "document-rel3", ComputedEdge, "", nil) + graph.AddEdge("document-rel1-and", "document-rel4", ComputedEdge, "", nil) + graph.AddEdge("document-rel2", "user", DirectEdge, "", nil) + graph.AddEdge("document-rel3", "user", DirectEdge, "", nil) + graph.AddEdge("document-rel3", "employee", DirectEdge, "", nil) + graph.AddEdge("document-rel5", "user", DirectEdge, "", nil) + graph.AddEdge("document-rel6", "employee", DirectEdge, "", nil) Infinite := math.MaxInt32 err := graph.AssignWeights() @@ -756,14 +756,14 @@ func TestValidRecursionUsersetAndTTU(t *testing.T) { graph.AddNode("employee", "employee", SpecificType) graph.AddNode("document", "document", SpecificType) - graph.AddEdge("document-rel4", "document-rel4-or", RewriteEdge, "") - graph.AddEdge("document-rel4-or", "document-rel5", ComputedEdge, "") - graph.AddEdge("document-rel4-or", "document-rel4", TTUEdge, "document-rel6") - graph.AddEdge("document-rel6", "document", DirectEdge, "") - graph.AddEdge("document-rel5", "user", DirectEdge, "") - graph.AddEdge("document-rel3", "user", DirectEdge, "") - graph.AddEdge("document-rel3", "employee", DirectEdge, "") - graph.AddEdge("document-rel3", "document-rel3", DirectEdge, "") + graph.AddEdge("document-rel4", "document-rel4-or", RewriteEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel5", ComputedEdge, "", nil) + graph.AddEdge("document-rel4-or", "document-rel4", TTUEdge, "document-rel6", nil) + graph.AddEdge("document-rel6", "document", DirectEdge, "", nil) + graph.AddEdge("document-rel5", "user", DirectEdge, "", nil) + graph.AddEdge("document-rel3", "user", DirectEdge, "", nil) + graph.AddEdge("document-rel3", "employee", DirectEdge, "", nil) + graph.AddEdge("document-rel3", "document-rel3", DirectEdge, "", nil) Infinite := math.MaxInt32 err := graph.AssignWeights() @@ -820,20 +820,20 @@ func TestValidRecursionWithWeight3(t *testing.T) { graph.AddNode("group-owner", "owner", SpecificTypeAndRelation) graph.AddNode("group-max_owner", "max_owner", SpecificTypeAndRelation) - graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "") - graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "") - graph.AddEdge("state-can_view-or", "user", DirectEdge, "") - graph.AddEdge("state-member", "user", DirectEdge, "") - graph.AddEdge("transition-start", "state", DirectEdge, "") - graph.AddEdge("transition-end", "state", DirectEdge, "") - graph.AddEdge("transition-can_apply", "transition-can_apply-and", RewriteEdge, "") - graph.AddEdge("transition-can_apply-and", "user", DirectEdge, "") - graph.AddEdge("transition-can_apply-and", "state-can_view", TTUEdge, "transition-start") - graph.AddEdge("transition-can_apply-and", "state-can_view", TTUEdge, "transition-end") - graph.AddEdge("group-owner", "user", DirectEdge, "") - graph.AddEdge("group-owner", "transition-can_apply", DirectEdge, "") - graph.AddEdge("group-max_owner", "group-owner", DirectEdge, "") - graph.AddEdge("group-max_owner", "group-max_owner", DirectEdge, "") + graph.AddEdge("state-can_view", "state-can_view-or", RewriteEdge, "", nil) + graph.AddEdge("state-can_view-or", "state-member", ComputedEdge, "", nil) + graph.AddEdge("state-can_view-or", "user", DirectEdge, "", nil) + graph.AddEdge("state-member", "user", DirectEdge, "", nil) + graph.AddEdge("transition-start", "state", DirectEdge, "", nil) + graph.AddEdge("transition-end", "state", DirectEdge, "", nil) + graph.AddEdge("transition-can_apply", "transition-can_apply-and", RewriteEdge, "", nil) + graph.AddEdge("transition-can_apply-and", "user", DirectEdge, "", nil) + graph.AddEdge("transition-can_apply-and", "state-can_view", TTUEdge, "transition-start", nil) + graph.AddEdge("transition-can_apply-and", "state-can_view", TTUEdge, "transition-end", nil) + graph.AddEdge("group-owner", "user", DirectEdge, "", nil) + graph.AddEdge("group-owner", "transition-can_apply", DirectEdge, "", nil) + graph.AddEdge("group-max_owner", "group-owner", DirectEdge, "", nil) + graph.AddEdge("group-max_owner", "group-max_owner", DirectEdge, "", nil) Infinite := math.MaxInt32 err := graph.AssignWeights() @@ -969,64 +969,64 @@ func TestValidRecursionWithMultipleWeightsAndTypes(t *testing.T) { graph.AddNode("feature-can_access", "can_access", SpecificTypeAndRelation) graph.AddNode("feature-can_access-and", IntersectionOperator, OperatorNode) - graph.AddEdge("company-member", "user", DirectEdge, "") - graph.AddEdge("company-member", "employee", DirectEdge, "") - graph.AddEdge("company-member", "user:*", DirectEdge, "") - graph.AddEdge("company-facilitator", "company-member", ComputedEdge, "") - graph.AddEdge("company-user_in_context", "user", DirectEdge, "x_less_than") - graph.AddEdge("company-approved_member", "company-approved_member-and", RewriteEdge, "") - graph.AddEdge("company-approved_member-and", "company-member", ComputedEdge, "") - graph.AddEdge("company-approved_member-and", "company-user_in_context", ComputedEdge, "") - - graph.AddEdge("group-member", "user", DirectEdge, "") - graph.AddEdge("group-member", "user", DirectEdge, "x_greater_than") - graph.AddEdge("group-user_in_context", "user", DirectEdge, "") - graph.AddEdge("group-reader", "group-member", ComputedEdge, "") - graph.AddEdge("group-assignee", "group-reader", ComputedEdge, "") - graph.AddEdge("group-approved_member", "group-approved_member-butnot", RewriteEdge, "") - graph.AddEdge("group-approved_member-butnot", "group-user_in_context", ComputedEdge, "") - graph.AddEdge("group-approved_member-butnot", "group-member", ComputedEdge, "") - - graph.AddEdge("license-active_holder", "license-active_holder-or", RewriteEdge, "") - graph.AddEdge("license-active_holder-or", "license-holder", ComputedEdge, "") - graph.AddEdge("license-active_holder-or", "license-holder_member", ComputedEdge, "") - graph.AddEdge("license-owner", "company", DirectEdge, "") - graph.AddEdge("license-owner", "group", DirectEdge, "") - graph.AddEdge("license-owner", "group", DirectEdge, "x_condition") - graph.AddEdge("license-holder_member", "group-member", TTUEdge, "license-owner") - graph.AddEdge("license-holder_member", "company-member", TTUEdge, "license-owner") - graph.AddEdge("license-holder_member", "group-member", TTUEdge, "license-owner") - graph.AddEdge("license-holder_approved_member", "group-approved_member", TTUEdge, "license-owner") - graph.AddEdge("license-holder_approved_member", "company-approved_member", TTUEdge, "license-owner") - graph.AddEdge("license-holder_approved_member", "group-approved_member", TTUEdge, "license-owner") - graph.AddEdge("license-holder", "user", DirectEdge, "") - graph.AddEdge("license-parent", "license", DirectEdge, "") - graph.AddEdge("license-trust_holder", "license-trust_holder-or", RewriteEdge, "") - graph.AddEdge("license-trust_holder-or", "user", DirectEdge, "") - graph.AddEdge("license-trust_holder-or", "user:*", DirectEdge, "") - graph.AddEdge("license-trust_holder-or", "license-trust_holder", TTUEdge, "license-parent") - - graph.AddEdge("tier-subscriber", "company-facilitator", DirectEdge, "") - graph.AddEdge("tier-assignee", "group-assignee", DirectEdge, "") - graph.AddEdge("tier-assignee", "group-user_in_context", DirectEdge, "") - graph.AddEdge("tier-assignee", "group-user_in_context", DirectEdge, "x_bigger_than") - graph.AddEdge("tier-subtier_owner", "user", DirectEdge, "") - graph.AddEdge("tier-subtier_owner", "tier-subtier_owner", DirectEdge, "") - graph.AddEdge("tier-assignee_sub", "tier-assignee_sub-and", RewriteEdge, "") - graph.AddEdge("tier-assignee_sub-and", "tier-subscriber", ComputedEdge, "") - graph.AddEdge("tier-assignee_sub-and", "tier-assignee", ComputedEdge, "") - graph.AddEdge("tier-assignee_sub-and", "tier-subtier_owner", ComputedEdge, "") - - graph.AddEdge("module-associated_license", "license", DirectEdge, "") - graph.AddEdge("module-module_holder", "license-holder_member", TTUEdge, "module-associated_license") - graph.AddEdge("module-module_user", "license-active_holder", TTUEdge, "module-associated_license") - - graph.AddEdge("feature-associated_module", "module", DirectEdge, "") - graph.AddEdge("feature-associated_tier", "tier", DirectEdge, "") - graph.AddEdge("feature-tier_can_access", "tier-subscriber", TTUEdge, "feature-associated_tier") - graph.AddEdge("feature-can_access", "feature-can_access-and", RewriteEdge, "") - graph.AddEdge("feature-can_access-and", "module-module_user", TTUEdge, "feature-associated_module") - graph.AddEdge("feature-can_access-and", "tier-subscriber", TTUEdge, "feature-associated_tier") + graph.AddEdge("company-member", "user", DirectEdge, "", nil) + graph.AddEdge("company-member", "employee", DirectEdge, "", nil) + graph.AddEdge("company-member", "user:*", DirectEdge, "", nil) + graph.AddEdge("company-facilitator", "company-member", ComputedEdge, "", nil) + graph.AddEdge("company-user_in_context", "user", DirectEdge, "x_less_than", nil) + graph.AddEdge("company-approved_member", "company-approved_member-and", RewriteEdge, "", nil) + graph.AddEdge("company-approved_member-and", "company-member", ComputedEdge, "", nil) + graph.AddEdge("company-approved_member-and", "company-user_in_context", ComputedEdge, "", nil) + + graph.AddEdge("group-member", "user", DirectEdge, "", nil) + graph.AddEdge("group-member", "user", DirectEdge, "x_greater_than", nil) + graph.AddEdge("group-user_in_context", "user", DirectEdge, "", nil) + graph.AddEdge("group-reader", "group-member", ComputedEdge, "", nil) + graph.AddEdge("group-assignee", "group-reader", ComputedEdge, "", nil) + graph.AddEdge("group-approved_member", "group-approved_member-butnot", RewriteEdge, "", nil) + graph.AddEdge("group-approved_member-butnot", "group-user_in_context", ComputedEdge, "", nil) + graph.AddEdge("group-approved_member-butnot", "group-member", ComputedEdge, "", nil) + + graph.AddEdge("license-active_holder", "license-active_holder-or", RewriteEdge, "", nil) + graph.AddEdge("license-active_holder-or", "license-holder", ComputedEdge, "", nil) + graph.AddEdge("license-active_holder-or", "license-holder_member", ComputedEdge, "", nil) + graph.AddEdge("license-owner", "company", DirectEdge, "", nil) + graph.AddEdge("license-owner", "group", DirectEdge, "", nil) + graph.AddEdge("license-owner", "group", DirectEdge, "x_condition", nil) + graph.AddEdge("license-holder_member", "group-member", TTUEdge, "license-owner", nil) + graph.AddEdge("license-holder_member", "company-member", TTUEdge, "license-owner", nil) + graph.AddEdge("license-holder_member", "group-member", TTUEdge, "license-owner", nil) + graph.AddEdge("license-holder_approved_member", "group-approved_member", TTUEdge, "license-owner", nil) + graph.AddEdge("license-holder_approved_member", "company-approved_member", TTUEdge, "license-owner", nil) + graph.AddEdge("license-holder_approved_member", "group-approved_member", TTUEdge, "license-owner", nil) + graph.AddEdge("license-holder", "user", DirectEdge, "", nil) + graph.AddEdge("license-parent", "license", DirectEdge, "", nil) + graph.AddEdge("license-trust_holder", "license-trust_holder-or", RewriteEdge, "", nil) + graph.AddEdge("license-trust_holder-or", "user", DirectEdge, "", nil) + graph.AddEdge("license-trust_holder-or", "user:*", DirectEdge, "", nil) + graph.AddEdge("license-trust_holder-or", "license-trust_holder", TTUEdge, "license-parent", nil) + + graph.AddEdge("tier-subscriber", "company-facilitator", DirectEdge, "", nil) + graph.AddEdge("tier-assignee", "group-assignee", DirectEdge, "", nil) + graph.AddEdge("tier-assignee", "group-user_in_context", DirectEdge, "", nil) + graph.AddEdge("tier-assignee", "group-user_in_context", DirectEdge, "x_bigger_than", nil) + graph.AddEdge("tier-subtier_owner", "user", DirectEdge, "", nil) + graph.AddEdge("tier-subtier_owner", "tier-subtier_owner", DirectEdge, "", nil) + graph.AddEdge("tier-assignee_sub", "tier-assignee_sub-and", RewriteEdge, "", nil) + graph.AddEdge("tier-assignee_sub-and", "tier-subscriber", ComputedEdge, "", nil) + graph.AddEdge("tier-assignee_sub-and", "tier-assignee", ComputedEdge, "", nil) + graph.AddEdge("tier-assignee_sub-and", "tier-subtier_owner", ComputedEdge, "", nil) + + graph.AddEdge("module-associated_license", "license", DirectEdge, "", nil) + graph.AddEdge("module-module_holder", "license-holder_member", TTUEdge, "module-associated_license", nil) + graph.AddEdge("module-module_user", "license-active_holder", TTUEdge, "module-associated_license", nil) + + graph.AddEdge("feature-associated_module", "module", DirectEdge, "", nil) + graph.AddEdge("feature-associated_tier", "tier", DirectEdge, "", nil) + graph.AddEdge("feature-tier_can_access", "tier-subscriber", TTUEdge, "feature-associated_tier", nil) + graph.AddEdge("feature-can_access", "feature-can_access-and", RewriteEdge, "", nil) + graph.AddEdge("feature-can_access-and", "module-module_user", TTUEdge, "feature-associated_module", nil) + graph.AddEdge("feature-can_access-and", "tier-subscriber", TTUEdge, "feature-associated_tier", nil) Infinite := math.MaxInt32 err := graph.AssignWeights()