feature(api): update gqlgen & add complexity limit
This commit is contained in:
parent
6b41461a6a
commit
e022e7914a
@ -3,7 +3,7 @@ module github.com/jordanknott/project-citadel/api
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.11.1
|
||||
github.com/99designs/gqlgen v0.11.3
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/go-chi/chi v3.3.2+incompatible
|
||||
github.com/go-chi/cors v1.0.0
|
||||
@ -13,6 +13,7 @@ require (
|
||||
github.com/lib/pq v1.0.0
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/urfave/cli v1.20.0 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.0.1
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||
)
|
||||
|
11
api/go.sum
11
api/go.sum
@ -1,10 +1,15 @@
|
||||
github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=
|
||||
github.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=
|
||||
github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4=
|
||||
github.com/99designs/gqlgen v0.11.3/go.mod h1:RgX5GRRdDWNkh4pBrdzNpNPFVsdoUFY2+adM6nb1N+4=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=
|
||||
github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -56,8 +61,12 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
@ -69,6 +78,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
|
||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=
|
||||
|
@ -101,11 +101,11 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Task struct {
|
||||
CreatedAt func(childComplexity int) int
|
||||
Name func(childComplexity int) int
|
||||
Position func(childComplexity int) int
|
||||
TaskGroupID func(childComplexity int) int
|
||||
TaskID func(childComplexity int) int
|
||||
CreatedAt func(childComplexity int) int
|
||||
Name func(childComplexity int) int
|
||||
Position func(childComplexity int) int
|
||||
TaskGroup func(childComplexity int) int
|
||||
TaskID func(childComplexity int) int
|
||||
}
|
||||
|
||||
TaskGroup struct {
|
||||
@ -164,7 +164,7 @@ type QueryResolver interface {
|
||||
TaskGroups(ctx context.Context) ([]pg.TaskGroup, error)
|
||||
}
|
||||
type TaskResolver interface {
|
||||
TaskGroupID(ctx context.Context, obj *pg.Task) (string, error)
|
||||
TaskGroup(ctx context.Context, obj *pg.Task) (*pg.TaskGroup, error)
|
||||
}
|
||||
type TaskGroupResolver interface {
|
||||
ProjectID(ctx context.Context, obj *pg.TaskGroup) (string, error)
|
||||
@ -505,12 +505,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Task.Position(childComplexity), true
|
||||
|
||||
case "Task.taskGroupID":
|
||||
if e.complexity.Task.TaskGroupID == nil {
|
||||
case "Task.taskGroup":
|
||||
if e.complexity.Task.TaskGroup == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Task.TaskGroupID(childComplexity), true
|
||||
return e.complexity.Task.TaskGroup(childComplexity), true
|
||||
|
||||
case "Task.taskID":
|
||||
if e.complexity.Task.TaskID == nil {
|
||||
@ -740,7 +740,7 @@ type TaskGroup {
|
||||
|
||||
type Task {
|
||||
taskID: ID!
|
||||
taskGroupID: String!
|
||||
taskGroup: TaskGroup!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
position: Float!
|
||||
@ -2382,7 +2382,7 @@ func (ec *executionContext) _Task_taskID(ctx context.Context, field graphql.Coll
|
||||
return ec.marshalNID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Task_taskGroupID(ctx context.Context, field graphql.CollectedField, obj *pg.Task) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _Task_taskGroup(ctx context.Context, field graphql.CollectedField, obj *pg.Task) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
@ -2399,7 +2399,7 @@ func (ec *executionContext) _Task_taskGroupID(ctx context.Context, field graphql
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Task().TaskGroupID(rctx, obj)
|
||||
return ec.resolvers.Task().TaskGroup(rctx, obj)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@ -2411,9 +2411,9 @@ func (ec *executionContext) _Task_taskGroupID(ctx context.Context, field graphql
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
res := resTmp.(*pg.TaskGroup)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
return ec.marshalNTaskGroup2ᚖgithubᚗcomᚋjordanknottᚋprojectᚑcitadelᚋapiᚋpgᚐTaskGroup(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Task_createdAt(ctx context.Context, field graphql.CollectedField, obj *pg.Task) (ret graphql.Marshaler) {
|
||||
@ -4825,7 +4825,7 @@ func (ec *executionContext) _Task(ctx context.Context, sel ast.SelectionSet, obj
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
case "taskGroupID":
|
||||
case "taskGroup":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
@ -4833,7 +4833,7 @@ func (ec *executionContext) _Task(ctx context.Context, sel ast.SelectionSet, obj
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Task_taskGroupID(ctx, field, obj)
|
||||
res = ec._Task_taskGroup(ctx, field, obj)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
|
@ -2,21 +2,46 @@ package graph
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/99designs/gqlgen/handler"
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/99designs/gqlgen/graphql/handler/extension"
|
||||
"github.com/99designs/gqlgen/graphql/handler/lru"
|
||||
"github.com/99designs/gqlgen/graphql/handler/transport"
|
||||
"github.com/99designs/gqlgen/graphql/playground"
|
||||
"github.com/jordanknott/project-citadel/api/pg"
|
||||
)
|
||||
|
||||
// NewHandler returns a new graphql endpoint handler.
|
||||
func NewHandler(repo pg.Repository) http.Handler {
|
||||
return handler.GraphQL(NewExecutableSchema(Config{
|
||||
srv := handler.New(NewExecutableSchema(Config{
|
||||
Resolvers: &Resolver{
|
||||
Repository: repo,
|
||||
},
|
||||
}))
|
||||
srv.AddTransport(transport.Websocket{
|
||||
KeepAlivePingInterval: 10 * time.Second,
|
||||
})
|
||||
srv.AddTransport(transport.Options{})
|
||||
srv.AddTransport(transport.GET{})
|
||||
srv.AddTransport(transport.POST{})
|
||||
srv.AddTransport(transport.MultipartForm{})
|
||||
|
||||
srv.SetQueryCache(lru.New(1000))
|
||||
|
||||
srv.Use(extension.AutomaticPersistedQuery{
|
||||
Cache: lru.New(100),
|
||||
})
|
||||
if isProd := os.Getenv("PRODUCTION") == "true"; isProd {
|
||||
srv.Use(extension.FixedComplexityLimit(10))
|
||||
} else {
|
||||
srv.Use(extension.Introspection{})
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// NewPlaygroundHandler returns a new GraphQL Playground handler.
|
||||
func NewPlaygroundHandler(endpoint string) http.Handler {
|
||||
return handler.Playground("GraphQL Playground", endpoint)
|
||||
return playground.Handler("GraphQL Playground", endpoint)
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ type TaskGroup {
|
||||
|
||||
type Task {
|
||||
taskID: ID!
|
||||
taskGroupID: String!
|
||||
taskGroup: TaskGroup!
|
||||
createdAt: Time!
|
||||
name: String!
|
||||
position: Float!
|
||||
|
@ -1,6 +1,7 @@
|
||||
package graph
|
||||
|
||||
// This file will be automatically regenerated based on the schema, any resolver implementations
|
||||
// will be copied through when generating and any unknown code will be moved to the end.
|
||||
package graph
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -198,8 +199,9 @@ func (r *queryResolver) TaskGroups(ctx context.Context) ([]pg.TaskGroup, error)
|
||||
return r.Repository.GetAllTaskGroups(ctx)
|
||||
}
|
||||
|
||||
func (r *taskResolver) TaskGroupID(ctx context.Context, obj *pg.Task) (string, error) {
|
||||
return obj.TaskGroupID.String(), nil
|
||||
func (r *taskResolver) TaskGroup(ctx context.Context, obj *pg.Task) (*pg.TaskGroup, error) {
|
||||
taskGroup, err := r.Repository.GetTaskGroupByID(ctx, obj.TaskGroupID)
|
||||
return &taskGroup, err
|
||||
}
|
||||
|
||||
func (r *taskGroupResolver) ProjectID(ctx context.Context, obj *pg.TaskGroup) (string, error) {
|
||||
@ -215,13 +217,26 @@ func (r *teamResolver) Projects(ctx context.Context, obj *pg.Team) ([]pg.Project
|
||||
return r.Repository.GetAllProjectsForTeam(ctx, obj.TeamID)
|
||||
}
|
||||
|
||||
func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} }
|
||||
// Mutation returns MutationResolver implementation.
|
||||
func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} }
|
||||
|
||||
// Organization returns OrganizationResolver implementation.
|
||||
func (r *Resolver) Organization() OrganizationResolver { return &organizationResolver{r} }
|
||||
func (r *Resolver) Project() ProjectResolver { return &projectResolver{r} }
|
||||
func (r *Resolver) Query() QueryResolver { return &queryResolver{r} }
|
||||
func (r *Resolver) Task() TaskResolver { return &taskResolver{r} }
|
||||
func (r *Resolver) TaskGroup() TaskGroupResolver { return &taskGroupResolver{r} }
|
||||
func (r *Resolver) Team() TeamResolver { return &teamResolver{r} }
|
||||
|
||||
// Project returns ProjectResolver implementation.
|
||||
func (r *Resolver) Project() ProjectResolver { return &projectResolver{r} }
|
||||
|
||||
// Query returns QueryResolver implementation.
|
||||
func (r *Resolver) Query() QueryResolver { return &queryResolver{r} }
|
||||
|
||||
// Task returns TaskResolver implementation.
|
||||
func (r *Resolver) Task() TaskResolver { return &taskResolver{r} }
|
||||
|
||||
// TaskGroup returns TaskGroupResolver implementation.
|
||||
func (r *Resolver) TaskGroup() TaskGroupResolver { return &taskGroupResolver{r} }
|
||||
|
||||
// Team returns TeamResolver implementation.
|
||||
func (r *Resolver) Team() TeamResolver { return &teamResolver{r} }
|
||||
|
||||
type mutationResolver struct{ *Resolver }
|
||||
type organizationResolver struct{ *Resolver }
|
||||
|
@ -27,6 +27,7 @@ type Repository interface {
|
||||
GetAllTaskGroups(ctx context.Context) ([]TaskGroup, error)
|
||||
GetAllOrganizations(ctx context.Context) ([]Organization, error)
|
||||
GetTaskGroupsForProject(ctx context.Context, projectID uuid.UUID) ([]TaskGroup, error)
|
||||
GetTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (TaskGroup, error)
|
||||
CreateOrganization(ctx context.Context, arg CreateOrganizationParams) (Organization, error)
|
||||
GetTeamsForOrganization(ctx context.Context, organizationID uuid.UUID) ([]Team, error)
|
||||
CreateTask(ctx context.Context, arg CreateTaskParams) (Task, error)
|
||||
|
@ -30,6 +30,7 @@ type Querier interface {
|
||||
GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||
GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error)
|
||||
GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error)
|
||||
GetTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (TaskGroup, error)
|
||||
GetTaskGroupsForProject(ctx context.Context, projectID uuid.UUID) ([]TaskGroup, error)
|
||||
GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error)
|
||||
GetTeamByID(ctx context.Context, teamID uuid.UUID) (Team, error)
|
||||
|
@ -73,6 +73,23 @@ func (q *Queries) GetAllTaskGroups(ctx context.Context) ([]TaskGroup, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getTaskGroupByID = `-- name: GetTaskGroupByID :one
|
||||
SELECT task_group_id, project_id, created_at, name, position FROM task_group WHERE task_group_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (TaskGroup, error) {
|
||||
row := q.db.QueryRowContext(ctx, getTaskGroupByID, taskGroupID)
|
||||
var i TaskGroup
|
||||
err := row.Scan(
|
||||
&i.TaskGroupID,
|
||||
&i.ProjectID,
|
||||
&i.CreatedAt,
|
||||
&i.Name,
|
||||
&i.Position,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTaskGroupsForProject = `-- name: GetTaskGroupsForProject :many
|
||||
SELECT task_group_id, project_id, created_at, name, position FROM task_group WHERE project_id = $1
|
||||
`
|
||||
|
@ -7,3 +7,6 @@ SELECT * FROM task_group WHERE project_id = $1;
|
||||
|
||||
-- name: GetAllTaskGroups :many
|
||||
SELECT * FROM task_group;
|
||||
|
||||
-- name: GetTaskGroupByID :one
|
||||
SELECT * FROM task_group WHERE task_group_id = $1;
|
||||
|
Loading…
Reference in New Issue
Block a user