fix: bug with single quote ecape in production mode

This commit is contained in:
Vikram Rangnekar 2020-05-01 02:20:13 -04:00
parent ec2f8d0c58
commit 38ed6dbc5f
13 changed files with 78 additions and 98 deletions

View File

@ -45,7 +45,7 @@ changelog: $(GITCHGLOG)
@git-chglog $(ARGS) @git-chglog $(ARGS)
$(GOLANGCILINT): $(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) lint: $(GOLANGCILINT)
@golangci-lint run ./... --skip-dirs-use-default @golangci-lint run ./... --skip-dirs-use-default

View File

@ -174,7 +174,7 @@ func (sg *SuperGraph) GraphQL(c context.Context, query string, vars json.RawMess
// use the chirino/graphql library for introspection queries // use the chirino/graphql library for introspection queries
// disabled when allow list is enforced // disabled when allow list is enforced
if !sg.conf.UseAllowList && res.name == "IntrospectionQuery" { 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 res.Data = r.Data
if r.Error() != nil { if r.Error() != nil {

View File

@ -9,6 +9,8 @@ import (
"github.com/dosco/super-graph/jsn" "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) { func (c *scontext) argMap() func(w io.Writer, tag string) (int, error) {
return func(w io.Writer, tag string) (int, error) { return func(w io.Writer, tag string) (int, error) {
switch tag { 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(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) { func (c *scontext) argList(args [][]byte) ([]interface{}, error) {
vars := make([]interface{}, len(args)) vars := make([]interface{}, len(args))
@ -113,7 +118,7 @@ func (c *scontext) argList(args [][]byte) ([]interface{}, error) {
if v, ok := fields[string(av)]; ok { if v, ok := fields[string(av)]; ok {
switch v[0] { switch v[0] {
case '[', '{': case '[', '{':
vars[i] = escQuote(v) vars[i] = v
default: default:
var val interface{} var val interface{}
if err := json.Unmarshal(v, &val); err != nil { if err := json.Unmarshal(v, &val); err != nil {
@ -132,27 +137,25 @@ func (c *scontext) argList(args [][]byte) ([]interface{}, error) {
return vars, nil return vars, nil
} }
func escQuote(b []byte) []byte { //
f := false func escSQuote(b []byte) []byte {
for i := range b { var buf *bytes.Buffer
if b[i] == '\'' {
f = true
break
}
}
if !f {
return b
}
buf := &bytes.Buffer{}
s := 0 s := 0
for i := range b { for i := range b {
if b[i] == '\'' { if b[i] == '\'' {
if buf == nil {
buf = &bytes.Buffer{}
}
buf.Write(b[s:i]) buf.Write(b[s:i])
buf.WriteString(`''`) buf.WriteString(`''`)
s = i + 1 s = i + 1
} }
} }
if buf == nil {
return b
}
l := len(b) l := len(b)
if s < (l - 1) { if s < (l - 1) {
buf.Write(b[s:l]) buf.Write(b[s:l])

13
core/args_test.go Normal file
View File

@ -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))
}
}

View File

@ -167,16 +167,16 @@ func (sg *SuperGraph) renderUserQuery(stmts []stmt) (string, error) {
return w.String(), nil return w.String(), nil
} }
func (sg *SuperGraph) hasTablesWithConfig(qc *qcode.QCode, role *Role) bool { // func (sg *SuperGraph) hasTablesWithConfig(qc *qcode.QCode, role *Role) bool {
for _, id := range qc.Roots { // for _, id := range qc.Roots {
t, err := sg.schema.GetTable(qc.Selects[id].Name) // t, err := sg.schema.GetTable(qc.Selects[id].Name)
if err != nil { // if err != nil {
return false // return false
} // }
if r := role.GetTable(t.Name); r == nil { // if r := role.GetTable(t.Name); r == nil {
return false // return false
} // }
} // }
return true // return true
} // }

View File

@ -40,8 +40,12 @@ func TestCockroachDB(t *testing.T) {
stopDatabase := func() { stopDatabase := func() {
fmt.Println("stopping temporary cockroach db") fmt.Println("stopping temporary cockroach db")
if atomic.CompareAndSwapInt32(&stopped, 0, 1) { if atomic.CompareAndSwapInt32(&stopped, 0, 1) {
cmd.Process.Kill() if err := cmd.Process.Kill(); err != nil {
cmd.Process.Wait() log.Fatal(err)
}
if _, err := cmd.Process.Wait(); err != nil {
log.Fatal(err)
}
os.RemoveAll(dir) os.RemoveAll(dir)
} }
} }

View File

@ -382,7 +382,7 @@ func (s *DBSchema) updateSchemaOTMT(
func (s *DBSchema) GetTableNames() []string { func (s *DBSchema) GetTableNames() []string {
var names []string var names []string
for name, _ := range s.t { for name := range s.t {
names = append(names, name) names = append(names, name)
} }
return names return names

View File

@ -29,12 +29,9 @@ func (sg *SuperGraph) initGraphQLEgine() error {
engineSchema := engine.Schema engineSchema := engine.Schema
dbSchema := sg.schema dbSchema := sg.schema
engineSchema.Parse(` if err := engineSchema.Parse(`enum OrderDirection { asc desc }`); err != nil {
enum OrderDirection { return err
asc
desc
} }
`)
gqltype := func(col psql.DBColumn) schema.Type { gqltype := func(col psql.DBColumn) schema.Type {
typeName := typeMap[strings.ToLower(col.Type)] typeName := typeMap[strings.ToLower(col.Type)]
@ -341,7 +338,7 @@ enum OrderDirection {
}) })
} }
for typeName, _ := range scalarExpressionTypesNeeded { for typeName := range scalarExpressionTypesNeeded {
expressionType := &schema.InputObject{ expressionType := &schema.InputObject{
Name: typeName + "Expression", Name: typeName + "Expression",
Fields: schema.InputValueList{ Fields: schema.InputValueList{
@ -471,8 +468,7 @@ enum OrderDirection {
engineSchema.Types[expressionType.Name] = expressionType engineSchema.Types[expressionType.Name] = expressionType
} }
err := engineSchema.ResolveTypes() if err := engineSchema.ResolveTypes(); err != nil {
if err != nil {
return err return err
} }

View File

@ -120,7 +120,7 @@ func buildFn(r Remote) func(http.Header, []byte) ([]byte, error) {
} }
defer res.Body.Close() defer res.Body.Close()
if r.Debug { // if r.Debug {
// reqDump, err := httputil.DumpRequestOut(req, true) // reqDump, err := httputil.DumpRequestOut(req, true)
// if err != nil { // if err != nil {
// return nil, err // return nil, err
@ -133,7 +133,7 @@ func buildFn(r Remote) func(http.Header, []byte) ([]byte, error) {
// logger.Debug().Msgf("Remote Request Debug:\n%s\n%s", // logger.Debug().Msgf("Remote Request Debug:\n%s\n%s",
// reqDump, resDump) // reqDump, resDump)
} // }
if res.StatusCode != 200 { if res.StatusCode != 200 {
return nil, return nil,

View File

@ -32,7 +32,6 @@ var (
conf *Config // parsed config conf *Config // parsed config
confPath string // path to the config file confPath string // path to the config file
db *sql.DB // database connection pool db *sql.DB // database connection pool
secretKey [32]byte // encryption key
) )
func Cmd() { func Cmd() {

View File

@ -415,6 +415,7 @@ func setFakeFuncs(f *goja.Object) {
//f.Set("programming_language", gofakeit.ProgrammingLanguage) //f.Set("programming_language", gofakeit.ProgrammingLanguage)
} }
//nolint: errcheck
func setUtilFuncs(f *goja.Object) { func setUtilFuncs(f *goja.Object) {
// Slugs // Slugs
f.Set("make_slug", slug.Make) f.Set("make_slug", slug.Make)

View File

@ -77,7 +77,7 @@ func apiV1(w http.ResponseWriter, r *http.Request) {
doLog := true doLog := true
res, err := sg.GraphQL(ct, req.Query, req.Vars) res, err := sg.GraphQL(ct, req.Query, req.Vars)
if !conf.Production && res.QueryName() == "IntrospectionQuery" { if !conf.Production && res.QueryName() == introspectionQuery {
doLog = false doLog = false
} }
@ -89,6 +89,7 @@ func apiV1(w http.ResponseWriter, r *http.Request) {
if len(conf.CacheControl) != 0 && res.Operation() == core.OpQuery { if len(conf.CacheControl) != 0 && res.Operation() == core.OpQuery {
w.Header().Set("Cache-Control", conf.CacheControl) w.Header().Set("Cache-Control", conf.CacheControl)
} }
//nolint: errcheck
json.NewEncoder(w).Encode(res) json.NewEncoder(w).Encode(res)
} else { } else {

View File

@ -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
}]
}
}
}
}`))
}