github.com/fortexxx/gqlgen@v0.10.3-0.20191216030626-ca5ea8b21ead/example/todo/todo.go (about) 1 //go:generate go run ../../testdata/gqlgen.go 2 3 package todo 4 5 import ( 6 "context" 7 "errors" 8 "fmt" 9 "time" 10 11 "github.com/99designs/gqlgen/graphql" 12 "github.com/mitchellh/mapstructure" 13 ) 14 15 var you = &User{ID: 1, Name: "You"} 16 var them = &User{ID: 2, Name: "Them"} 17 18 func getUserId(ctx context.Context) int { 19 if id, ok := ctx.Value("userId").(int); ok { 20 return id 21 } 22 return you.ID 23 } 24 25 func New() Config { 26 c := Config{ 27 Resolvers: &resolvers{ 28 todos: []*Todo{ 29 {ID: 1, Text: "A todo not to forget", Done: false, owner: you}, 30 {ID: 2, Text: "This is the most important", Done: false, owner: you}, 31 {ID: 3, Text: "Somebody else's todo", Done: true, owner: them}, 32 {ID: 4, Text: "Please do this or else", Done: false, owner: you}, 33 }, 34 lastID: 4, 35 }, 36 } 37 c.Directives.HasRole = func(ctx context.Context, obj interface{}, next graphql.Resolver, role Role) (interface{}, error) { 38 switch role { 39 case RoleAdmin: 40 // No admin for you! 41 return nil, nil 42 case RoleOwner: 43 ownable, isOwnable := obj.(Ownable) 44 if !isOwnable { 45 return nil, fmt.Errorf("obj cant be owned") 46 } 47 48 if ownable.Owner().ID != getUserId(ctx) { 49 return nil, fmt.Errorf("you dont own that") 50 } 51 } 52 53 return next(ctx) 54 } 55 c.Directives.User = func(ctx context.Context, obj interface{}, next graphql.Resolver, id int) (interface{}, error) { 56 return next(context.WithValue(ctx, "userId", id)) 57 } 58 return c 59 } 60 61 type resolvers struct { 62 todos []*Todo 63 lastID int 64 } 65 66 func (r *resolvers) MyQuery() MyQueryResolver { 67 return (*QueryResolver)(r) 68 } 69 70 func (r *resolvers) MyMutation() MyMutationResolver { 71 return (*MutationResolver)(r) 72 } 73 74 type QueryResolver resolvers 75 76 func (r *QueryResolver) Todo(ctx context.Context, id int) (*Todo, error) { 77 time.Sleep(220 * time.Millisecond) 78 79 if id == 666 { 80 panic("critical failure") 81 } 82 83 for _, todo := range r.todos { 84 if todo.ID == id { 85 return todo, nil 86 } 87 } 88 return nil, errors.New("not found") 89 } 90 91 func (r *QueryResolver) LastTodo(ctx context.Context) (*Todo, error) { 92 if len(r.todos) == 0 { 93 return nil, errors.New("not found") 94 } 95 return r.todos[len(r.todos)-1], nil 96 } 97 98 func (r *QueryResolver) Todos(ctx context.Context) ([]*Todo, error) { 99 return r.todos, nil 100 } 101 102 type MutationResolver resolvers 103 104 func (r *MutationResolver) CreateTodo(ctx context.Context, todo TodoInput) (*Todo, error) { 105 newID := r.id() 106 107 newTodo := &Todo{ 108 ID: newID, 109 Text: todo.Text, 110 owner: you, 111 } 112 113 if todo.Done != nil { 114 newTodo.Done = *todo.Done 115 } 116 117 r.todos = append(r.todos, newTodo) 118 119 return newTodo, nil 120 } 121 122 func (r *MutationResolver) UpdateTodo(ctx context.Context, id int, changes map[string]interface{}) (*Todo, error) { 123 var affectedTodo *Todo 124 125 for i := 0; i < len(r.todos); i++ { 126 if r.todos[i].ID == id { 127 affectedTodo = r.todos[i] 128 break 129 } 130 } 131 132 if affectedTodo == nil { 133 return nil, nil 134 } 135 136 err := mapstructure.Decode(changes, affectedTodo) 137 if err != nil { 138 panic(err) 139 } 140 141 return affectedTodo, nil 142 } 143 144 func (r *MutationResolver) id() int { 145 r.lastID++ 146 return r.lastID 147 }