From 38ed6dbc5f02660708a38c38c88fa61ac92132c1 Mon Sep 17 00:00:00 2001 From: Vikram Rangnekar Date: Fri, 1 May 2020 02:20:13 -0400 Subject: [PATCH] fix: bug with single quote ecape in production mode --- Makefile | 2 +- core/api.go | 2 +- core/args.go | 33 +++++++++-------- core/args_test.go | 13 +++++++ core/build.go | 24 ++++++------ .../cockroachdb/cockroachdb_test.go | 8 +++- core/internal/psql/schema.go | 2 +- core/{graph-schema.go => introspec.go} | 14 +++---- core/resolve.go | 24 ++++++------ internal/serv/cmd.go | 13 +++---- internal/serv/cmd_seed.go | 1 + internal/serv/http.go | 3 +- internal/serv/introsp.go | 37 ------------------- 13 files changed, 78 insertions(+), 98 deletions(-) create mode 100644 core/args_test.go rename core/{graph-schema.go => introspec.go} (98%) delete mode 100644 internal/serv/introsp.go diff --git a/Makefile b/Makefile index 4131dc5..5d4beba 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ changelog: $(GITCHGLOG) @git-chglog $(ARGS) $(GOLANGCILINT): - @GO111MODULE=off curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(GOPATH)/bin v1.21.0 + @GO111MODULE=off curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(GOPATH)/bin v1.25.1 lint: $(GOLANGCILINT) @golangci-lint run ./... --skip-dirs-use-default diff --git a/core/api.go b/core/api.go index 0c9a73d..68d9667 100644 --- a/core/api.go +++ b/core/api.go @@ -174,7 +174,7 @@ func (sg *SuperGraph) GraphQL(c context.Context, query string, vars json.RawMess // use the chirino/graphql library for introspection queries // disabled when allow list is enforced if !sg.conf.UseAllowList && res.name == "IntrospectionQuery" { - r := sg.ge.ExecuteOne(&graphql.EngineRequest{Query: query}) + r := sg.ge.ServeGraphQL(&graphql.Request{Query: query}) res.Data = r.Data if r.Error() != nil { diff --git a/core/args.go b/core/args.go index 5b5f532..af35fa7 100644 --- a/core/args.go +++ b/core/args.go @@ -9,6 +9,8 @@ import ( "github.com/dosco/super-graph/jsn" ) +// argMap function is used to string replace variables with values by +// the fasttemplate code func (c *scontext) argMap() func(w io.Writer, tag string) (int, error) { return func(w io.Writer, tag string) (int, error) { switch tag { @@ -56,10 +58,13 @@ func (c *scontext) argMap() func(w io.Writer, tag string) (int, error) { return w.Write(v1) } - return w.Write(escQuote(fields[0].Value)) + return w.Write(escSQuote(fields[0].Value)) } } +// argList function is used to create a list of arguments to pass +// to a prepared statement. FYI no escaping of single quotes is +// needed here func (c *scontext) argList(args [][]byte) ([]interface{}, error) { vars := make([]interface{}, len(args)) @@ -113,7 +118,7 @@ func (c *scontext) argList(args [][]byte) ([]interface{}, error) { if v, ok := fields[string(av)]; ok { switch v[0] { case '[', '{': - vars[i] = escQuote(v) + vars[i] = v default: var val interface{} if err := json.Unmarshal(v, &val); err != nil { @@ -132,27 +137,25 @@ func (c *scontext) argList(args [][]byte) ([]interface{}, error) { return vars, nil } -func escQuote(b []byte) []byte { - f := false - for i := range b { - if b[i] == '\'' { - f = true - break - } - } - if !f { - return b - } - - buf := &bytes.Buffer{} +// +func escSQuote(b []byte) []byte { + var buf *bytes.Buffer s := 0 for i := range b { if b[i] == '\'' { + if buf == nil { + buf = &bytes.Buffer{} + } buf.Write(b[s:i]) buf.WriteString(`''`) s = i + 1 } } + + if buf == nil { + return b + } + l := len(b) if s < (l - 1) { buf.Write(b[s:l]) diff --git a/core/args_test.go b/core/args_test.go new file mode 100644 index 0000000..2227feb --- /dev/null +++ b/core/args_test.go @@ -0,0 +1,13 @@ +package core + +import "testing" + +func TestEscQuote(t *testing.T) { + val := "That's the worst, don''t be calling me's again" + exp := "That''s the worst, don''''t be calling me''s again" + ret := escSQuote([]byte(val)) + + if exp != string(ret) { + t.Errorf("escSQuote failed: %s", string(ret)) + } +} diff --git a/core/build.go b/core/build.go index 1c7e839..4f77673 100644 --- a/core/build.go +++ b/core/build.go @@ -167,16 +167,16 @@ func (sg *SuperGraph) renderUserQuery(stmts []stmt) (string, error) { return w.String(), nil } -func (sg *SuperGraph) hasTablesWithConfig(qc *qcode.QCode, role *Role) bool { - for _, id := range qc.Roots { - t, err := sg.schema.GetTable(qc.Selects[id].Name) - if err != nil { - return false - } +// func (sg *SuperGraph) hasTablesWithConfig(qc *qcode.QCode, role *Role) bool { +// for _, id := range qc.Roots { +// t, err := sg.schema.GetTable(qc.Selects[id].Name) +// if err != nil { +// return false +// } - if r := role.GetTable(t.Name); r == nil { - return false - } - } - return true -} +// if r := role.GetTable(t.Name); r == nil { +// return false +// } +// } +// return true +// } diff --git a/core/internal/integration_tests/cockroachdb/cockroachdb_test.go b/core/internal/integration_tests/cockroachdb/cockroachdb_test.go index 766ad3a..5062985 100644 --- a/core/internal/integration_tests/cockroachdb/cockroachdb_test.go +++ b/core/internal/integration_tests/cockroachdb/cockroachdb_test.go @@ -40,8 +40,12 @@ func TestCockroachDB(t *testing.T) { stopDatabase := func() { fmt.Println("stopping temporary cockroach db") if atomic.CompareAndSwapInt32(&stopped, 0, 1) { - cmd.Process.Kill() - cmd.Process.Wait() + if err := cmd.Process.Kill(); err != nil { + log.Fatal(err) + } + if _, err := cmd.Process.Wait(); err != nil { + log.Fatal(err) + } os.RemoveAll(dir) } } diff --git a/core/internal/psql/schema.go b/core/internal/psql/schema.go index 5ff57cb..e95e1aa 100644 --- a/core/internal/psql/schema.go +++ b/core/internal/psql/schema.go @@ -382,7 +382,7 @@ func (s *DBSchema) updateSchemaOTMT( func (s *DBSchema) GetTableNames() []string { var names []string - for name, _ := range s.t { + for name := range s.t { names = append(names, name) } return names diff --git a/core/graph-schema.go b/core/introspec.go similarity index 98% rename from core/graph-schema.go rename to core/introspec.go index e0a0e6c..bc595c3 100644 --- a/core/graph-schema.go +++ b/core/introspec.go @@ -29,12 +29,9 @@ func (sg *SuperGraph) initGraphQLEgine() error { engineSchema := engine.Schema dbSchema := sg.schema - engineSchema.Parse(` -enum OrderDirection { - asc - desc -} -`) + if err := engineSchema.Parse(`enum OrderDirection { asc desc }`); err != nil { + return err + } gqltype := func(col psql.DBColumn) schema.Type { typeName := typeMap[strings.ToLower(col.Type)] @@ -341,7 +338,7 @@ enum OrderDirection { }) } - for typeName, _ := range scalarExpressionTypesNeeded { + for typeName := range scalarExpressionTypesNeeded { expressionType := &schema.InputObject{ Name: typeName + "Expression", Fields: schema.InputValueList{ @@ -471,8 +468,7 @@ enum OrderDirection { engineSchema.Types[expressionType.Name] = expressionType } - err := engineSchema.ResolveTypes() - if err != nil { + if err := engineSchema.ResolveTypes(); err != nil { return err } diff --git a/core/resolve.go b/core/resolve.go index 8987103..08671e2 100644 --- a/core/resolve.go +++ b/core/resolve.go @@ -120,20 +120,20 @@ func buildFn(r Remote) func(http.Header, []byte) ([]byte, error) { } defer res.Body.Close() - if r.Debug { - // reqDump, err := httputil.DumpRequestOut(req, true) - // if err != nil { - // return nil, err - // } + // if r.Debug { + // reqDump, err := httputil.DumpRequestOut(req, true) + // if err != nil { + // return nil, err + // } - // resDump, err := httputil.DumpResponse(res, true) - // if err != nil { - // return nil, err - // } + // resDump, err := httputil.DumpResponse(res, true) + // if err != nil { + // return nil, err + // } - // logger.Debug().Msgf("Remote Request Debug:\n%s\n%s", - // reqDump, resDump) - } + // logger.Debug().Msgf("Remote Request Debug:\n%s\n%s", + // reqDump, resDump) + // } if res.StatusCode != 200 { return nil, diff --git a/internal/serv/cmd.go b/internal/serv/cmd.go index d90fe2e..e66a5e2 100644 --- a/internal/serv/cmd.go +++ b/internal/serv/cmd.go @@ -26,13 +26,12 @@ var ( ) var ( - log *_log.Logger // logger - zlog *zap.Logger // fast logger - logLevel int // log level - conf *Config // parsed config - confPath string // path to the config file - db *sql.DB // database connection pool - secretKey [32]byte // encryption key + log *_log.Logger // logger + zlog *zap.Logger // fast logger + logLevel int // log level + conf *Config // parsed config + confPath string // path to the config file + db *sql.DB // database connection pool ) func Cmd() { diff --git a/internal/serv/cmd_seed.go b/internal/serv/cmd_seed.go index c5a8eff..0488519 100644 --- a/internal/serv/cmd_seed.go +++ b/internal/serv/cmd_seed.go @@ -415,6 +415,7 @@ func setFakeFuncs(f *goja.Object) { //f.Set("programming_language", gofakeit.ProgrammingLanguage) } +//nolint: errcheck func setUtilFuncs(f *goja.Object) { // Slugs f.Set("make_slug", slug.Make) diff --git a/internal/serv/http.go b/internal/serv/http.go index 812285b..62651ea 100644 --- a/internal/serv/http.go +++ b/internal/serv/http.go @@ -77,7 +77,7 @@ func apiV1(w http.ResponseWriter, r *http.Request) { doLog := true res, err := sg.GraphQL(ct, req.Query, req.Vars) - if !conf.Production && res.QueryName() == "IntrospectionQuery" { + if !conf.Production && res.QueryName() == introspectionQuery { doLog = false } @@ -89,6 +89,7 @@ func apiV1(w http.ResponseWriter, r *http.Request) { if len(conf.CacheControl) != 0 && res.Operation() == core.OpQuery { w.Header().Set("Cache-Control", conf.CacheControl) } + //nolint: errcheck json.NewEncoder(w).Encode(res) } else { diff --git a/internal/serv/introsp.go b/internal/serv/introsp.go deleted file mode 100644 index 04f62e4..0000000 --- a/internal/serv/introsp.go +++ /dev/null @@ -1,37 +0,0 @@ -package serv - -import "net/http" - -//nolint: errcheck -func introspect(w http.ResponseWriter) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{ - "data": { - "__schema": { - "queryType": { - "name": "Query" - }, - "mutationType": null, - "subscriptionType": null - } - }, - "extensions":{ - "tracing":{ - "version":1, - "startTime":"2019-06-04T19:53:31.093Z", - "endTime":"2019-06-04T19:53:31.108Z", - "duration":15219720, - "execution": { - "resolvers": [{ - "path": ["__schema"], - "parentType": "Query", - "fieldName": "__schema", - "returnType": "__Schema!", - "startOffset": 50950, - "duration": 17187 - }] - } - } - } - }`)) -}