Added Singleton and Field to simplify GQL definitions

graph-rework-2
noah metz 2023-07-21 17:49:19 -06:00
parent 551370e541
commit d4fcd80ff8
7 changed files with 636 additions and 663 deletions

@ -120,6 +120,10 @@ type GQLContext struct {
ValidLockables ObjTypeMap ValidLockables ObjTypeMap
ValidThreads ObjTypeMap ValidThreads ObjTypeMap
BaseNodeType *graphql.Object
BaseLockableType *graphql.Object
BaseThreadType *graphql.Object
Query *graphql.Object Query *graphql.Object
Mutation *graphql.Object Mutation *graphql.Object
Subscription *graphql.Object Subscription *graphql.Object
@ -154,6 +158,7 @@ func NewGQLContext() GQLContext {
Query: query, Query: query,
Mutation: mutation, Mutation: mutation,
Subscription: subscription, Subscription: subscription,
BaseNodeType: GQLTypeGraphNode.Type,
} }
return ctx return ctx
@ -168,48 +173,49 @@ func NewContext(db * badger.DB, log Logger) * Context {
Types: map[uint64]NodeDef{}, Types: map[uint64]NodeDef{},
} }
err := ctx.RegisterNodeType(NewNodeDef((*GraphNode)(nil), LoadGraphNode, GQLTypeGraphNode())) err := ctx.RegisterNodeType(NewNodeDef((*GraphNode)(nil), LoadGraphNode, GQLTypeGraphNode.Type))
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = ctx.RegisterNodeType(NewNodeDef((*SimpleLockable)(nil), LoadSimpleLockable, GQLTypeSimpleLockable())) err = ctx.RegisterNodeType(NewNodeDef((*SimpleLockable)(nil), LoadSimpleLockable, GQLTypeSimpleLockable.Type))
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = ctx.RegisterNodeType(NewNodeDef((*SimpleThread)(nil), LoadSimpleThread, GQLTypeSimpleThread())) err = ctx.RegisterNodeType(NewNodeDef((*SimpleThread)(nil), LoadSimpleThread, GQLTypeSimpleThread.Type))
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = ctx.RegisterNodeType(NewNodeDef((*GQLThread)(nil), LoadGQLThread, GQLTypeGQLThread())) err = ctx.RegisterNodeType(NewNodeDef((*GQLThread)(nil), LoadGQLThread, GQLTypeGQLThread.Type))
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = ctx.RegisterNodeType(NewNodeDef((*User)(nil), LoadUser, GQLTypeUser())) err = ctx.RegisterNodeType(NewNodeDef((*User)(nil), LoadUser, GQLTypeUser.Type))
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = ctx.RegisterNodeType(NewNodeDef((*PerNodePolicy)(nil), LoadPerNodePolicy, GQLTypeGraphNode())) err = ctx.RegisterNodeType(NewNodeDef((*PerNodePolicy)(nil), LoadPerNodePolicy, GQLTypeGraphNode.Type))
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = ctx.RegisterNodeType(NewNodeDef((*SimplePolicy)(nil), LoadSimplePolicy, GQLTypeGraphNode())) err = ctx.RegisterNodeType(NewNodeDef((*SimplePolicy)(nil), LoadSimplePolicy, GQLTypeGraphNode.Type))
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = ctx.RegisterNodeType(NewNodeDef((*PerTagPolicy)(nil), LoadPerTagPolicy, GQLTypeGraphNode())) err = ctx.RegisterNodeType(NewNodeDef((*PerTagPolicy)(nil), LoadPerTagPolicy, GQLTypeGraphNode.Type))
if err != nil { if err != nil {
panic(err) panic(err)
} }
ctx.AddGQLType(GQLTypeSignal()) ctx.AddGQLType(GQLTypeSignal.Type)
ctx.GQL.Query.AddFieldConfig("Self", GQLQuerySelf()) ctx.GQL.Query.AddFieldConfig("Self", GQLQuerySelf)
ctx.GQL.Query.AddFieldConfig("User", GQLQueryUser)
ctx.GQL.Subscription.AddFieldConfig("Update", GQLSubscriptionUpdate()) ctx.GQL.Subscription.AddFieldConfig("Update", GQLSubscriptionUpdate)
ctx.GQL.Subscription.AddFieldConfig("Self", GQLSubscriptionSelf()) ctx.GQL.Subscription.AddFieldConfig("Self", GQLSubscriptionSelf)
ctx.GQL.Mutation.AddFieldConfig("sendUpdate", GQLMutationSendUpdate()) ctx.GQL.Mutation.AddFieldConfig("sendUpdate", GQLMutationSendUpdate)
ctx.GQL.Mutation.AddFieldConfig("startChild", GQLMutationStartChild()) ctx.GQL.Mutation.AddFieldConfig("startChild", GQLMutationStartChild)
err = ctx.RebuildSchema() err = ctx.RebuildSchema()
if err != nil { if err != nil {

@ -4,135 +4,130 @@ import (
"github.com/graphql-go/graphql" "github.com/graphql-go/graphql"
) )
var gql_mutation_send_update *graphql.Field = nil var GQLMutationSendUpdate = NewField(func()*graphql.Field {
func GQLMutationSendUpdate() *graphql.Field { gql_mutation_send_update := &graphql.Field{
if gql_mutation_send_update == nil { Type: GQLTypeSignal.Type,
gql_mutation_send_update = &graphql.Field{ Args: graphql.FieldConfigArgument{
Type: GQLTypeSignal(), "id": &graphql.ArgumentConfig{
Args: graphql.FieldConfigArgument{ Type: graphql.String,
"id": &graphql.ArgumentConfig{
Type: graphql.String,
},
"signal": &graphql.ArgumentConfig{
Type: GQLTypeSignalInput(),
},
}, },
Resolve: func(p graphql.ResolveParams) (interface{}, error) { "signal": &graphql.ArgumentConfig{
ctx, server, user, err := PrepResolve(p) Type: GQLTypeSignalInput.Type,
if err != nil {
return nil, err
}
err = server.Allowed("signal", "self", user)
if err != nil {
return nil, err
}
signal_map, err := ExtractParam[map[string]interface{}](p, "signal")
if err != nil {
return nil, err
}
var signal GraphSignal = nil
if signal_map["Direction"] == "up" {
signal = NewSignal(server, signal_map["Type"].(string))
} else if signal_map["Direction"] == "down" {
signal = NewDownSignal(server, signal_map["Type"].(string))
} else if signal_map["Direction"] == "direct" {
signal = NewDirectSignal(server, signal_map["Type"].(string))
} else {
return nil, fmt.Errorf("Bad direction: %d", signal_map["Direction"])
}
id, err := ExtractID(p, "id")
if err != nil {
return nil, err
}
var node Node = nil
err = UseStates(ctx, []Node{server}, func(nodes NodeMap) (error){
node = FindChild(ctx, server, id, nodes)
if node == nil {
return fmt.Errorf("Failed to find ID: %s as child of server thread", id)
}
node.Signal(ctx, signal, nodes)
return nil
})
if err != nil {
return nil, err
}
return signal, nil
}, },
} },
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
ctx, server, user, err := PrepResolve(p)
if err != nil {
return nil, err
}
err = server.Allowed("signal", "self", user)
if err != nil {
return nil, err
}
signal_map, err := ExtractParam[map[string]interface{}](p, "signal")
if err != nil {
return nil, err
}
var signal GraphSignal = nil
if signal_map["Direction"] == "up" {
signal = NewSignal(server, signal_map["Type"].(string))
} else if signal_map["Direction"] == "down" {
signal = NewDownSignal(server, signal_map["Type"].(string))
} else if signal_map["Direction"] == "direct" {
signal = NewDirectSignal(server, signal_map["Type"].(string))
} else {
return nil, fmt.Errorf("Bad direction: %d", signal_map["Direction"])
}
id, err := ExtractID(p, "id")
if err != nil {
return nil, err
}
var node Node = nil
err = UseStates(ctx, []Node{server}, func(nodes NodeMap) (error){
node = FindChild(ctx, server, id, nodes)
if node == nil {
return fmt.Errorf("Failed to find ID: %s as child of server thread", id)
}
node.Signal(ctx, signal, nodes)
return nil
})
if err != nil {
return nil, err
}
return signal, nil
},
} }
return gql_mutation_send_update return gql_mutation_send_update
} })
var gql_mutation_start_child *graphql.Field = nil var GQLMutationStartChild = NewField(func()*graphql.Field{
func GQLMutationStartChild() *graphql.Field { gql_mutation_start_child := &graphql.Field{
if gql_mutation_start_child == nil { Type: GQLTypeSignal.Type,
gql_mutation_start_child = &graphql.Field{ Args: graphql.FieldConfigArgument{
Type: GQLTypeSignal(), "parent_id": &graphql.ArgumentConfig{
Args: graphql.FieldConfigArgument{ Type: graphql.String,
"parent_id": &graphql.ArgumentConfig{
Type: graphql.String,
},
"child_id": &graphql.ArgumentConfig{
Type: graphql.String,
},
"action": &graphql.ArgumentConfig{
Type: graphql.String,
DefaultValue: "start",
},
}, },
Resolve: func(p graphql.ResolveParams) (interface{}, error) { "child_id": &graphql.ArgumentConfig{
ctx, server, user, err := PrepResolve(p) Type: graphql.String,
if err != nil { },
return nil, err "action": &graphql.ArgumentConfig{
} Type: graphql.String,
DefaultValue: "start",
err = server.Allowed("start_child", "self", user) },
if err != nil { },
return nil, err Resolve: func(p graphql.ResolveParams) (interface{}, error) {
} ctx, server, user, err := PrepResolve(p)
if err != nil {
parent_id, err := ExtractID(p, "parent_id") return nil, err
if err != nil { }
return nil, err
} err = server.Allowed("start_child", "self", user)
if err != nil {
child_id, err := ExtractID(p, "child_id") return nil, err
if err != nil { }
return nil, err
} parent_id, err := ExtractID(p, "parent_id")
if err != nil {
action, err := ExtractParam[string](p, "action") return nil, err
if err != nil { }
return nil, err
child_id, err := ExtractID(p, "child_id")
if err != nil {
return nil, err
}
action, err := ExtractParam[string](p, "action")
if err != nil {
return nil, err
}
var signal GraphSignal
err = UseStates(ctx, []Node{server}, func(nodes NodeMap) (error){
node := FindChild(ctx, server, parent_id, nodes)
if node == nil {
return fmt.Errorf("Failed to find ID: %s as child of server thread", parent_id)
} }
return UseMoreStates(ctx, []Node{node}, nodes, func(NodeMap) error {
var signal GraphSignal signal = NewStartChildSignal(server, child_id, action)
err = UseStates(ctx, []Node{server}, func(nodes NodeMap) (error){ return node.Signal(ctx, signal, nodes)
node := FindChild(ctx, server, parent_id, nodes)
if node == nil {
return fmt.Errorf("Failed to find ID: %s as child of server thread", parent_id)
}
return UseMoreStates(ctx, []Node{node}, nodes, func(NodeMap) error {
signal = NewStartChildSignal(server, child_id, action)
return node.Signal(ctx, signal, nodes)
})
}) })
if err != nil { })
return nil, err if err != nil {
} return nil, err
}
// TODO: wait for the result of the signal to send back instead of just the signal
return signal, nil // TODO: wait for the result of the signal to send back instead of just the signal
}, return signal, nil
} },
} }
return gql_mutation_start_child return gql_mutation_start_child
} })

@ -1,30 +1,38 @@
package graphvent package graphvent
import ( import (
"fmt"
"github.com/graphql-go/graphql" "github.com/graphql-go/graphql"
) )
var gql_query_self *graphql.Field = nil var GQLQuerySelf = &graphql.Field{
func GQLQuerySelf() *graphql.Field { Type: GQLTypeGQLThread.Type,
if gql_query_self == nil { Resolve: func(p graphql.ResolveParams) (interface{}, error) {
gql_query_self = &graphql.Field{ _, server, user, err := PrepResolve(p)
Type: GQLTypeGQLThread(), if err != nil {
Resolve: func(p graphql.ResolveParams) (interface{}, error) { return nil, err
_, server, user, err := PrepResolve(p) }
if err != nil { err = server.Allowed("enumerate", "self", user)
return nil, err if err != nil {
} return nil, err
}
err = server.Allowed("enumerate", "self", user) return server, nil
if err != nil { },
return nil, fmt.Errorf("User %s is not allowed to perform self.enumerate on %s", user.ID(), server.ID()) }
}
var GQLQueryUser = &graphql.Field{
Type: GQLTypeUser.Type,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
_, _, user, err := PrepResolve(p)
if err != nil {
return nil, err
}
return server, nil err = user.Allowed("enumerate", "self", user)
}, if err != nil {
return nil, err
} }
}
return gql_query_self return user, nil
},
} }

@ -50,33 +50,26 @@ func GQLSubscribeFn(p graphql.ResolveParams, send_nil bool, fn func(*Context, *G
return c, nil return c, nil
} }
var gql_subscription_self * graphql.Field = nil var GQLSubscriptionSelf = NewField(func()*graphql.Field{
func GQLSubscriptionSelf() * graphql.Field { gql_subscription_self := &graphql.Field{
if gql_subscription_self == nil { Type: GQLTypeGQLThread.Type,
gql_subscription_self = &graphql.Field{ Resolve: func(p graphql.ResolveParams) (interface{}, error) {
Type: GQLTypeGQLThread(), return p.Source, nil
Resolve: func(p graphql.ResolveParams) (interface{}, error) { },
return p.Source, nil Subscribe: GQLSubscribeSelf,
},
Subscribe: GQLSubscribeSelf,
}
} }
return gql_subscription_self return gql_subscription_self
} })
var gql_subscription_update * graphql.Field = nil var GQLSubscriptionUpdate = NewField(func()*graphql.Field{
func GQLSubscriptionUpdate() * graphql.Field { gql_subscription_update := &graphql.Field{
if gql_subscription_update == nil { Type: GQLTypeSignal.Type,
gql_subscription_update = &graphql.Field{ Resolve: func(p graphql.ResolveParams) (interface{}, error) {
Type: GQLTypeSignal(), return p.Source, nil
Resolve: func(p graphql.ResolveParams) (interface{}, error) { },
return p.Source, nil Subscribe: GQLSubscribeSignal,
},
Subscribe: GQLSubscribeSignal,
}
} }
return gql_subscription_update return gql_subscription_update
} })

@ -237,7 +237,7 @@ func TestGQLAuth(t * testing.T) {
url = fmt.Sprintf("https://localhost:%d/gql", port) url = fmt.Sprintf("https://localhost:%d/gql", port)
ser, err := json.MarshalIndent(&GQLPayload{ ser, err := json.MarshalIndent(&GQLPayload{
Query: "query { Self { Users { ID } } }", Query: "query { Self { Users { ID, Name } } }",
}, "", " ") }, "", " ")
fatalErr(t, err) fatalErr(t, err)

@ -5,532 +5,497 @@ import (
"reflect" "reflect"
) )
var gql_interface_graph_node *graphql.Interface = nil type Field *graphql.Field
func GQLInterfaceNode() *graphql.Interface {
if gql_interface_graph_node == nil {
gql_interface_graph_node = graphql.NewInterface(graphql.InterfaceConfig{
Name: "Node",
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil
}
valid_nodes := ctx.GQL.ValidNodes
node_type := ctx.GQL.NodeType
p_type := reflect.TypeOf(p.Value)
for key, value := range(valid_nodes) {
if p_type == key {
return value
}
}
if p_type.Implements(node_type) {
return GQLTypeGraphNode()
}
return nil func NewField(init func()*graphql.Field) Field {
}, return Field(init())
Fields: graphql.Fields{},
})
gql_interface_graph_node.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String,
})
}
return gql_interface_graph_node
} }
var gql_list_thread *graphql.List = nil type Singleton[K graphql.Type] struct {
func GQLListThread() *graphql.List { Type K
if gql_list_thread == nil { List *graphql.List
gql_list_thread = graphql.NewList(GQLInterfaceThread())
}
return gql_list_thread
} }
var gql_interface_thread *graphql.Interface = nil func NewSingleton[K graphql.Type](init func() K, post_init func(K, *graphql.List)) *Singleton[K] {
func GQLInterfaceThread() *graphql.Interface { val := init()
if gql_interface_thread == nil { list := graphql.NewList(val)
gql_interface_thread = graphql.NewInterface(graphql.InterfaceConfig{ if post_init != nil {
Name: "Thread", post_init(val, list)
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil
}
valid_threads := ctx.GQL.ValidThreads
thread_type := ctx.GQL.ThreadType
p_type := reflect.TypeOf(p.Value)
for key, value := range(valid_threads) {
if p_type == key {
return value
}
}
if p_type.Implements(thread_type) {
return GQLTypeSimpleThread()
}
ctx.Log.Logf("gql", "Found no type that matches %+v: %+v", p_type, p_type.Implements(thread_type))
return nil
},
Fields: graphql.Fields{},
})
gql_interface_thread.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String,
})
gql_interface_thread.AddFieldConfig("Name", &graphql.Field{
Type: graphql.String,
})
gql_interface_thread.AddFieldConfig("State", &graphql.Field{
Type: graphql.String,
})
gql_interface_thread.AddFieldConfig("Children", &graphql.Field{
Type: GQLListThread(),
})
gql_interface_thread.AddFieldConfig("Parent", &graphql.Field{
Type: GQLInterfaceThread(),
})
gql_interface_thread.AddFieldConfig("Requirements", &graphql.Field{
Type: GQLListLockable(),
})
gql_interface_thread.AddFieldConfig("Dependencies", &graphql.Field{
Type: GQLListLockable(),
})
gql_interface_thread.AddFieldConfig("Owner", &graphql.Field{
Type: GQLInterfaceLockable(),
})
} }
return &Singleton[K]{
return gql_interface_thread Type: val,
} List: list,
var gql_list_lockable *graphql.List = nil
func GQLListLockable() *graphql.List {
if gql_list_lockable == nil {
gql_list_lockable = graphql.NewList(GQLInterfaceLockable())
} }
return gql_list_lockable
} }
var gql_interface_lockable *graphql.Interface = nil var GQLInterfaceNode = NewSingleton(func() *graphql.Interface {
func GQLInterfaceLockable() *graphql.Interface { i := graphql.NewInterface(graphql.InterfaceConfig{
if gql_interface_lockable == nil { Name: "Node",
gql_interface_lockable = graphql.NewInterface(graphql.InterfaceConfig{ ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
Name: "Lockable", ctx, ok := p.Context.Value("graph_context").(*Context)
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object { if ok == false {
ctx, ok := p.Context.Value("graph_context").(*Context) return nil
if ok == false { }
return nil
}
valid_lockables := ctx.GQL.ValidLockables valid_nodes := ctx.GQL.ValidNodes
lockable_type := ctx.GQL.LockableType node_type := ctx.GQL.NodeType
p_type := reflect.TypeOf(p.Value) p_type := reflect.TypeOf(p.Value)
for key, value := range(valid_lockables) { for key, value := range(valid_nodes) {
if p_type == key { if p_type == key {
return value return value
}
}
if p_type.Implements(lockable_type) {
return GQLTypeSimpleLockable()
} }
}
if p_type.Implements(node_type) {
return ctx.GQL.BaseNodeType
}
return nil
},
Fields: graphql.Fields{},
})
i.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String,
})
return i
}, nil)
var GQLInterfaceThread = NewSingleton(func() *graphql.Interface {
gql_interface_thread := graphql.NewInterface(graphql.InterfaceConfig{
Name: "Thread",
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil return nil
}, }
Fields: graphql.Fields{},
})
gql_interface_lockable.AddFieldConfig("ID", &graphql.Field{ valid_threads := ctx.GQL.ValidThreads
Type: graphql.String, thread_type := ctx.GQL.ThreadType
}) p_type := reflect.TypeOf(p.Value)
gql_interface_lockable.AddFieldConfig("Name", &graphql.Field{ for key, value := range(valid_threads) {
Type: graphql.String, if p_type == key {
}) return value
}
}
if gql_list_lockable == nil { if p_type.Implements(thread_type) {
gql_list_lockable = graphql.NewList(gql_interface_lockable) return ctx.GQL.BaseThreadType
} }
gql_interface_lockable.AddFieldConfig("Requirements", &graphql.Field{ ctx.Log.Logf("gql", "Found no type that matches %+v: %+v", p_type, p_type.Implements(thread_type))
Type: gql_list_lockable, return nil
}) },
Fields: graphql.Fields{},
})
gql_interface_lockable.AddFieldConfig("Dependencies", &graphql.Field{ gql_interface_thread.AddFieldConfig("ID", &graphql.Field{
Type: gql_list_lockable, Type: graphql.String,
}) })
gql_interface_lockable.AddFieldConfig("Owner", &graphql.Field{ gql_interface_thread.AddFieldConfig("Name", &graphql.Field{
Type: gql_interface_lockable, Type: graphql.String,
}) })
} gql_interface_thread.AddFieldConfig("State", &graphql.Field{
Type: graphql.String,
})
return gql_interface_lockable gql_interface_thread.AddFieldConfig("Requirements", &graphql.Field{
} Type: GQLInterfaceLockable.List,
})
var gql_list_user *graphql.List = nil gql_interface_thread.AddFieldConfig("Dependencies", &graphql.Field{
func GQLListUser() *graphql.List { Type: GQLInterfaceLockable.List,
if gql_list_user == nil { })
gql_list_user = graphql.NewList(GQLTypeUser())
}
return gql_list_user
}
var gql_type_user *graphql.Object = nil gql_interface_thread.AddFieldConfig("Owner", &graphql.Field{
func GQLTypeUser() * graphql.Object { Type: GQLInterfaceLockable.Type,
if gql_type_user == nil { })
gql_type_user = graphql.NewObject(graphql.ObjectConfig{
Name: "User",
Interfaces: []*graphql.Interface{
GQLInterfaceNode(),
GQLInterfaceLockable(),
},
IsTypeOf: func(p graphql.IsTypeOfParams) bool {
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return false
}
lockable_type := ctx.GQL.LockableType return gql_interface_thread
value_type := reflect.TypeOf(p.Value) }, func(thread *graphql.Interface, thread_list *graphql.List) {
thread.AddFieldConfig("Children", &graphql.Field{
Type: thread_list,
})
thread.AddFieldConfig("Parent", &graphql.Field{
Type: thread,
})
})
var GQLInterfaceLockable = NewSingleton(func() *graphql.Interface {
gql_interface_lockable := graphql.NewInterface(graphql.InterfaceConfig{
Name: "Lockable",
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil
}
if value_type.Implements(lockable_type) { valid_lockables := ctx.GQL.ValidLockables
return true lockable_type := ctx.GQL.LockableType
} p_type := reflect.TypeOf(p.Value)
for key, value := range(valid_lockables) {
if p_type == key {
return value
}
}
if p_type.Implements(lockable_type) {
return ctx.GQL.BaseThreadType
}
return nil
},
Fields: graphql.Fields{},
})
gql_interface_lockable.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String,
})
gql_interface_lockable.AddFieldConfig("Name", &graphql.Field{
Type: graphql.String,
})
return gql_interface_lockable
}, func(lockable *graphql.Interface, lockable_list *graphql.List) {
lockable.AddFieldConfig("Requirements", &graphql.Field{
Type: lockable_list,
})
lockable.AddFieldConfig("Dependencies", &graphql.Field{
Type: lockable_list,
})
lockable.AddFieldConfig("Owner", &graphql.Field{
Type: lockable,
})
})
var GQLTypeUser = NewSingleton(func() *graphql.Object {
gql_type_user := graphql.NewObject(graphql.ObjectConfig{
Name: "User",
Interfaces: []*graphql.Interface{
GQLInterfaceNode.Type,
GQLInterfaceLockable.Type,
},
IsTypeOf: func(p graphql.IsTypeOfParams) bool {
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return false return false
}, }
Fields: graphql.Fields{},
}) lockable_type := ctx.GQL.LockableType
value_type := reflect.TypeOf(p.Value)
gql_type_user.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String, if value_type.Implements(lockable_type) {
Resolve: GQLNodeID, return true
}) }
gql_type_user.AddFieldConfig("Name", &graphql.Field{ return false
Type: graphql.String, },
Resolve: GQLLockableName, Fields: graphql.Fields{},
}) })
gql_type_user.AddFieldConfig("Requirements", &graphql.Field{ gql_type_user.AddFieldConfig("ID", &graphql.Field{
Type: GQLListLockable(), Type: graphql.String,
Resolve: GQLLockableRequirements, Resolve: GQLNodeID,
}) })
gql_type_user.AddFieldConfig("Owner", &graphql.Field{ gql_type_user.AddFieldConfig("Name", &graphql.Field{
Type: GQLInterfaceLockable(), Type: graphql.String,
Resolve: GQLLockableOwner, Resolve: GQLLockableName,
}) })
gql_type_user.AddFieldConfig("Dependencies", &graphql.Field{ gql_type_user.AddFieldConfig("Requirements", &graphql.Field{
Type: GQLListLockable(), Type: GQLInterfaceLockable.List,
Resolve: GQLLockableDependencies, Resolve: GQLLockableRequirements,
}) })
}
gql_type_user.AddFieldConfig("Owner", &graphql.Field{
Type: GQLInterfaceLockable.Type,
Resolve: GQLLockableOwner,
})
gql_type_user.AddFieldConfig("Dependencies", &graphql.Field{
Type: GQLInterfaceLockable.List,
Resolve: GQLLockableDependencies,
})
return gql_type_user return gql_type_user
} }, nil)
var gql_type_gql_thread *graphql.Object = nil var GQLTypeGQLThread = NewSingleton(func() *graphql.Object {
func GQLTypeGQLThread() * graphql.Object { gql_type_gql_thread := graphql.NewObject(graphql.ObjectConfig{
if gql_type_gql_thread == nil { Name: "GQLThread",
gql_type_gql_thread = graphql.NewObject(graphql.ObjectConfig{ Interfaces: []*graphql.Interface{
Name: "GQLThread", GQLInterfaceNode.Type,
Interfaces: []*graphql.Interface{ GQLInterfaceThread.Type,
GQLInterfaceNode(), GQLInterfaceLockable.Type,
GQLInterfaceThread(), },
GQLInterfaceLockable(), IsTypeOf: func(p graphql.IsTypeOfParams) bool {
}, _, ok := p.Value.(*GQLThread)
IsTypeOf: func(p graphql.IsTypeOfParams) bool { return ok
_, ok := p.Value.(*GQLThread) },
return ok Fields: graphql.Fields{},
}, })
Fields: graphql.Fields{},
}) gql_type_gql_thread.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String,
gql_type_gql_thread.AddFieldConfig("ID", &graphql.Field{ Resolve: GQLNodeID,
Type: graphql.String, })
Resolve: GQLNodeID,
}) gql_type_gql_thread.AddFieldConfig("Name", &graphql.Field{
Type: graphql.String,
gql_type_gql_thread.AddFieldConfig("Name", &graphql.Field{ Resolve: GQLLockableName,
Type: graphql.String, })
Resolve: GQLLockableName,
}) gql_type_gql_thread.AddFieldConfig("State", &graphql.Field{
Type: graphql.String,
gql_type_gql_thread.AddFieldConfig("State", &graphql.Field{ Resolve: GQLThreadState,
Type: graphql.String, })
Resolve: GQLThreadState,
}) gql_type_gql_thread.AddFieldConfig("Children", &graphql.Field{
Type: GQLInterfaceThread.List,
gql_type_gql_thread.AddFieldConfig("Children", &graphql.Field{ Resolve: GQLThreadChildren,
Type: GQLListThread(), })
Resolve: GQLThreadChildren,
}) gql_type_gql_thread.AddFieldConfig("Parent", &graphql.Field{
Type: GQLInterfaceThread.Type,
gql_type_gql_thread.AddFieldConfig("Parent", &graphql.Field{ Resolve: GQLThreadParent,
Type: GQLInterfaceThread(), })
Resolve: GQLThreadParent,
}) gql_type_gql_thread.AddFieldConfig("Listen", &graphql.Field{
Type: graphql.String,
gql_type_gql_thread.AddFieldConfig("Listen", &graphql.Field{ Resolve: GQLThreadListen,
Type: graphql.String, })
Resolve: GQLThreadListen,
}) gql_type_gql_thread.AddFieldConfig("Requirements", &graphql.Field{
Type: GQLInterfaceLockable.List,
gql_type_gql_thread.AddFieldConfig("Requirements", &graphql.Field{ Resolve: GQLLockableRequirements,
Type: GQLListLockable(), })
Resolve: GQLLockableRequirements,
}) gql_type_gql_thread.AddFieldConfig("Owner", &graphql.Field{
Type: GQLInterfaceLockable.Type,
gql_type_gql_thread.AddFieldConfig("Owner", &graphql.Field{ Resolve: GQLLockableOwner,
Type: GQLInterfaceLockable(), })
Resolve: GQLLockableOwner,
}) gql_type_gql_thread.AddFieldConfig("Dependencies", &graphql.Field{
Type: GQLInterfaceLockable.List,
gql_type_gql_thread.AddFieldConfig("Dependencies", &graphql.Field{ Resolve: GQLLockableDependencies,
Type: GQLListLockable(), })
Resolve: GQLLockableDependencies,
}) gql_type_gql_thread.AddFieldConfig("Users", &graphql.Field{
Type: GQLTypeUser.List,
gql_type_gql_thread.AddFieldConfig("Users", &graphql.Field{ Resolve: GQLThreadUsers,
Type: GQLListUser(), })
Resolve: GQLThreadUsers,
})
}
return gql_type_gql_thread return gql_type_gql_thread
} }, nil)
var gql_type_simple_thread *graphql.Object = nil var GQLTypeSimpleThread = NewSingleton(func() *graphql.Object {
func GQLTypeSimpleThread() * graphql.Object { gql_type_simple_thread := graphql.NewObject(graphql.ObjectConfig{
if gql_type_simple_thread == nil { Name: "SimpleThread",
gql_type_simple_thread = graphql.NewObject(graphql.ObjectConfig{ Interfaces: []*graphql.Interface{
Name: "SimpleThread", GQLInterfaceNode.Type,
Interfaces: []*graphql.Interface{ GQLInterfaceThread.Type,
GQLInterfaceNode(), GQLInterfaceLockable.Type,
GQLInterfaceThread(), },
GQLInterfaceLockable(), IsTypeOf: func(p graphql.IsTypeOfParams) bool {
}, ctx, ok := p.Context.Value("graph_context").(*Context)
IsTypeOf: func(p graphql.IsTypeOfParams) bool { if ok == false {
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return false
}
thread_type := ctx.GQL.ThreadType
value_type := reflect.TypeOf(p.Value)
if value_type.Implements(thread_type) {
return true
}
return false return false
}, }
Fields: graphql.Fields{},
}) thread_type := ctx.GQL.ThreadType
gql_type_simple_thread.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String, value_type := reflect.TypeOf(p.Value)
Resolve: GQLNodeID,
}) if value_type.Implements(thread_type) {
return true
gql_type_simple_thread.AddFieldConfig("Name", &graphql.Field{ }
Type: graphql.String,
Resolve: GQLLockableName, return false
}) },
Fields: graphql.Fields{},
gql_type_simple_thread.AddFieldConfig("State", &graphql.Field{ })
Type: graphql.String, gql_type_simple_thread.AddFieldConfig("ID", &graphql.Field{
Resolve: GQLThreadState, Type: graphql.String,
}) Resolve: GQLNodeID,
})
gql_type_simple_thread.AddFieldConfig("Children", &graphql.Field{
Type: GQLListThread(), gql_type_simple_thread.AddFieldConfig("Name", &graphql.Field{
Resolve: GQLThreadChildren, Type: graphql.String,
}) Resolve: GQLLockableName,
})
gql_type_simple_thread.AddFieldConfig("Parent", &graphql.Field{
Type: GQLInterfaceThread(), gql_type_simple_thread.AddFieldConfig("State", &graphql.Field{
Resolve: GQLThreadParent, Type: graphql.String,
}) Resolve: GQLThreadState,
})
gql_type_simple_thread.AddFieldConfig("Requirements", &graphql.Field{
Type: GQLListLockable(), gql_type_simple_thread.AddFieldConfig("Children", &graphql.Field{
Resolve: GQLLockableRequirements, Type: GQLInterfaceThread.List,
}) Resolve: GQLThreadChildren,
})
gql_type_simple_thread.AddFieldConfig("Owner", &graphql.Field{
Type: GQLInterfaceLockable(), gql_type_simple_thread.AddFieldConfig("Parent", &graphql.Field{
Resolve: GQLLockableOwner, Type: GQLInterfaceThread.Type,
}) Resolve: GQLThreadParent,
})
gql_type_simple_thread.AddFieldConfig("Dependencies", &graphql.Field{
Type: GQLListLockable(), gql_type_simple_thread.AddFieldConfig("Requirements", &graphql.Field{
Resolve: GQLLockableDependencies, Type: GQLInterfaceLockable.List,
}) Resolve: GQLLockableRequirements,
} })
return gql_type_simple_thread
} gql_type_simple_thread.AddFieldConfig("Owner", &graphql.Field{
Type: GQLInterfaceLockable.Type,
Resolve: GQLLockableOwner,
})
gql_type_simple_thread.AddFieldConfig("Dependencies", &graphql.Field{
Type: GQLInterfaceLockable.List,
Resolve: GQLLockableDependencies,
})
var gql_type_simple_lockable *graphql.Object = nil return gql_type_simple_thread
func GQLTypeSimpleLockable() * graphql.Object { }, nil)
if gql_type_simple_lockable == nil {
gql_type_simple_lockable = graphql.NewObject(graphql.ObjectConfig{ var GQLTypeSimpleLockable = NewSingleton(func() *graphql.Object {
Name: "SimpleLockable", gql_type_simple_lockable := graphql.NewObject(graphql.ObjectConfig{
Interfaces: []*graphql.Interface{ Name: "SimpleLockable",
GQLInterfaceNode(), Interfaces: []*graphql.Interface{
GQLInterfaceLockable(), GQLInterfaceNode.Type,
}, GQLInterfaceLockable.Type,
IsTypeOf: func(p graphql.IsTypeOfParams) bool { },
ctx, ok := p.Context.Value("graph_context").(*Context) IsTypeOf: func(p graphql.IsTypeOfParams) bool {
if ok == false { ctx, ok := p.Context.Value("graph_context").(*Context)
return false if ok == false {
} return false
}
lockable_type := ctx.GQL.LockableType lockable_type := ctx.GQL.LockableType
value_type := reflect.TypeOf(p.Value) value_type := reflect.TypeOf(p.Value)
if value_type.Implements(lockable_type) { if value_type.Implements(lockable_type) {
return true return true
} }
return false return false
}, },
Fields: graphql.Fields{}, Fields: graphql.Fields{},
}) })
gql_type_simple_lockable.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String,
Resolve: GQLNodeID,
})
gql_type_simple_lockable.AddFieldConfig("Name", &graphql.Field{
Type: graphql.String,
Resolve: GQLLockableName,
})
gql_type_simple_lockable.AddFieldConfig("Requirements", &graphql.Field{
Type: GQLListLockable(),
Resolve: GQLLockableRequirements,
})
gql_type_simple_lockable.AddFieldConfig("Owner", &graphql.Field{
Type: GQLInterfaceLockable(),
Resolve: GQLLockableOwner,
})
gql_type_simple_lockable.AddFieldConfig("Dependencies", &graphql.Field{
Type: GQLListLockable(),
Resolve: GQLLockableDependencies,
})
}
return gql_type_simple_lockable
}
var gql_type_simple_node *graphql.Object = nil gql_type_simple_lockable.AddFieldConfig("ID", &graphql.Field{
func GQLTypeGraphNode() * graphql.Object { Type: graphql.String,
if gql_type_simple_node == nil { Resolve: GQLNodeID,
gql_type_simple_node = graphql.NewObject(graphql.ObjectConfig{ })
Name: "GraphNode",
Interfaces: []*graphql.Interface{
GQLInterfaceNode(),
},
IsTypeOf: func(p graphql.IsTypeOfParams) bool {
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return false
}
node_type := ctx.GQL.NodeType gql_type_simple_lockable.AddFieldConfig("Name", &graphql.Field{
value_type := reflect.TypeOf(p.Value) Type: graphql.String,
Resolve: GQLLockableName,
})
if value_type.Implements(node_type) { gql_type_simple_lockable.AddFieldConfig("Requirements", &graphql.Field{
return true Type: GQLInterfaceLockable.List,
} Resolve: GQLLockableRequirements,
})
return false gql_type_simple_lockable.AddFieldConfig("Owner", &graphql.Field{
}, Type: GQLInterfaceLockable.Type,
Fields: graphql.Fields{}, Resolve: GQLLockableOwner,
}) })
gql_type_simple_node.AddFieldConfig("ID", &graphql.Field{
Type: graphql.String,
Resolve: GQLNodeID,
})
gql_type_simple_node.AddFieldConfig("Name", &graphql.Field{
Type: graphql.String,
Resolve: GQLLockableName,
})
}
return gql_type_simple_node gql_type_simple_lockable.AddFieldConfig("Dependencies", &graphql.Field{
} Type: GQLInterfaceLockable.List,
Resolve: GQLLockableDependencies,
})
var gql_type_signal *graphql.Object = nil return gql_type_simple_lockable
func GQLTypeSignal() *graphql.Object { }, nil)
if gql_type_signal == nil {
gql_type_signal = graphql.NewObject(graphql.ObjectConfig{ var GQLTypeGraphNode = NewSingleton(func() *graphql.Object {
Name: "SignalOut", object := graphql.NewObject(graphql.ObjectConfig{
IsTypeOf: func(p graphql.IsTypeOfParams) bool { Name: "GraphNode",
_, ok := p.Value.(GraphSignal) Interfaces: []*graphql.Interface{
return ok GQLInterfaceNode.Type,
}, },
Fields: graphql.Fields{}, IsTypeOf: func(p graphql.IsTypeOfParams) bool {
}) ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
gql_type_signal.AddFieldConfig("Type", &graphql.Field{ return false
Type: graphql.String, }
Resolve: GQLSignalType,
}) node_type := ctx.GQL.NodeType
gql_type_signal.AddFieldConfig("Source", &graphql.Field{ value_type := reflect.TypeOf(p.Value)
Type: graphql.String,
Resolve: GQLSignalSource, if value_type.Implements(node_type) {
}) return true
gql_type_signal.AddFieldConfig("Direction", &graphql.Field{ }
Type: graphql.String,
Resolve: GQLSignalDirection, return false
}) },
gql_type_signal.AddFieldConfig("String", &graphql.Field{ Fields: graphql.Fields{},
Type: graphql.String, })
Resolve: GQLSignalString,
}) object.AddFieldConfig("ID", &graphql.Field{
} Type: graphql.String,
Resolve: GQLNodeID,
})
object.AddFieldConfig("Name", &graphql.Field{
Type: graphql.String,
Resolve: GQLLockableName,
})
return object
}, nil)
var GQLTypeSignal = NewSingleton(func() *graphql.Object {
gql_type_signal := graphql.NewObject(graphql.ObjectConfig{
Name: "SignalOut",
IsTypeOf: func(p graphql.IsTypeOfParams) bool {
_, ok := p.Value.(GraphSignal)
return ok
},
Fields: graphql.Fields{},
})
gql_type_signal.AddFieldConfig("Type", &graphql.Field{
Type: graphql.String,
Resolve: GQLSignalType,
})
gql_type_signal.AddFieldConfig("Source", &graphql.Field{
Type: graphql.String,
Resolve: GQLSignalSource,
})
gql_type_signal.AddFieldConfig("Direction", &graphql.Field{
Type: graphql.String,
Resolve: GQLSignalDirection,
})
gql_type_signal.AddFieldConfig("String", &graphql.Field{
Type: graphql.String,
Resolve: GQLSignalString,
})
return gql_type_signal return gql_type_signal
} }, nil)
var GQLTypeSignalInput = NewSingleton(func()*graphql.InputObject {
gql_type_signal_input := graphql.NewInputObject(graphql.InputObjectConfig{
Name: "SignalIn",
Fields: graphql.InputObjectConfigFieldMap{},
})
gql_type_signal_input.AddFieldConfig("Type", &graphql.InputObjectFieldConfig{
Type: graphql.String,
DefaultValue: "cancel",
})
gql_type_signal_input.AddFieldConfig("Direction", &graphql.InputObjectFieldConfig{
Type: graphql.String,
DefaultValue: "down",
})
var gql_type_signal_input *graphql.InputObject = nil
func GQLTypeSignalInput() *graphql.InputObject {
if gql_type_signal_input == nil {
gql_type_signal_input = graphql.NewInputObject(graphql.InputObjectConfig{
Name: "SignalIn",
Fields: graphql.InputObjectConfigFieldMap{},
})
gql_type_signal_input.AddFieldConfig("Type", &graphql.InputObjectFieldConfig{
Type: graphql.String,
DefaultValue: "cancel",
})
gql_type_signal_input.AddFieldConfig("Direction", &graphql.InputObjectFieldConfig{
Type: graphql.String,
DefaultValue: "down",
})
}
return gql_type_signal_input return gql_type_signal_input
} }, nil)

@ -101,6 +101,12 @@ func (node * GraphNode) Serialize() ([]byte, error) {
} }
func (node *GraphNode) Allowed(action string, resource string, principal Node) error { func (node *GraphNode) Allowed(action string, resource string, principal Node) error {
if principal == nil {
return fmt.Errorf("nil is not allowed to perform any actions")
}
if node.ID() == principal.ID() {
return nil
}
for _, policy := range(node.policies) { for _, policy := range(node.policies) {
if policy.Allows(action, resource, principal) == true { if policy.Allows(action, resource, principal) == true {
return nil return nil