First pass of gql read permission

graph-rework-2
noah metz 2023-07-21 19:16:30 -06:00
parent 97815c86ff
commit 76512afd4e
5 changed files with 98 additions and 92 deletions

@ -16,7 +16,7 @@ var GQLMutationSendUpdate = NewField(func()*graphql.Field {
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
ctx, err := GetResolveContext(p)
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
@ -83,7 +83,7 @@ var GQLMutationStartChild = NewField(func()*graphql.Field{
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
ctx, err := GetResolveContext(p)
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}

@ -6,7 +6,7 @@ import (
var GQLQuerySelf = &graphql.Field{
Type: GQLTypeGQLThread.Type,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
ctx, err := GetResolveContext(p)
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
@ -23,7 +23,7 @@ var GQLQuerySelf = &graphql.Field{
var GQLQueryUser = &graphql.Field{
Type: GQLTypeUser.Type,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
ctx, err := GetResolveContext(p)
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}

@ -5,7 +5,7 @@ import (
"github.com/graphql-go/graphql"
)
func GetResolveContext(p graphql.ResolveParams) (*ResolveContext, error) {
func PrepResolve(p graphql.ResolveParams) (*ResolveContext, error) {
resolve_context, ok := p.Context.Value("resolve").(*ResolveContext)
if ok == false {
return nil, fmt.Errorf("Bad resolve in params context")
@ -43,28 +43,42 @@ func ExtractID(p graphql.ResolveParams, name string) (NodeID, error) {
}
func GQLNodeID(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(Node)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to Node")
}
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) error {
return node.Allowed("read", "id", ctx.User)
})
if err != nil {
return nil, err
}
return node.ID(), nil
}
func GQLThreadListen(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(*GQLThread)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to GQLThread")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
}
listen := ""
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) (error) {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) error {
listen = node.Listen
return nil
return node.Allowed("read", "listen", ctx.User)
})
if err != nil {
@ -75,20 +89,20 @@ func GQLThreadListen(p graphql.ResolveParams) (interface{}, error) {
}
func GQLThreadParent(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(Thread)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to Thread")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
}
var parent Thread = nil
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) (error) {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) (error) {
parent = node.Parent()
return nil
return node.Allowed("read", "parent", ctx.User)
})
if err != nil {
@ -99,20 +113,20 @@ func GQLThreadParent(p graphql.ResolveParams) (interface{}, error) {
}
func GQLThreadState(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(Thread)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to Thread")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
}
var state string
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) (error) {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) (error) {
state = node.State()
return nil
return node.Allowed("read", "state", ctx.User)
})
if err != nil {
@ -123,20 +137,20 @@ func GQLThreadState(p graphql.ResolveParams) (interface{}, error) {
}
func GQLThreadChildren(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(Thread)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to Thread")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
}
var children []Thread = nil
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) (error) {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) (error) {
children = node.Children()
return nil
return node.Allowed("read", "children", ctx.User)
})
if err != nil {
@ -147,20 +161,20 @@ func GQLThreadChildren(p graphql.ResolveParams) (interface{}, error) {
}
func GQLLockableName(p graphql.ResolveParams) (interface{}, error) {
node, ok := p.Source.(Lockable)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to Lockable")
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
ctx, ok := p.Context.Value("graph_context").(*Context)
node, ok := p.Source.(Lockable)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
return nil, fmt.Errorf("Failed to cast source to Lockable")
}
name := ""
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) error {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) error {
name = node.Name()
return nil
return node.Allowed("read", "name", ctx.User)
})
if err != nil {
@ -171,20 +185,20 @@ func GQLLockableName(p graphql.ResolveParams) (interface{}, error) {
}
func GQLLockableRequirements(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(Lockable)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to Lockable")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
}
var requirements []Lockable = nil
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) (error) {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) (error) {
requirements = node.Requirements()
return nil
return node.Allowed("read", "requirements", ctx.User)
})
if err != nil {
@ -195,20 +209,20 @@ func GQLLockableRequirements(p graphql.ResolveParams) (interface{}, error) {
}
func GQLLockableDependencies(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(Lockable)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to Lockable")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
}
var dependencies []Lockable = nil
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) (error) {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) (error) {
dependencies = node.Dependencies()
return nil
return node.Allowed("read", "dependencies", ctx.User)
})
if err != nil {
@ -219,20 +233,20 @@ func GQLLockableDependencies(p graphql.ResolveParams) (interface{}, error) {
}
func GQLLockableOwner(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(Lockable)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to Lockable")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
}
var owner Node = nil
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) (error) {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) (error) {
owner = node.Owner()
return nil
return node.Allowed("read", "owner", ctx.User)
})
if err != nil {
@ -243,25 +257,25 @@ func GQLLockableOwner(p graphql.ResolveParams) (interface{}, error) {
}
func GQLThreadUsers(p graphql.ResolveParams) (interface{}, error) {
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
node, ok := p.Source.(*GQLThread)
if ok == false || node == nil {
return nil, fmt.Errorf("Failed to cast source to GQLThread")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to cast context graph_context to Context")
}
var users []*User
err := UseStates(ctx, []Node{node}, func(nodes NodeMap) error {
err = UseStates(ctx.Context, []Node{node, ctx.User}, func(nodes NodeMap) error {
users = make([]*User, len(node.Users))
i := 0
for _, user := range(node.Users) {
users[i] = user
i += 1
}
return nil
return node.Allowed("read", "users", ctx.User)
})
if err != nil {

@ -1,6 +1,5 @@
package graphvent
import (
"fmt"
"github.com/graphql-go/graphql"
)
@ -17,19 +16,14 @@ func GQLSubscribeSelf(p graphql.ResolveParams) (interface{}, error) {
}
func GQLSubscribeFn(p graphql.ResolveParams, send_nil bool, fn func(*Context, *GQLThread, GraphSignal, graphql.ResolveParams)(interface{}, error))(interface{}, error) {
server, ok := p.Context.Value("gql_server").(*GQLThread)
if ok == false {
return nil, fmt.Errorf("Failed to get gql_server from context and cast to GQLServer")
}
ctx, ok := p.Context.Value("graph_context").(*Context)
if ok == false {
return nil, fmt.Errorf("Failed to get graph_context from context and cast to Context")
ctx, err := PrepResolve(p)
if err != nil {
return nil, err
}
c := make(chan interface{})
go func(c chan interface{}, server *GQLThread) {
ctx.Log.Logf("gqlws", "GQL_SUBSCRIBE_THREAD_START")
ctx.Context.Log.Logf("gqlws", "GQL_SUBSCRIBE_THREAD_START")
sig_c := UpdateChannel(server, 1, RandID())
if send_nil == true {
sig_c <- nil
@ -39,14 +33,14 @@ func GQLSubscribeFn(p graphql.ResolveParams, send_nil bool, fn func(*Context, *G
if ok == false {
return
}
ret, err := fn(ctx, server, val, p)
ret, err := fn(ctx.Context, server, val, p)
if err != nil {
ctx.Log.Logf("gqlws", "type convertor error %s", err)
ctx.Context.Log.Logf("gqlws", "type convertor error %s", err)
return
}
c <- ret
}
}(c, server)
}(c, ctx.Server)
return c, nil
}

@ -406,21 +406,22 @@ func LoadNodeRecurse(ctx * Context, id NodeID, nodes NodeMap) (Node, error) {
return node, nil
}
// Internal function to check for a duplicate node in a slice by ID
func checkForDuplicate(nodes []Node) error {
// Internal function to filter duplicate nodes from a list
func filterDuplicates(nodes []Node) []Node {
ret := []Node{}
found := map[NodeID]bool{}
for _, node := range(nodes) {
if node == nil {
return fmt.Errorf("Cannot get state of nil node")
return []Node{}
}
_, exists := found[node.ID()]
if exists == true {
return fmt.Errorf("Attempted to get state of %s twice", node.ID())
}
if exists == false {
found[node.ID()] = true
ret = append(ret, node)
}
return nil
}
return ret
}
// Convert any slice of types that implement Node to a []Node
@ -443,10 +444,7 @@ func UseStates(ctx * Context, init_nodes []Node, nodes_fn NodesFn) error {
// Add nodes to an existing read context and call nodes_fn with new_nodes locked for read
func UseMoreStates(ctx * Context, new_nodes []Node, nodes NodeMap, nodes_fn NodesFn) error {
err := checkForDuplicate(new_nodes)
if err != nil {
return err
}
new_nodes = filterDuplicates(new_nodes)
locked_nodes := []Node{}
for _, node := range(new_nodes) {
@ -458,7 +456,7 @@ func UseMoreStates(ctx * Context, new_nodes []Node, nodes NodeMap, nodes_fn Node
}
}
err = nodes_fn(nodes)
err := nodes_fn(nodes)
for _, node := range(locked_nodes) {
delete(nodes, node.ID())