Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
1a15e433ba | |||
816121fbcf | |||
e82e97a9d7 | |||
6102f1d66e | |||
701b2f3bfd | |||
bac89d8301 |
@ -49,6 +49,7 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"hash/maphash"
|
||||||
_log "log"
|
_log "log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@ -83,7 +84,8 @@ type SuperGraph struct {
|
|||||||
schema *psql.DBSchema
|
schema *psql.DBSchema
|
||||||
allowList *allow.List
|
allowList *allow.List
|
||||||
encKey [32]byte
|
encKey [32]byte
|
||||||
prepared map[string]*preparedItem
|
hashSeed maphash.Seed
|
||||||
|
queries map[uint64]*query
|
||||||
roles map[string]*Role
|
roles map[string]*Role
|
||||||
getRole *sql.Stmt
|
getRole *sql.Stmt
|
||||||
rmap map[uint64]*resolvFn
|
rmap map[uint64]*resolvFn
|
||||||
@ -111,6 +113,7 @@ func newSuperGraph(conf *Config, db *sql.DB, dbinfo *psql.DBInfo) (*SuperGraph,
|
|||||||
db: db,
|
db: db,
|
||||||
dbinfo: dbinfo,
|
dbinfo: dbinfo,
|
||||||
log: _log.New(os.Stdout, "", 0),
|
log: _log.New(os.Stdout, "", 0),
|
||||||
|
hashSeed: maphash.MakeSeed(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sg.initConfig(); err != nil {
|
if err := sg.initConfig(); err != nil {
|
||||||
|
41
core/bench.11
Normal file
41
core/bench.11
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
INF roles_query not defined: attribute based access control disabled
|
||||||
|
all expectations were already fulfilled, call to Query 'SELECT jsonb_build_object('users', "__sj_0"."json", 'products', "__sj_1"."json") as "__root" FROM (SELECT coalesce(jsonb_agg("__sj_1"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_1".*) AS "json"FROM (SELECT "products_1"."id" AS "id", "products_1"."name" AS "name", "__sj_2"."json" AS "customers", "__sj_3"."json" AS "user" FROM (SELECT "products"."id", "products"."name", "products"."user_id" FROM "products" LIMIT ('20') :: integer) AS "products_1" LEFT OUTER JOIN LATERAL (SELECT to_jsonb("__sr_3".*) AS "json"FROM (SELECT "users_3"."full_name" AS "full_name", "users_3"."phone" AS "phone", "users_3"."email" AS "email" FROM (SELECT "users"."full_name", "users"."phone", "users"."email" FROM "users" WHERE ((("users"."id") = ("products_1"."user_id"))) LIMIT ('1') :: integer) AS "users_3") AS "__sr_3") AS "__sj_3" ON ('true') LEFT OUTER JOIN LATERAL (SELECT coalesce(jsonb_agg("__sj_2"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_2".*) AS "json"FROM (SELECT "customers_2"."id" AS "id", "customers_2"."email" AS "email" FROM (SELECT "customers"."id", "customers"."email" FROM "customers" LEFT OUTER JOIN "purchases" ON (("purchases"."product_id") = ("products_1"."id")) WHERE ((("customers"."id") = ("purchases"."customer_id"))) LIMIT ('20') :: integer) AS "customers_2") AS "__sr_2") AS "__sj_2") AS "__sj_2" ON ('true')) AS "__sr_1") AS "__sj_1") AS "__sj_1", (SELECT coalesce(jsonb_agg("__sj_0"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_0".*) AS "json"FROM (SELECT "users_0"."id" AS "id", "users_0"."name" AS "name" FROM (SELECT "users"."id" FROM "users" GROUP BY "users"."id" LIMIT ('20') :: integer) AS "users_0") AS "__sr_0") AS "__sj_0") AS "__sj_0"' with args [] was not expected
|
||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/dosco/super-graph/core
|
||||||
|
BenchmarkGraphQL-16 INF roles_query not defined: attribute based access control disabled
|
||||||
|
all expectations were already fulfilled, call to Query 'SELECT jsonb_build_object('users', "__sj_0"."json", 'products', "__sj_1"."json") as "__root" FROM (SELECT coalesce(jsonb_agg("__sj_1"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_1".*) AS "json"FROM (SELECT "products_1"."id" AS "id", "products_1"."name" AS "name", "__sj_2"."json" AS "customers", "__sj_3"."json" AS "user" FROM (SELECT "products"."id", "products"."name", "products"."user_id" FROM "products" LIMIT ('20') :: integer) AS "products_1" LEFT OUTER JOIN LATERAL (SELECT to_jsonb("__sr_3".*) AS "json"FROM (SELECT "users_3"."full_name" AS "full_name", "users_3"."phone" AS "phone", "users_3"."email" AS "email" FROM (SELECT "users"."full_name", "users"."phone", "users"."email" FROM "users" WHERE ((("users"."id") = ("products_1"."user_id"))) LIMIT ('1') :: integer) AS "users_3") AS "__sr_3") AS "__sj_3" ON ('true') LEFT OUTER JOIN LATERAL (SELECT coalesce(jsonb_agg("__sj_2"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_2".*) AS "json"FROM (SELECT "customers_2"."id" AS "id", "customers_2"."email" AS "email" FROM (SELECT "customers"."id", "customers"."email" FROM "customers" LEFT OUTER JOIN "purchases" ON (("purchases"."product_id") = ("products_1"."id")) WHERE ((("customers"."id") = ("purchases"."customer_id"))) LIMIT ('20') :: integer) AS "customers_2") AS "__sr_2") AS "__sj_2") AS "__sj_2" ON ('true')) AS "__sr_1") AS "__sj_1") AS "__sj_1", (SELECT coalesce(jsonb_agg("__sj_0"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_0".*) AS "json"FROM (SELECT "users_0"."id" AS "id", "users_0"."name" AS "name" FROM (SELECT "users"."id" FROM "users" GROUP BY "users"."id" LIMIT ('20') :: integer) AS "users_0") AS "__sr_0") AS "__sj_0") AS "__sj_0"' with args [] was not expected
|
||||||
|
INF roles_query not defined: attribute based access control disabled
|
||||||
|
all expectations were already fulfilled, call to Query 'SELECT jsonb_build_object('users', "__sj_0"."json", 'products', "__sj_1"."json") as "__root" FROM (SELECT coalesce(jsonb_agg("__sj_1"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_1".*) AS "json"FROM (SELECT "products_1"."id" AS "id", "products_1"."name" AS "name", "__sj_2"."json" AS "customers", "__sj_3"."json" AS "user" FROM (SELECT "products"."id", "products"."name", "products"."user_id" FROM "products" LIMIT ('20') :: integer) AS "products_1" LEFT OUTER JOIN LATERAL (SELECT to_jsonb("__sr_3".*) AS "json"FROM (SELECT "users_3"."full_name" AS "full_name", "users_3"."phone" AS "phone", "users_3"."email" AS "email" FROM (SELECT "users"."full_name", "users"."phone", "users"."email" FROM "users" WHERE ((("users"."id") = ("products_1"."user_id"))) LIMIT ('1') :: integer) AS "users_3") AS "__sr_3") AS "__sj_3" ON ('true') LEFT OUTER JOIN LATERAL (SELECT coalesce(jsonb_agg("__sj_2"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_2".*) AS "json"FROM (SELECT "customers_2"."id" AS "id", "customers_2"."email" AS "email" FROM (SELECT "customers"."id", "customers"."email" FROM "customers" LEFT OUTER JOIN "purchases" ON (("purchases"."product_id") = ("products_1"."id")) WHERE ((("customers"."id") = ("purchases"."customer_id"))) LIMIT ('20') :: integer) AS "customers_2") AS "__sr_2") AS "__sj_2") AS "__sj_2" ON ('true')) AS "__sr_1") AS "__sj_1") AS "__sj_1", (SELECT coalesce(jsonb_agg("__sj_0"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_0".*) AS "json"FROM (SELECT "users_0"."id" AS "id", "users_0"."name" AS "name" FROM (SELECT "users"."id" FROM "users" GROUP BY "users"."id" LIMIT ('20') :: integer) AS "users_0") AS "__sr_0") AS "__sj_0") AS "__sj_0"' with args [] was not expected
|
||||||
|
INF roles_query not defined: attribute based access control disabled
|
||||||
|
all expectations were already fulfilled, call to Query 'SELECT jsonb_build_object('users', "__sj_0"."json", 'products', "__sj_1"."json") as "__root" FROM (SELECT coalesce(jsonb_agg("__sj_1"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_1".*) AS "json"FROM (SELECT "products_1"."id" AS "id", "products_1"."name" AS "name", "__sj_2"."json" AS "customers", "__sj_3"."json" AS "user" FROM (SELECT "products"."id", "products"."name", "products"."user_id" FROM "products" LIMIT ('20') :: integer) AS "products_1" LEFT OUTER JOIN LATERAL (SELECT to_jsonb("__sr_3".*) AS "json"FROM (SELECT "users_3"."full_name" AS "full_name", "users_3"."phone" AS "phone", "users_3"."email" AS "email" FROM (SELECT "users"."full_name", "users"."phone", "users"."email" FROM "users" WHERE ((("users"."id") = ("products_1"."user_id"))) LIMIT ('1') :: integer) AS "users_3") AS "__sr_3") AS "__sj_3" ON ('true') LEFT OUTER JOIN LATERAL (SELECT coalesce(jsonb_agg("__sj_2"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_2".*) AS "json"FROM (SELECT "customers_2"."id" AS "id", "customers_2"."email" AS "email" FROM (SELECT "customers"."id", "customers"."email" FROM "customers" LEFT OUTER JOIN "purchases" ON (("purchases"."product_id") = ("products_1"."id")) WHERE ((("customers"."id") = ("purchases"."customer_id"))) LIMIT ('20') :: integer) AS "customers_2") AS "__sr_2") AS "__sj_2") AS "__sj_2" ON ('true')) AS "__sr_1") AS "__sj_1") AS "__sj_1", (SELECT coalesce(jsonb_agg("__sj_0"."json"), '[]') as "json" FROM (SELECT to_jsonb("__sr_0".*) AS "json"FROM (SELECT "users_0"."id" AS "id", "users_0"."name" AS "name" FROM (SELECT "users"."id" FROM "users" GROUP BY "users"."id" LIMIT ('20') :: integer) AS "users_0") AS "__sr_0") AS "__sj_0") AS "__sj_0"' with args [] was not expected
|
||||||
|
105048 10398 ns/op 18342 B/op 55 allocs/op
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/core 1.328s
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/core/internal/allow 0.088s
|
||||||
|
? github.com/dosco/super-graph/core/internal/crypto [no test files]
|
||||||
|
? github.com/dosco/super-graph/core/internal/integration_tests [no test files]
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/core/internal/integration_tests/cockroachdb 0.121s
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/core/internal/integration_tests/postgresql 0.118s
|
||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/dosco/super-graph/core/internal/psql
|
||||||
|
BenchmarkCompile-16 79845 14428 ns/op 4584 B/op 39 allocs/op
|
||||||
|
BenchmarkCompileParallel-16 326205 3918 ns/op 4633 B/op 39 allocs/op
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/core/internal/psql 2.696s
|
||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/dosco/super-graph/core/internal/qcode
|
||||||
|
BenchmarkQCompile-16 146953 8049 ns/op 3756 B/op 28 allocs/op
|
||||||
|
BenchmarkQCompileP-16 475936 2447 ns/op 3790 B/op 28 allocs/op
|
||||||
|
BenchmarkParse-16 140811 8163 ns/op 3902 B/op 18 allocs/op
|
||||||
|
BenchmarkParseP-16 571345 2041 ns/op 3903 B/op 18 allocs/op
|
||||||
|
BenchmarkSchemaParse-16 230715 5012 ns/op 3968 B/op 57 allocs/op
|
||||||
|
BenchmarkSchemaParseP-16 802426 1565 ns/op 3968 B/op 57 allocs/op
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/core/internal/qcode 8.427s
|
||||||
|
? github.com/dosco/super-graph/core/internal/util [no test files]
|
32
core/core.go
32
core/core.go
@ -5,6 +5,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/maphash"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dosco/super-graph/core/internal/psql"
|
"github.com/dosco/super-graph/core/internal/psql"
|
||||||
@ -165,32 +166,43 @@ func (c *scontext) resolvePreparedSQL() ([]byte, *stmt, error) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
role = c.role
|
role = c.role
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.res.role = role
|
c.res.role = role
|
||||||
|
|
||||||
ps, ok := c.sg.prepared[stmtHash(c.res.name, role)]
|
h := maphash.Hash{}
|
||||||
|
h.SetSeed(c.sg.hashSeed)
|
||||||
|
|
||||||
|
q, ok := c.sg.queries[queryID(&h, c.res.name, role)]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil, errNotFound
|
return nil, nil, errNotFound
|
||||||
}
|
}
|
||||||
c.res.sql = ps.st.sql
|
|
||||||
|
if q.sd == nil {
|
||||||
|
q.Do(func() { c.sg.prepare(q, role) })
|
||||||
|
|
||||||
|
if q.err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.res.sql = q.st.sql
|
||||||
|
|
||||||
var root []byte
|
var root []byte
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
|
|
||||||
varsList, err := c.argList(ps.st.md)
|
varsList, err := c.argList(q.st.md)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if useTx {
|
if useTx {
|
||||||
row = tx.Stmt(ps.sd).QueryRow(varsList...)
|
row = tx.Stmt(q.sd).QueryRow(varsList...)
|
||||||
} else {
|
} else {
|
||||||
row = ps.sd.QueryRow(varsList...)
|
row = q.sd.QueryRow(varsList...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ps.roleArg {
|
if q.roleArg {
|
||||||
err = row.Scan(&role, &root)
|
err = row.Scan(&role, &root)
|
||||||
} else {
|
} else {
|
||||||
err = row.Scan(&root)
|
err = row.Scan(&root)
|
||||||
@ -204,15 +216,15 @@ func (c *scontext) resolvePreparedSQL() ([]byte, *stmt, error) {
|
|||||||
|
|
||||||
if useTx {
|
if useTx {
|
||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, q.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if root, err = c.sg.encryptCursor(ps.st.qc, root); err != nil {
|
if root, err = c.sg.encryptCursor(q.st.qc, root); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return root, &ps.st, nil
|
return root, &q.st, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *scontext) resolveSQL() ([]byte, *stmt, error) {
|
func (c *scontext) resolveSQL() ([]byte, *stmt, error) {
|
||||||
|
@ -74,7 +74,7 @@ func (sg *SuperGraph) initConfig() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.RolesQuery == "" {
|
if c.RolesQuery == "" {
|
||||||
sg.log.Printf("WRN roles_query not defined: attribute based access control disabled")
|
sg.log.Printf("INF roles_query not defined: attribute based access control disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, userExists := sg.roles["user"]
|
_, userExists := sg.roles["user"]
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -35,6 +36,7 @@ type List struct {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
CreateIfNotExists bool
|
CreateIfNotExists bool
|
||||||
Persist bool
|
Persist bool
|
||||||
|
Log *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(filename string, conf Config) (*List, error) {
|
func New(filename string, conf Config) (*List, error) {
|
||||||
@ -80,6 +82,12 @@ func New(filename string, conf Config) (*List, error) {
|
|||||||
} else {
|
} else {
|
||||||
al.filepath = filename
|
al.filepath = filename
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if file, err := os.OpenFile(al.filepath, os.O_RDONLY|os.O_CREATE, 0644); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -89,8 +97,10 @@ func New(filename string, conf Config) (*List, error) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for v := range al.saveChan {
|
for v := range al.saveChan {
|
||||||
if err = al.save(v); err != nil {
|
err := al.save(v)
|
||||||
break
|
|
||||||
|
if err != nil && conf.Log != nil {
|
||||||
|
conf.Log.Println("WRN allow list save:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
qcompileTest, _ = qcode.NewCompiler(qcode.Config{})
|
qcompileTest, _ = qcode.NewCompiler(qcode.Config{})
|
||||||
|
|
||||||
schema = GetTestSchema()
|
schema, _ = GetTestSchema()
|
||||||
|
|
||||||
vars = map[string]string{
|
vars = map[string]string{
|
||||||
"admin_account_id": "5",
|
"admin_account_id": "5",
|
||||||
@ -25,6 +25,37 @@ var (
|
|||||||
|
|
||||||
// FuzzerEntrypoint for Fuzzbuzz
|
// FuzzerEntrypoint for Fuzzbuzz
|
||||||
func Fuzz(data []byte) int {
|
func Fuzz(data []byte) int {
|
||||||
|
err1 := query(data)
|
||||||
|
err2 := insert(data)
|
||||||
|
err3 := update(data)
|
||||||
|
err4 := delete(data)
|
||||||
|
|
||||||
|
if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func query(data []byte) error {
|
||||||
|
gql := data
|
||||||
|
|
||||||
|
qc, err1 := qcompileTest.Compile(gql, "user")
|
||||||
|
|
||||||
|
vars := map[string]json.RawMessage{
|
||||||
|
"data": json.RawMessage(data),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err2 := pcompileTest.CompileEx(qc, vars)
|
||||||
|
|
||||||
|
if err1 != nil {
|
||||||
|
return err1
|
||||||
|
} else {
|
||||||
|
return err2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func insert(data []byte) error {
|
||||||
gql := `mutation {
|
gql := `mutation {
|
||||||
product(insert: $data) {
|
product(insert: $data) {
|
||||||
id
|
id
|
||||||
@ -47,9 +78,57 @@ func Fuzz(data []byte) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, _, err = pcompileTest.CompileEx(qc, vars)
|
_, _, err = pcompileTest.CompileEx(qc, vars)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(data []byte) error {
|
||||||
|
gql := `mutation {
|
||||||
|
product(insert: $data) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
user {
|
||||||
|
id
|
||||||
|
full_name
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
qc, err := qcompileTest.Compile([]byte(gql), "user")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0
|
panic("qcompile can't fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1
|
vars := map[string]json.RawMessage{
|
||||||
|
"data": json.RawMessage(data),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = pcompileTest.CompileEx(qc, vars)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func delete(data []byte) error {
|
||||||
|
gql := `mutation {
|
||||||
|
product(insert: $data) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
user {
|
||||||
|
id
|
||||||
|
full_name
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
qc, err := qcompileTest.Compile([]byte(gql), "user")
|
||||||
|
if err != nil {
|
||||||
|
panic("qcompile can't fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
vars := map[string]json.RawMessage{
|
||||||
|
"data": json.RawMessage(data),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = pcompileTest.CompileEx(qc, vars)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
20
core/internal/psql/fuzz_test.go
Normal file
20
core/internal/psql/fuzz_test.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package psql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ret int
|
||||||
|
|
||||||
|
func TestFuzzCrashers(t *testing.T) {
|
||||||
|
var crashers = []string{
|
||||||
|
"{\"connect\":{}}",
|
||||||
|
"q(q{q{q{q{q{q{q{q{",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range crashers {
|
||||||
|
ret = Fuzz([]byte(f))
|
||||||
|
}
|
||||||
|
}
|
@ -542,6 +542,10 @@ func (c *compilerContext) renderConnectStmt(qc *qcode.QCode, w io.Writer,
|
|||||||
|
|
||||||
rel := item.relPC
|
rel := item.relPC
|
||||||
|
|
||||||
|
if rel == nil {
|
||||||
|
return errors.New("invalid connect value")
|
||||||
|
}
|
||||||
|
|
||||||
// Render only for parent-to-child relationship of one-to-one
|
// Render only for parent-to-child relationship of one-to-one
|
||||||
// For this to work the child needs to found first so it's primary key
|
// For this to work the child needs to found first so it's primary key
|
||||||
// can be set in the related column on the parent object.
|
// can be set in the related column on the parent object.
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/dosco/super-graph/core/internal/qcode"
|
"github.com/dosco/super-graph/core/internal/qcode"
|
||||||
@ -79,6 +80,10 @@ func (co *Compiler) CompileEx(qc *qcode.QCode, vars Variables) (Metadata, []byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (co *Compiler) Compile(w io.Writer, qc *qcode.QCode, vars Variables) (Metadata, error) {
|
func (co *Compiler) Compile(w io.Writer, qc *qcode.QCode, vars Variables) (Metadata, error) {
|
||||||
|
if qc == nil {
|
||||||
|
return Metadata{}, fmt.Errorf("qcode is nil")
|
||||||
|
}
|
||||||
|
|
||||||
switch qc.Type {
|
switch qc.Type {
|
||||||
case qcode.QTQuery:
|
case qcode.QTQuery:
|
||||||
return co.compileQuery(w, qc, vars)
|
return co.compileQuery(w, qc, vars)
|
||||||
@ -1352,26 +1357,6 @@ func squoted(w io.Writer, identifier string) {
|
|||||||
io.WriteString(w, `'`)
|
io.WriteString(w, `'`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const charset = "0123456789"
|
|
||||||
|
|
||||||
func int32String(w io.Writer, val int32) {
|
func int32String(w io.Writer, val int32) {
|
||||||
if val < 10 {
|
io.WriteString(w, strconv.FormatInt(int64(val), 10))
|
||||||
w.Write([]byte{charset[val]})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
temp := int32(0)
|
|
||||||
val2 := val
|
|
||||||
for val2 > 0 {
|
|
||||||
temp *= 10
|
|
||||||
temp += val2 % 10
|
|
||||||
val2 = int32(float64(val2 / 10))
|
|
||||||
}
|
|
||||||
|
|
||||||
val3 := temp
|
|
||||||
for val3 > 0 {
|
|
||||||
d := val3 % 10
|
|
||||||
val3 /= 10
|
|
||||||
w.Write([]byte{charset[d]})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
11
core/internal/qcode/bench.10
Normal file
11
core/internal/qcode/bench.10
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/dosco/super-graph/core/internal/qcode
|
||||||
|
BenchmarkQCompile-16 120888 9236 ns/op 3755 B/op 28 allocs/op
|
||||||
|
BenchmarkQCompileP-16 502248 2620 ns/op 3795 B/op 28 allocs/op
|
||||||
|
BenchmarkParse-16 128370 9294 ns/op 3902 B/op 18 allocs/op
|
||||||
|
BenchmarkParseP-16 575752 2340 ns/op 3903 B/op 18 allocs/op
|
||||||
|
BenchmarkSchemaParse-16 212048 5779 ns/op 3968 B/op 57 allocs/op
|
||||||
|
BenchmarkSchemaParseP-16 630918 1686 ns/op 3968 B/op 57 allocs/op
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/core/internal/qcode 7.710s
|
@ -201,6 +201,7 @@ func (p *Parser) peek(types ...itemType) bool {
|
|||||||
// if p.items[n]._type == itemEOF {
|
// if p.items[n]._type == itemEOF {
|
||||||
// return false
|
// return false
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if n >= len(p.items) {
|
if n >= len(p.items) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -299,7 +300,7 @@ func (p *Parser) parseFields(fields []Field) ([]Field, error) {
|
|||||||
return nil, fmt.Errorf("too many fields (max %d)", maxFields)
|
return nil, fmt.Errorf("too many fields (max %d)", maxFields)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.peek(itemObjClose) {
|
if p.peek(itemEOF, itemObjClose) {
|
||||||
p.ignore()
|
p.ignore()
|
||||||
st.Pop()
|
st.Pop()
|
||||||
|
|
||||||
@ -385,7 +386,7 @@ func (p *Parser) parseOpParams(args []Arg) ([]Arg, error) {
|
|||||||
return nil, fmt.Errorf("too many args (max %d)", maxArgs)
|
return nil, fmt.Errorf("too many args (max %d)", maxArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.peek(itemArgsClose) {
|
if p.peek(itemEOF, itemArgsClose) {
|
||||||
p.ignore()
|
p.ignore()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -403,7 +404,7 @@ func (p *Parser) parseArgs(args []Arg) ([]Arg, error) {
|
|||||||
return nil, fmt.Errorf("too many args (max %d)", maxArgs)
|
return nil, fmt.Errorf("too many args (max %d)", maxArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.peek(itemArgsClose) {
|
if p.peek(itemEOF, itemArgsClose) {
|
||||||
p.ignore()
|
p.ignore()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -470,7 +471,7 @@ func (p *Parser) parseObj() (*Node, error) {
|
|||||||
parent.Reset()
|
parent.Reset()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if p.peek(itemObjClose) {
|
if p.peek(itemEOF, itemObjClose) {
|
||||||
p.ignore()
|
p.ignore()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
167
core/prepare.go
167
core/prepare.go
@ -2,126 +2,97 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"crypto/sha256"
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/maphash"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/dosco/super-graph/core/internal/allow"
|
"github.com/dosco/super-graph/core/internal/allow"
|
||||||
"github.com/dosco/super-graph/core/internal/qcode"
|
"github.com/dosco/super-graph/core/internal/qcode"
|
||||||
)
|
)
|
||||||
|
|
||||||
type preparedItem struct {
|
type query struct {
|
||||||
|
sync.Once
|
||||||
sd *sql.Stmt
|
sd *sql.Stmt
|
||||||
|
ai allow.Item
|
||||||
|
qt qcode.QType
|
||||||
|
err error
|
||||||
st stmt
|
st stmt
|
||||||
roleArg bool
|
roleArg bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sg *SuperGraph) initPrepared() error {
|
func (sg *SuperGraph) prepare(q *query, role string) {
|
||||||
ct := context.Background()
|
var stmts []stmt
|
||||||
|
var err error
|
||||||
|
|
||||||
|
qb := []byte(q.ai.Query)
|
||||||
|
|
||||||
|
switch q.qt {
|
||||||
|
case qcode.QTQuery:
|
||||||
|
if sg.abacEnabled {
|
||||||
|
stmts, err = sg.buildMultiStmt(qb, q.ai.Vars)
|
||||||
|
} else {
|
||||||
|
stmts, err = sg.buildRoleStmt(qb, q.ai.Vars, role)
|
||||||
|
}
|
||||||
|
|
||||||
|
case qcode.QTMutation:
|
||||||
|
stmts, err = sg.buildRoleStmt(qb, q.ai.Vars, role)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
sg.log.Printf("WRN %s %s: %v", q.qt, q.ai.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
q.st = stmts[0]
|
||||||
|
q.roleArg = len(stmts) > 1
|
||||||
|
|
||||||
|
q.sd, err = sg.db.Prepare(q.st.sql)
|
||||||
|
if err != nil {
|
||||||
|
q.err = fmt.Errorf("prepare failed: %v: %s", err, q.st.sql)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sg *SuperGraph) initPrepared() error {
|
||||||
if sg.allowList.IsPersist() {
|
if sg.allowList.IsPersist() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
sg.prepared = make(map[string]*preparedItem)
|
|
||||||
|
|
||||||
tx, err := sg.db.BeginTx(ct, nil)
|
if err := sg.prepareRoleStmt(); err != nil {
|
||||||
if err != nil {
|
return fmt.Errorf("role query: %w", err)
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer tx.Rollback() //nolint: errcheck
|
|
||||||
|
|
||||||
if err = sg.prepareRoleStmt(tx); err != nil {
|
|
||||||
return fmt.Errorf("prepareRoleStmt: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
sg.queries = make(map[uint64]*query)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
success := 0
|
|
||||||
|
|
||||||
list, err := sg.allowList.Load()
|
list, err := sg.allowList.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h := maphash.Hash{}
|
||||||
|
h.SetSeed(sg.hashSeed)
|
||||||
|
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
if len(v.Query) == 0 {
|
if len(v.Query) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
q := &query{ai: v, qt: qcode.GetQType(v.Query)}
|
||||||
|
|
||||||
err := sg.prepareStmt(v)
|
switch q.qt {
|
||||||
if err != nil {
|
|
||||||
sg.log.Printf("WRN %s: %v", v.Name, err)
|
|
||||||
} else {
|
|
||||||
success++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sg.log.Printf("INF allow list: prepared %d / %d queries", success, len(list))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sg *SuperGraph) prepareStmt(item allow.Item) error {
|
|
||||||
query := item.Query
|
|
||||||
qb := []byte(query)
|
|
||||||
vars := item.Vars
|
|
||||||
|
|
||||||
qt := qcode.GetQType(query)
|
|
||||||
ct := context.Background()
|
|
||||||
switch qt {
|
|
||||||
case qcode.QTQuery:
|
case qcode.QTQuery:
|
||||||
var stmts1 []stmt
|
sg.queries[queryID(&h, v.Name, "user")] = q
|
||||||
var err error
|
h.Reset()
|
||||||
|
|
||||||
if sg.abacEnabled {
|
|
||||||
stmts1, err = sg.buildMultiStmt(qb, vars)
|
|
||||||
} else {
|
|
||||||
stmts1, err = sg.buildRoleStmt(qb, vars, "user")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
//logger.Debug().Msgf("Prepared statement 'query %s' (user)", item.Name)
|
|
||||||
|
|
||||||
err = sg.prepare(ct, stmts1, stmtHash(item.Name, "user"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if sg.anonExists {
|
if sg.anonExists {
|
||||||
// logger.Debug().Msgf("Prepared statement 'query %s' (anon)", item.Name)
|
sg.queries[queryID(&h, v.Name, "anon")] = q
|
||||||
|
h.Reset()
|
||||||
stmts2, err := sg.buildRoleStmt(qb, vars, "anon")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sg.prepare(ct, stmts2, stmtHash(item.Name, "anon"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case qcode.QTMutation:
|
case qcode.QTMutation:
|
||||||
for _, role := range sg.conf.Roles {
|
for _, role := range sg.conf.Roles {
|
||||||
// logger.Debug().Msgf("Prepared statement 'mutation %s' (%s)", item.Name, role.Name)
|
sg.queries[queryID(&h, v.Name, role.Name)] = q
|
||||||
|
h.Reset()
|
||||||
stmts, err := sg.buildRoleStmt(qb, vars, role.Name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sg.prepare(ct, stmts, stmtHash(item.Name, role.Name))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,22 +100,8 @@ func (sg *SuperGraph) prepareStmt(item allow.Item) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sg *SuperGraph) prepare(ct context.Context, st []stmt, key string) error {
|
|
||||||
sd, err := sg.db.PrepareContext(ct, st[0].sql)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("prepare failed: %v: %s", err, st[0].sql)
|
|
||||||
}
|
|
||||||
|
|
||||||
sg.prepared[key] = &preparedItem{
|
|
||||||
sd: sd,
|
|
||||||
st: st[0],
|
|
||||||
roleArg: len(st) > 1,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func (sg *SuperGraph) prepareRoleStmt(tx *sql.Tx) error {
|
func (sg *SuperGraph) prepareRoleStmt() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if !sg.abacEnabled {
|
if !sg.abacEnabled {
|
||||||
@ -175,7 +132,7 @@ func (sg *SuperGraph) prepareRoleStmt(tx *sql.Tx) error {
|
|||||||
io.WriteString(w, `) AS "_sg_auth_roles_query" LIMIT 1) `)
|
io.WriteString(w, `) AS "_sg_auth_roles_query" LIMIT 1) `)
|
||||||
io.WriteString(w, `ELSE 'anon' END) FROM (VALUES (1)) AS "_sg_auth_filler" LIMIT 1; `)
|
io.WriteString(w, `ELSE 'anon' END) FROM (VALUES (1)) AS "_sg_auth_filler" LIMIT 1; `)
|
||||||
|
|
||||||
sg.getRole, err = tx.Prepare(w.String())
|
sg.getRole, err = sg.db.Prepare(w.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -187,15 +144,14 @@ func (sg *SuperGraph) initAllowList() error {
|
|||||||
var ac allow.Config
|
var ac allow.Config
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if len(sg.conf.AllowListFile) == 0 {
|
if sg.conf.AllowListFile == "" {
|
||||||
sg.conf.UseAllowList = false
|
sg.conf.AllowListFile = "allow.list"
|
||||||
sg.log.Printf("WRN allow list disabled no file specified")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When list is not eabled it is still created and
|
// When list is not eabled it is still created and
|
||||||
// and new queries are saved to it.
|
// and new queries are saved to it.
|
||||||
if !sg.conf.UseAllowList {
|
if !sg.conf.UseAllowList {
|
||||||
ac = allow.Config{CreateIfNotExists: true, Persist: true}
|
ac = allow.Config{CreateIfNotExists: true, Persist: true, Log: sg.log}
|
||||||
}
|
}
|
||||||
|
|
||||||
sg.allowList, err = allow.New(sg.conf.AllowListFile, ac)
|
sg.allowList, err = allow.New(sg.conf.AllowListFile, ac)
|
||||||
@ -207,9 +163,8 @@ func (sg *SuperGraph) initAllowList() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func stmtHash(name string, role string) string {
|
func queryID(h *maphash.Hash, name string, role string) uint64 {
|
||||||
h := sha256.New()
|
h.WriteString(name)
|
||||||
io.WriteString(h, strings.ToLower(name))
|
h.WriteString(role)
|
||||||
io.WriteString(h, role)
|
return h.Sum64()
|
||||||
return hex.EncodeToString(h.Sum(nil))
|
|
||||||
}
|
}
|
||||||
|
@ -1805,11 +1805,6 @@ asynckit@^0.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||||
|
|
||||||
at-least-node@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
|
|
||||||
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
|
|
||||||
|
|
||||||
atob@^2.1.2:
|
atob@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||||
@ -2323,7 +2318,7 @@ ccount@^1.0.0, ccount@^1.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17"
|
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17"
|
||||||
integrity sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==
|
integrity sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==
|
||||||
|
|
||||||
chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2:
|
chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||||
@ -2522,15 +2517,6 @@ cliui@^5.0.0:
|
|||||||
strip-ansi "^5.2.0"
|
strip-ansi "^5.2.0"
|
||||||
wrap-ansi "^5.1.0"
|
wrap-ansi "^5.1.0"
|
||||||
|
|
||||||
cliui@^6.0.0:
|
|
||||||
version "6.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
|
||||||
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
|
||||||
dependencies:
|
|
||||||
string-width "^4.2.0"
|
|
||||||
strip-ansi "^6.0.0"
|
|
||||||
wrap-ansi "^6.2.0"
|
|
||||||
|
|
||||||
coa@^2.0.2:
|
coa@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
|
resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
|
||||||
@ -3216,11 +3202,6 @@ depd@~1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||||
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
||||||
|
|
||||||
dependency-graph@^0.9.0:
|
|
||||||
version "0.9.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.9.0.tgz#11aed7e203bc8b00f48356d92db27b265c445318"
|
|
||||||
integrity sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w==
|
|
||||||
|
|
||||||
des.js@^1.0.0:
|
des.js@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
|
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
|
||||||
@ -3830,7 +3811,7 @@ fast-glob@^2.0.2:
|
|||||||
merge2 "^1.2.3"
|
merge2 "^1.2.3"
|
||||||
micromatch "^3.1.10"
|
micromatch "^3.1.10"
|
||||||
|
|
||||||
fast-glob@^3.0.3, fast-glob@^3.1.1:
|
fast-glob@^3.0.3:
|
||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d"
|
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d"
|
||||||
integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==
|
integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==
|
||||||
@ -3970,7 +3951,7 @@ find-cache-dir@^3.0.0, find-cache-dir@^3.3.1:
|
|||||||
make-dir "^3.0.2"
|
make-dir "^3.0.2"
|
||||||
pkg-dir "^4.1.0"
|
pkg-dir "^4.1.0"
|
||||||
|
|
||||||
find-up@4.1.0, find-up@^4.0.0, find-up@^4.1.0:
|
find-up@4.1.0, find-up@^4.0.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||||
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
|
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
|
||||||
@ -4084,16 +4065,6 @@ fs-extra@^8.0.0, fs-extra@^8.1.0:
|
|||||||
jsonfile "^4.0.0"
|
jsonfile "^4.0.0"
|
||||||
universalify "^0.1.0"
|
universalify "^0.1.0"
|
||||||
|
|
||||||
fs-extra@^9.0.0:
|
|
||||||
version "9.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3"
|
|
||||||
integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==
|
|
||||||
dependencies:
|
|
||||||
at-least-node "^1.0.0"
|
|
||||||
graceful-fs "^4.2.0"
|
|
||||||
jsonfile "^6.0.1"
|
|
||||||
universalify "^1.0.0"
|
|
||||||
|
|
||||||
fs-minipass@^2.0.0:
|
fs-minipass@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||||
@ -4149,11 +4120,6 @@ get-own-enumerable-property-symbols@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
|
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
|
||||||
integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
|
integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
|
||||||
|
|
||||||
get-stdin@^7.0.0:
|
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6"
|
|
||||||
integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==
|
|
||||||
|
|
||||||
get-stream@^4.0.0:
|
get-stream@^4.0.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||||
@ -4275,18 +4241,6 @@ globby@^10.0.1:
|
|||||||
merge2 "^1.2.3"
|
merge2 "^1.2.3"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
|
|
||||||
globby@^11.0.0:
|
|
||||||
version "11.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.0.tgz#56fd0e9f0d4f8fb0c456f1ab0dee96e1380bc154"
|
|
||||||
integrity sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg==
|
|
||||||
dependencies:
|
|
||||||
array-union "^2.1.0"
|
|
||||||
dir-glob "^3.0.1"
|
|
||||||
fast-glob "^3.1.1"
|
|
||||||
ignore "^5.1.4"
|
|
||||||
merge2 "^1.3.0"
|
|
||||||
slash "^3.0.0"
|
|
||||||
|
|
||||||
globby@^6.1.0:
|
globby@^6.1.0:
|
||||||
version "6.1.0"
|
version "6.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
|
resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
|
||||||
@ -4743,7 +4697,7 @@ ignore@^3.3.5:
|
|||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
|
||||||
integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
|
integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
|
||||||
|
|
||||||
ignore@^5.1.1, ignore@^5.1.4:
|
ignore@^5.1.1:
|
||||||
version "5.1.4"
|
version "5.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf"
|
||||||
integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==
|
integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==
|
||||||
@ -5382,15 +5336,6 @@ jsonfile@^4.0.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
graceful-fs "^4.1.6"
|
graceful-fs "^4.1.6"
|
||||||
|
|
||||||
jsonfile@^6.0.1:
|
|
||||||
version "6.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179"
|
|
||||||
integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==
|
|
||||||
dependencies:
|
|
||||||
universalify "^1.0.0"
|
|
||||||
optionalDependencies:
|
|
||||||
graceful-fs "^4.1.6"
|
|
||||||
|
|
||||||
jsprim@^1.2.2:
|
jsprim@^1.2.2:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||||
@ -5656,13 +5601,6 @@ lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17
|
|||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||||
|
|
||||||
log-symbols@^2.2.0:
|
|
||||||
version "2.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
|
|
||||||
integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
|
|
||||||
dependencies:
|
|
||||||
chalk "^2.0.1"
|
|
||||||
|
|
||||||
loglevel@^1.6.8:
|
loglevel@^1.6.8:
|
||||||
version "1.6.8"
|
version "1.6.8"
|
||||||
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171"
|
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171"
|
||||||
@ -6645,7 +6583,7 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
||||||
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
|
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
|
||||||
|
|
||||||
pify@^2.0.0, pify@^2.3.0:
|
pify@^2.0.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||||
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
|
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
|
||||||
@ -6731,24 +6669,6 @@ postcss-calc@^7.0.1:
|
|||||||
postcss-selector-parser "^6.0.2"
|
postcss-selector-parser "^6.0.2"
|
||||||
postcss-value-parser "^4.0.2"
|
postcss-value-parser "^4.0.2"
|
||||||
|
|
||||||
postcss-cli@^7.1.1:
|
|
||||||
version "7.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-7.1.1.tgz#260f9546be260b2149bf32e28d785a0d79c9aab8"
|
|
||||||
integrity sha512-bYQy5ydAQJKCMSpvaMg0ThPBeGYqhQXumjbFOmWnL4u65CYXQ16RfS6afGQpit0dGv/fNzxbdDtx8dkqOhhIbg==
|
|
||||||
dependencies:
|
|
||||||
chalk "^4.0.0"
|
|
||||||
chokidar "^3.3.0"
|
|
||||||
dependency-graph "^0.9.0"
|
|
||||||
fs-extra "^9.0.0"
|
|
||||||
get-stdin "^7.0.0"
|
|
||||||
globby "^11.0.0"
|
|
||||||
postcss "^7.0.0"
|
|
||||||
postcss-load-config "^2.0.0"
|
|
||||||
postcss-reporter "^6.0.0"
|
|
||||||
pretty-hrtime "^1.0.3"
|
|
||||||
read-cache "^1.0.0"
|
|
||||||
yargs "^15.0.2"
|
|
||||||
|
|
||||||
postcss-color-functional-notation@^2.0.1:
|
postcss-color-functional-notation@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0"
|
resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0"
|
||||||
@ -7288,16 +7208,6 @@ postcss-replace-overflow-wrap@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
postcss "^7.0.2"
|
postcss "^7.0.2"
|
||||||
|
|
||||||
postcss-reporter@^6.0.0:
|
|
||||||
version "6.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.1.tgz#7c055120060a97c8837b4e48215661aafb74245f"
|
|
||||||
integrity sha512-LpmQjfRWyabc+fRygxZjpRxfhRf9u/fdlKf4VHG4TSPbV2XNsuISzYW1KL+1aQzx53CAppa1bKG4APIB/DOXXw==
|
|
||||||
dependencies:
|
|
||||||
chalk "^2.4.1"
|
|
||||||
lodash "^4.17.11"
|
|
||||||
log-symbols "^2.2.0"
|
|
||||||
postcss "^7.0.7"
|
|
||||||
|
|
||||||
postcss-selector-matches@^4.0.0:
|
postcss-selector-matches@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff"
|
resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff"
|
||||||
@ -7397,7 +7307,7 @@ postcss@^6.0.9:
|
|||||||
source-map "^0.6.1"
|
source-map "^0.6.1"
|
||||||
supports-color "^5.4.0"
|
supports-color "^5.4.0"
|
||||||
|
|
||||||
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.18, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.27, postcss@^7.0.30, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7:
|
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.18, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.27, postcss@^7.0.30, postcss@^7.0.5, postcss@^7.0.6:
|
||||||
version "7.0.30"
|
version "7.0.30"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.30.tgz#cc9378beffe46a02cbc4506a0477d05fcea9a8e2"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.30.tgz#cc9378beffe46a02cbc4506a0477d05fcea9a8e2"
|
||||||
integrity sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==
|
integrity sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==
|
||||||
@ -7692,6 +7602,11 @@ react-helmet@^6.0.0-beta:
|
|||||||
react-fast-compare "^2.0.4"
|
react-fast-compare "^2.0.4"
|
||||||
react-side-effect "^2.1.0"
|
react-side-effect "^2.1.0"
|
||||||
|
|
||||||
|
react-hook-sticky@^0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-hook-sticky/-/react-hook-sticky-0.2.0.tgz#0dcc40a2afb1856e53764af9b231f1146e3de576"
|
||||||
|
integrity sha512-J92F5H6PJQlMBgZ2tv58GeVlTZtEhpZ9bYLdoV2+5fVSJScszuY+TDZY3enQEAPIgJsLteFglGGuf8/TB9L72Q==
|
||||||
|
|
||||||
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
|
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
@ -7785,13 +7700,6 @@ react@^16.8.4:
|
|||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
|
|
||||||
read-cache@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
|
|
||||||
integrity sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=
|
|
||||||
dependencies:
|
|
||||||
pify "^2.3.0"
|
|
||||||
|
|
||||||
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
|
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
|
||||||
version "2.3.7"
|
version "2.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||||
@ -8709,7 +8617,7 @@ string-width@^3.0.0, string-width@^3.1.0:
|
|||||||
is-fullwidth-code-point "^2.0.0"
|
is-fullwidth-code-point "^2.0.0"
|
||||||
strip-ansi "^5.1.0"
|
strip-ansi "^5.1.0"
|
||||||
|
|
||||||
string-width@^4.1.0, string-width@^4.2.0:
|
string-width@^4.1.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
|
||||||
integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
|
integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
|
||||||
@ -9305,11 +9213,6 @@ universalify@^0.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||||
|
|
||||||
universalify@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
|
|
||||||
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
|
|
||||||
|
|
||||||
unpipe@1.0.0, unpipe@~1.0.0:
|
unpipe@1.0.0, unpipe@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||||
@ -9723,7 +9626,7 @@ wrap-ansi@^5.1.0:
|
|||||||
string-width "^3.0.0"
|
string-width "^3.0.0"
|
||||||
strip-ansi "^5.0.0"
|
strip-ansi "^5.0.0"
|
||||||
|
|
||||||
wrap-ansi@^6.0.0, wrap-ansi@^6.2.0:
|
wrap-ansi@^6.0.0:
|
||||||
version "6.2.0"
|
version "6.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||||
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
||||||
@ -9784,14 +9687,6 @@ yargs-parser@^13.1.2:
|
|||||||
camelcase "^5.0.0"
|
camelcase "^5.0.0"
|
||||||
decamelize "^1.2.0"
|
decamelize "^1.2.0"
|
||||||
|
|
||||||
yargs-parser@^18.1.1:
|
|
||||||
version "18.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
|
|
||||||
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
|
|
||||||
dependencies:
|
|
||||||
camelcase "^5.0.0"
|
|
||||||
decamelize "^1.2.0"
|
|
||||||
|
|
||||||
yargs@^13.3.2:
|
yargs@^13.3.2:
|
||||||
version "13.3.2"
|
version "13.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
||||||
@ -9808,23 +9703,6 @@ yargs@^13.3.2:
|
|||||||
y18n "^4.0.0"
|
y18n "^4.0.0"
|
||||||
yargs-parser "^13.1.2"
|
yargs-parser "^13.1.2"
|
||||||
|
|
||||||
yargs@^15.0.2:
|
|
||||||
version "15.3.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b"
|
|
||||||
integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==
|
|
||||||
dependencies:
|
|
||||||
cliui "^6.0.0"
|
|
||||||
decamelize "^1.2.0"
|
|
||||||
find-up "^4.1.0"
|
|
||||||
get-caller-file "^2.0.1"
|
|
||||||
require-directory "^2.1.1"
|
|
||||||
require-main-filename "^2.0.0"
|
|
||||||
set-blocking "^2.0.0"
|
|
||||||
string-width "^4.2.0"
|
|
||||||
which-module "^2.0.0"
|
|
||||||
y18n "^4.0.0"
|
|
||||||
yargs-parser "^18.1.1"
|
|
||||||
|
|
||||||
zepto@^1.2.0:
|
zepto@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/zepto/-/zepto-1.2.0.tgz#e127bd9e66fd846be5eab48c1394882f7c0e4f98"
|
resolved "https://registry.yarnpkg.com/zepto/-/zepto-1.2.0.tgz#e127bd9e66fd846be5eab48c1394882f7c0e4f98"
|
||||||
|
2
go.mod
2
go.mod
@ -18,6 +18,7 @@ require (
|
|||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/dlclark/regexp2 v1.2.0 // indirect
|
github.com/dlclark/regexp2 v1.2.0 // indirect
|
||||||
github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0
|
github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0
|
||||||
|
github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.4.9
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
github.com/garyburd/redigo v1.6.0
|
github.com/garyburd/redigo v1.6.0
|
||||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||||
@ -29,6 +30,7 @@ require (
|
|||||||
github.com/openzipkin/zipkin-go v0.2.2
|
github.com/openzipkin/zipkin-go v0.2.2
|
||||||
github.com/pelletier/go-toml v1.7.0 // indirect
|
github.com/pelletier/go-toml v1.7.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
github.com/prometheus/common v0.4.0
|
||||||
github.com/rs/cors v1.7.0
|
github.com/rs/cors v1.7.0
|
||||||
github.com/spf13/afero v1.2.2 // indirect
|
github.com/spf13/afero v1.2.2 // indirect
|
||||||
github.com/spf13/cast v1.3.1 // indirect
|
github.com/spf13/cast v1.3.1 // indirect
|
||||||
|
7
go.sum
7
go.sum
@ -35,7 +35,9 @@ github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3 h1:+qz9Ga6l6lKw6fgv
|
|||||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3/go.mod h1:FlkD11RtgMTYjVuBnb7cxoHmQGqvPpCsr2atC88nl/M=
|
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3/go.mod h1:FlkD11RtgMTYjVuBnb7cxoHmQGqvPpCsr2atC88nl/M=
|
||||||
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
|
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
|
||||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/aws/aws-sdk-go v1.15.27 h1:i75BxN4Es/8rTVQbEKAP1WCiIhhz635xTNeDdZJRAXQ=
|
github.com/aws/aws-sdk-go v1.15.27 h1:i75BxN4Es/8rTVQbEKAP1WCiIhhz635xTNeDdZJRAXQ=
|
||||||
@ -85,6 +87,8 @@ github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk
|
|||||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||||
github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0 h1:EfFAcaAwGai/wlDCWwIObHBm3T2C2CCPX/SaS0fpOJ4=
|
github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0 h1:EfFAcaAwGai/wlDCWwIObHBm3T2C2CCPX/SaS0fpOJ4=
|
||||||
github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
|
github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
|
||||||
|
github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813 h1:NgO45/5mBLRVfiXerEFzH6ikcZ7DNRPS639xFg3ENzU=
|
||||||
|
github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
|
||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
@ -220,6 +224,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
|||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
@ -319,6 +324,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
|||||||
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
@ -543,6 +549,7 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
|
|||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk=
|
google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk=
|
||||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -156,7 +156,7 @@ func cmdVersion(cmd *cobra.Command, args []string) {
|
|||||||
|
|
||||||
func BuildDetails() string {
|
func BuildDetails() string {
|
||||||
if len(version) == 0 {
|
if len(version) == 0 {
|
||||||
return fmt.Sprintf(`
|
return `
|
||||||
Super Graph (unknown version)
|
Super Graph (unknown version)
|
||||||
For documentation, visit https://supergraph.dev
|
For documentation, visit https://supergraph.dev
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ To build with version information please use the Makefile
|
|||||||
|
|
||||||
Licensed under the Apache Public License 2.0
|
Licensed under the Apache Public License 2.0
|
||||||
Copyright 2020, Vikram Rangnekar
|
Copyright 2020, Vikram Rangnekar
|
||||||
`)
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
|
@ -6,9 +6,11 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
@ -105,39 +107,40 @@ func (defaultMigratorFS) Glob(pattern string) ([]string, error) {
|
|||||||
func FindMigrationsEx(path string, fs MigratorFS) ([]string, error) {
|
func FindMigrationsEx(path string, fs MigratorFS) ([]string, error) {
|
||||||
path = strings.TrimRight(path, string(filepath.Separator))
|
path = strings.TrimRight(path, string(filepath.Separator))
|
||||||
|
|
||||||
fileInfos, err := fs.ReadDir(path)
|
files, err := ioutil.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paths := make([]string, 0, len(fileInfos))
|
fm := make(map[int]string, len(files))
|
||||||
for _, fi := range fileInfos {
|
keys := make([]int, 0, len(files))
|
||||||
|
|
||||||
|
for _, fi := range files {
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
matches := migrationPattern.FindStringSubmatch(fi.Name())
|
matches := migrationPattern.FindStringSubmatch(fi.Name())
|
||||||
|
|
||||||
if len(matches) != 2 {
|
if len(matches) != 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := strconv.ParseInt(matches[1], 10, 32)
|
n, err := strconv.Atoi(matches[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The regexp already validated that the prefix is all digits so this *should* never fail
|
// The regexp already validated that the prefix is all digits so this *should* never fail
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mcount := len(paths)
|
fm[n] = filepath.Join(path, fi.Name())
|
||||||
|
keys = append(keys, n)
|
||||||
if n < int64(mcount) {
|
|
||||||
return nil, fmt.Errorf("Duplicate migration %d", n)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if int64(mcount) < n {
|
sort.Ints(keys)
|
||||||
return nil, fmt.Errorf("Missing migration %d", mcount)
|
|
||||||
}
|
|
||||||
|
|
||||||
paths = append(paths, filepath.Join(path, fi.Name()))
|
paths := make([]string, 0, len(keys))
|
||||||
|
for _, k := range keys {
|
||||||
|
paths = append(paths, fm[k])
|
||||||
}
|
}
|
||||||
|
|
||||||
return paths, nil
|
return paths, nil
|
||||||
|
File diff suppressed because one or more lines are too long
@ -11,9 +11,9 @@
|
|||||||
// opt-in, read http://bit.ly/CRA-PWA
|
// opt-in, read http://bit.ly/CRA-PWA
|
||||||
|
|
||||||
const isLocalhost = Boolean(
|
const isLocalhost = Boolean(
|
||||||
window.location.hostname === 'localhost' ||
|
window.location.hostname === "localhost" ||
|
||||||
// [::1] is the IPv6 localhost address.
|
// [::1] is the IPv6 localhost address.
|
||||||
window.location.hostname === '[::1]' ||
|
window.location.hostname === "[::1]" ||
|
||||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||||
window.location.hostname.match(
|
window.location.hostname.match(
|
||||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||||
@ -21,7 +21,7 @@ const isLocalhost = Boolean(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export function register(config) {
|
export function register(config) {
|
||||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||||
// The URL constructor is available in all browsers that support SW.
|
// The URL constructor is available in all browsers that support SW.
|
||||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||||
if (publicUrl.origin !== window.location.origin) {
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
@ -31,7 +31,7 @@ export function register(config) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener("load", () => {
|
||||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||||
|
|
||||||
if (isLocalhost) {
|
if (isLocalhost) {
|
||||||
@ -42,8 +42,8 @@ export function register(config) {
|
|||||||
// service worker/PWA documentation.
|
// service worker/PWA documentation.
|
||||||
navigator.serviceWorker.ready.then(() => {
|
navigator.serviceWorker.ready.then(() => {
|
||||||
console.log(
|
console.log(
|
||||||
'This web app is being served cache-first by a service ' +
|
"This web app is being served cache-first by a service " +
|
||||||
'worker. To learn more, visit http://bit.ly/CRA-PWA'
|
"worker. To learn more, visit http://bit.ly/CRA-PWA"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -57,21 +57,21 @@ export function register(config) {
|
|||||||
function registerValidSW(swUrl, config) {
|
function registerValidSW(swUrl, config) {
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
.register(swUrl)
|
.register(swUrl)
|
||||||
.then(registration => {
|
.then((registration) => {
|
||||||
registration.onupdatefound = () => {
|
registration.onupdatefound = () => {
|
||||||
const installingWorker = registration.installing;
|
const installingWorker = registration.installing;
|
||||||
if (installingWorker == null) {
|
if (installingWorker == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
installingWorker.onstatechange = () => {
|
installingWorker.onstatechange = () => {
|
||||||
if (installingWorker.state === 'installed') {
|
if (installingWorker.state === "installed") {
|
||||||
if (navigator.serviceWorker.controller) {
|
if (navigator.serviceWorker.controller) {
|
||||||
// At this point, the updated precached content has been fetched,
|
// At this point, the updated precached content has been fetched,
|
||||||
// but the previous service worker will still serve the older
|
// but the previous service worker will still serve the older
|
||||||
// content until all client tabs are closed.
|
// content until all client tabs are closed.
|
||||||
console.log(
|
console.log(
|
||||||
'New content is available and will be used when all ' +
|
"New content is available and will be used when all " +
|
||||||
'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
|
"tabs for this page are closed. See http://bit.ly/CRA-PWA."
|
||||||
);
|
);
|
||||||
|
|
||||||
// Execute callback
|
// Execute callback
|
||||||
@ -82,7 +82,7 @@ function registerValidSW(swUrl, config) {
|
|||||||
// At this point, everything has been precached.
|
// At this point, everything has been precached.
|
||||||
// It's the perfect time to display a
|
// It's the perfect time to display a
|
||||||
// "Content is cached for offline use." message.
|
// "Content is cached for offline use." message.
|
||||||
console.log('Content is cached for offline use.');
|
console.log("Content is cached for offline use.");
|
||||||
|
|
||||||
// Execute callback
|
// Execute callback
|
||||||
if (config && config.onSuccess) {
|
if (config && config.onSuccess) {
|
||||||
@ -93,23 +93,23 @@ function registerValidSW(swUrl, config) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
console.error('Error during service worker registration:', error);
|
console.error("Error during service worker registration:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkValidServiceWorker(swUrl, config) {
|
function checkValidServiceWorker(swUrl, config) {
|
||||||
// Check if the service worker can be found. If it can't reload the page.
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
fetch(swUrl)
|
fetch(swUrl)
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
// Ensure service worker exists, and that we really are getting a JS file.
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
const contentType = response.headers.get('content-type');
|
const contentType = response.headers.get("content-type");
|
||||||
if (
|
if (
|
||||||
response.status === 404 ||
|
response.status === 404 ||
|
||||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
(contentType != null && contentType.indexOf("javascript") === -1)
|
||||||
) {
|
) {
|
||||||
// No service worker found. Probably a different app. Reload the page.
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then((registration) => {
|
||||||
registration.unregister().then(() => {
|
registration.unregister().then(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
@ -121,14 +121,14 @@ function checkValidServiceWorker(swUrl, config) {
|
|||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
console.log(
|
console.log(
|
||||||
'No internet connection found. App is running in offline mode.'
|
"No internet connection found. App is running in offline mode."
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unregister() {
|
export function unregister() {
|
||||||
if ('serviceWorker' in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then((registration) => {
|
||||||
registration.unregister();
|
registration.unregister();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package jsn
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,7 +69,12 @@ func Clear(w *bytes.Buffer, v []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
io := int(dec.InputOffset())
|
io := int(dec.InputOffset())
|
||||||
w.Write(v[io-len(v1)-2 : io])
|
s := io - len(v1) - 2
|
||||||
|
if io <= s || s <= 0 {
|
||||||
|
return errors.New("invalid json")
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write(v[s:io])
|
||||||
w.WriteString(`:`)
|
w.WriteString(`:`)
|
||||||
isValue = true
|
isValue = true
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"github.com/dosco/super-graph/jsn"
|
"github.com/dosco/super-graph/jsn"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ret int
|
||||||
|
|
||||||
func TestFuzzCrashers(t *testing.T) {
|
func TestFuzzCrashers(t *testing.T) {
|
||||||
var crashers = []string{
|
var crashers = []string{
|
||||||
"00\"0000\"0{",
|
"00\"0000\"0{",
|
||||||
@ -56,9 +58,16 @@ func TestFuzzCrashers(t *testing.T) {
|
|||||||
"0000\"0\"{",
|
"0000\"0\"{",
|
||||||
"000\"000\"{",
|
"000\"000\"{",
|
||||||
"\"00000000\"{",
|
"\"00000000\"{",
|
||||||
|
`0000"00"00000000"000000000"00"000000000000000"00000"00000": "00"0"__twitter_id": [{ "name": "hello" }, { "name": "world"}]`,
|
||||||
|
`0000"000000000000000000000000000000000000"00000000"000000000"00"000000000000000"00000"00000": "00000000000000"00000"__twitter_id": [{ "name": "hello" }, { "name": "world"}]`,
|
||||||
|
`00"__twitter_id":[{ "name": "hello" }, { "name": "world"}]`,
|
||||||
|
"\"\xb0\xef\xbd\xe3\xbd\xef\x99\xe3\xbd\xef\xbd\xef\xbd\xef\xbd\xe5\x99\xe3\xbd" +
|
||||||
|
"\xef\x99\xe3\"",
|
||||||
|
"\"\xef\xe3\xef\xe3\xe3\xe3\xef\xe3\xe3\xef\xe3\xef\xe3\xe3\xe3\xef\xe3\xef\xe3" +
|
||||||
|
"\xe3\xef\xef\xef\xe5\xe3\xef\xe3\xc6\xef\xef\xef\xe5\xe3\xef\xe3\xc6\xef\xef\"",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range crashers {
|
for _, f := range crashers {
|
||||||
_ = jsn.Fuzz([]byte(f))
|
ret = jsn.Fuzz([]byte(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,9 +133,18 @@ func Replace(w *bytes.Buffer, b []byte, from, to []Field) error {
|
|||||||
if e != 0 {
|
if e != 0 {
|
||||||
e++
|
e++
|
||||||
|
|
||||||
|
if e <= s {
|
||||||
|
return errors.New("invalid json")
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := h.Write(b[s:e]); err != nil {
|
if _, err := h.Write(b[s:e]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (we + 1) <= ws {
|
||||||
|
return errors.New("invalid json")
|
||||||
|
}
|
||||||
|
|
||||||
n, ok := tmap[h.Sum64()]
|
n, ok := tmap[h.Sum64()]
|
||||||
h.Reset()
|
h.Reset()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user