Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
1344246287 | |||
7b25873438 | |||
d572b4f753 | |||
cd69b5a78f | |||
01ad9b71ba | |||
b64daaf034 | |||
c7837bf758 | |||
448e6bb72a | |||
f7d3760af7 | |||
2acb05741e | |||
8104ee9df2 | |||
ab8566df03 | |||
94fa51ffb2 |
@ -7,7 +7,7 @@
|
|||||||

|

|
||||||
[](https://discord.gg/6pSWCTZ)
|
[](https://discord.gg/6pSWCTZ)
|
||||||
|
|
||||||
Super Graph gives you a high performance GraphQL API without you having to write any code. GraphQL is automatically compiled efficient an SQL query. Use it either as a library or a standalone service.
|
Super Graph gives you a high performance GraphQL API without you having to write any code. GraphQL is automagically compiled into an efficient SQL query. Use it either as a library or a standalone service.
|
||||||
|
|
||||||
## Using it as a service
|
## Using it as a service
|
||||||
|
|
||||||
@ -91,6 +91,7 @@ This compiler is what sits at the heart of Super Graph, with layers of useful fu
|
|||||||
- Database migrations tool
|
- Database migrations tool
|
||||||
- Database seeding tool
|
- Database seeding tool
|
||||||
- Works with Postgres and YugabyteDB
|
- Works with Postgres and YugabyteDB
|
||||||
|
- OpenCensus Support: Zipkin, Prometheus, X-Ray, Stackdriver
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ log_level: "debug"
|
|||||||
# enable or disable http compression (uses gzip)
|
# enable or disable http compression (uses gzip)
|
||||||
http_compress: true
|
http_compress: true
|
||||||
|
|
||||||
# When production mode is 'true' only queries
|
# When production mode is 'true' only queries
|
||||||
# from the allow list are permitted.
|
# from the allow list are permitted.
|
||||||
# When it's 'false' all queries are saved to the
|
# When it's 'false' all queries are saved to the
|
||||||
# the allow list in ./config/allow.list
|
# the allow list in ./config/allow.list
|
||||||
@ -32,13 +32,13 @@ reload_on_config_change: true
|
|||||||
# Path pointing to where the migrations can be found
|
# Path pointing to where the migrations can be found
|
||||||
migrations_path: ./migrations
|
migrations_path: ./migrations
|
||||||
|
|
||||||
# Secret key for general encryption operations like
|
# Secret key for general encryption operations like
|
||||||
# encrypting the cursor data
|
# encrypting the cursor data
|
||||||
secret_key: supercalifajalistics
|
secret_key: supercalifajalistics
|
||||||
|
|
||||||
# CORS: A list of origins a cross-domain request can be executed from.
|
# CORS: A list of origins a cross-domain request can be executed from.
|
||||||
# If the special * value is present in the list, all origins will be allowed.
|
# If the special * value is present in the list, all origins will be allowed.
|
||||||
# An origin may contain a wildcard (*) to replace 0 or more
|
# An origin may contain a wildcard (*) to replace 0 or more
|
||||||
# characters (i.e.: http://*.domain.com).
|
# characters (i.e.: http://*.domain.com).
|
||||||
cors_allowed_origins: ["*"]
|
cors_allowed_origins: ["*"]
|
||||||
|
|
||||||
@ -48,8 +48,8 @@ cors_debug: true
|
|||||||
# Default API path prefix is /api you can change it if you like
|
# Default API path prefix is /api you can change it if you like
|
||||||
# api_path: "/data"
|
# api_path: "/data"
|
||||||
|
|
||||||
# Cache-Control header can help cache queries if your CDN supports cache-control
|
# Cache-Control header can help cache queries if your CDN supports cache-control
|
||||||
# on POST requests (does not work with not mutations)
|
# on POST requests (does not work with not mutations)
|
||||||
# cache_control: "public, max-age=300, s-maxage=600"
|
# cache_control: "public, max-age=300, s-maxage=600"
|
||||||
|
|
||||||
# Postgres related environment Variables
|
# Postgres related environment Variables
|
||||||
@ -68,13 +68,25 @@ cors_debug: true
|
|||||||
# person: people
|
# person: people
|
||||||
# sheep: sheep
|
# sheep: sheep
|
||||||
|
|
||||||
|
# open opencensus tracing and metrics
|
||||||
|
# telemetry:
|
||||||
|
# debug: true
|
||||||
|
# metrics:
|
||||||
|
# exporter: "prometheus"
|
||||||
|
# tracing:
|
||||||
|
# exporter: "zipkin"
|
||||||
|
# endpoint: "http://zipkin:9411/api/v2/spans"
|
||||||
|
# sample: 0.2
|
||||||
|
# include_query: false
|
||||||
|
# include_params: false
|
||||||
|
|
||||||
auth:
|
auth:
|
||||||
# Can be 'rails' or 'jwt'
|
# Can be 'rails' or 'jwt'
|
||||||
type: rails
|
type: rails
|
||||||
cookie: _app_session
|
cookie: _app_session
|
||||||
|
|
||||||
# Comment this out if you want to disable setting
|
# Comment this out if you want to disable setting
|
||||||
# the user_id via a header for testing.
|
# the user_id via a header for testing.
|
||||||
# Disable in production
|
# Disable in production
|
||||||
creds_in_header: true
|
creds_in_header: true
|
||||||
|
|
||||||
@ -91,7 +103,6 @@ auth:
|
|||||||
# password: ""
|
# password: ""
|
||||||
# max_idle: 80
|
# max_idle: 80
|
||||||
# max_active: 12000
|
# max_active: 12000
|
||||||
|
|
||||||
# In most cases you don't need these
|
# In most cases you don't need these
|
||||||
# salt: "encrypted cookie"
|
# salt: "encrypted cookie"
|
||||||
# sign_salt: "signed encrypted cookie"
|
# sign_salt: "signed encrypted cookie"
|
||||||
@ -144,7 +155,7 @@ tables:
|
|||||||
url: http://rails_app:3000/stripe/$id
|
url: http://rails_app:3000/stripe/$id
|
||||||
path: data
|
path: data
|
||||||
# debug: true
|
# debug: true
|
||||||
pass_headers:
|
pass_headers:
|
||||||
- cookie
|
- cookie
|
||||||
set_headers:
|
set_headers:
|
||||||
- name: Host
|
- name: Host
|
||||||
@ -165,7 +176,6 @@ tables:
|
|||||||
- name: email
|
- name: email
|
||||||
related_to: products.name
|
related_to: products.name
|
||||||
|
|
||||||
|
|
||||||
roles_query: "SELECT * FROM users WHERE id = $user_id"
|
roles_query: "SELECT * FROM users WHERE id = $user_id"
|
||||||
|
|
||||||
roles:
|
roles:
|
||||||
@ -174,12 +184,12 @@ roles:
|
|||||||
- name: products
|
- name: products
|
||||||
query:
|
query:
|
||||||
limit: 10
|
limit: 10
|
||||||
columns: ["id", "name", "description" ]
|
columns: ["id", "name", "description"]
|
||||||
aggregation: false
|
aggregation: false
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
block: false
|
block: false
|
||||||
|
|
||||||
update:
|
update:
|
||||||
block: false
|
block: false
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ log_level: "info"
|
|||||||
# enable or disable http compression (uses gzip)
|
# enable or disable http compression (uses gzip)
|
||||||
http_compress: true
|
http_compress: true
|
||||||
|
|
||||||
# When production mode is 'true' only queries
|
# When production mode is 'true' only queries
|
||||||
# from the allow list are permitted.
|
# from the allow list are permitted.
|
||||||
# When it's 'false' all queries are saved to the
|
# When it's 'false' all queries are saved to the
|
||||||
# the allow list in ./config/allow.list
|
# the allow list in ./config/allow.list
|
||||||
@ -32,7 +32,7 @@ enable_tracing: true
|
|||||||
# Path pointing to where the migrations can be found
|
# Path pointing to where the migrations can be found
|
||||||
# migrations_path: ./migrations
|
# migrations_path: ./migrations
|
||||||
|
|
||||||
# Secret key for general encryption operations like
|
# Secret key for general encryption operations like
|
||||||
# encrypting the cursor data
|
# encrypting the cursor data
|
||||||
# secret_key: supercalifajalistics
|
# secret_key: supercalifajalistics
|
||||||
|
|
||||||
@ -57,11 +57,20 @@ database:
|
|||||||
password: postgres
|
password: postgres
|
||||||
#pool_size: 10
|
#pool_size: 10
|
||||||
#max_retries: 0
|
#max_retries: 0
|
||||||
#log_level: "debug"
|
#log_level: "debug"
|
||||||
|
|
||||||
# Set session variable "user.id" to the user id
|
# Set session variable "user.id" to the user id
|
||||||
# Enable this if you need the user id in triggers, etc
|
# Enable this if you need the user id in triggers, etc
|
||||||
set_user_id: false
|
set_user_id: false
|
||||||
|
|
||||||
# database ping timeout is used for db health checking
|
# database ping timeout is used for db health checking
|
||||||
ping_timeout: 5m
|
ping_timeout: 5m
|
||||||
|
# open opencensus tracing and metrics
|
||||||
|
# telemetry:
|
||||||
|
# debug: false
|
||||||
|
# metrics:
|
||||||
|
# exporter: "prometheus"
|
||||||
|
# tracing:
|
||||||
|
# exporter: "zipkin"
|
||||||
|
# endpoint: "http://zipkin:9411/api/v2/spans"
|
||||||
|
# sample: 0.6
|
||||||
|
12
core/api.go
12
core/api.go
@ -210,3 +210,15 @@ func (sg *SuperGraph) GraphQL(c context.Context, query string, vars json.RawMess
|
|||||||
func (sg *SuperGraph) GraphQLSchema() (string, error) {
|
func (sg *SuperGraph) GraphQLSchema() (string, error) {
|
||||||
return sg.ge.Schema.String(), nil
|
return sg.ge.Schema.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Operation function return the operation type from the query. It uses a very fast algorithm to
|
||||||
|
// extract the operation without having to parse the query.
|
||||||
|
func Operation(query string) OpType {
|
||||||
|
return OpType(qcode.GetQType(query))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name function return the operation name from the query. It uses a very fast algorithm to
|
||||||
|
// extract the operation name without having to parse the query.
|
||||||
|
func Name(query string) string {
|
||||||
|
return allow.QueryName(query)
|
||||||
|
}
|
||||||
|
@ -19,7 +19,7 @@ func BenchmarkGraphQL(b *testing.B) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// mock.ExpectQuery(`^SELECT jsonb_build_object`).WithArgs()
|
// mock.ExpectQuery(`^SELECT jsonb_build_object`).WithArgs()
|
||||||
c := &Config{DefaultBlock: true}
|
c := &Config{}
|
||||||
sg, err := newSuperGraph(c, db, psql.GetTestDBInfo())
|
sg, err := newSuperGraph(c, db, psql.GetTestDBInfo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
|
@ -30,11 +30,12 @@ type Config struct {
|
|||||||
// or other database functions
|
// or other database functions
|
||||||
SetUserID bool `mapstructure:"set_user_id"`
|
SetUserID bool `mapstructure:"set_user_id"`
|
||||||
|
|
||||||
// DefaultBlock ensures only tables configured under the `anon` role
|
// DefaultAllow reverses the blocked by default behaviour for queries in
|
||||||
// config can be queries if the `anon` role. For example if the table
|
// anonymous mode. (anon role)
|
||||||
// `users` is not listed under the anon role then it will be filtered
|
// For example if the table `users` is not listed under the anon role then
|
||||||
// out of any unauthenticated queries that mention it.
|
// access to it would by default for unauthenticated queries this reverses
|
||||||
DefaultBlock bool `mapstructure:"default_block"`
|
// this behavior (!!! Use with caution !!!!)
|
||||||
|
DefaultAllow bool `mapstructure:"default_allow"`
|
||||||
|
|
||||||
// Vars is a map of hardcoded variables that can be leveraged in your
|
// Vars is a map of hardcoded variables that can be leveraged in your
|
||||||
// queries (eg variable admin_id will be $admin_id in the query)
|
// queries (eg variable admin_id will be $admin_id in the query)
|
||||||
@ -61,6 +62,9 @@ type Config struct {
|
|||||||
// Inflections is to add additionally singular to plural mappings
|
// Inflections is to add additionally singular to plural mappings
|
||||||
// to the engine (eg. sheep: sheep)
|
// to the engine (eg. sheep: sheep)
|
||||||
Inflections map[string]string `mapstructure:"inflections"`
|
Inflections map[string]string `mapstructure:"inflections"`
|
||||||
|
|
||||||
|
// Database schema name. Defaults to 'public'
|
||||||
|
DBSchema string `mapstructure:"db_schema"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Table struct defines a database table
|
// Table struct defines a database table
|
||||||
@ -103,7 +107,8 @@ type Role struct {
|
|||||||
|
|
||||||
// RoleTable struct contains role specific access control values for a database table
|
// RoleTable struct contains role specific access control values for a database table
|
||||||
type RoleTable struct {
|
type RoleTable struct {
|
||||||
Name string
|
Name string
|
||||||
|
ReadOnly *bool `mapstructure:"read_only"`
|
||||||
|
|
||||||
Query Query
|
Query Query
|
||||||
Insert Insert
|
Insert Insert
|
||||||
@ -117,7 +122,7 @@ type Query struct {
|
|||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
DisableFunctions bool `mapstructure:"disable_functions"`
|
DisableFunctions bool `mapstructure:"disable_functions"`
|
||||||
Block bool
|
Block *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert struct contains access control values for insert operations
|
// Insert struct contains access control values for insert operations
|
||||||
@ -125,7 +130,7 @@ type Insert struct {
|
|||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Presets map[string]string
|
Presets map[string]string
|
||||||
Block bool
|
Block *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert struct contains access control values for update operations
|
// Insert struct contains access control values for update operations
|
||||||
@ -133,14 +138,14 @@ type Update struct {
|
|||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Presets map[string]string
|
Presets map[string]string
|
||||||
Block bool
|
Block *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete struct contains access control values for delete operations
|
// Delete struct contains access control values for delete operations
|
||||||
type Delete struct {
|
type Delete struct {
|
||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Block bool
|
Block *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadInConfig function reads in the config file for the environment specified in the GO_ENV
|
// ReadInConfig function reads in the config file for the environment specified in the GO_ENV
|
||||||
|
22
core/core.go
22
core/core.go
@ -14,8 +14,10 @@ import (
|
|||||||
"github.com/valyala/fasttemplate"
|
"github.com/valyala/fasttemplate"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type OpType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
OpQuery int = iota
|
OpQuery OpType = iota
|
||||||
OpMutation
|
OpMutation
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -56,16 +58,27 @@ type scontext struct {
|
|||||||
|
|
||||||
func (sg *SuperGraph) initCompilers() error {
|
func (sg *SuperGraph) initCompilers() error {
|
||||||
var err error
|
var err error
|
||||||
|
var schema string
|
||||||
|
|
||||||
|
if sg.conf.DBSchema == "" {
|
||||||
|
schema = "public"
|
||||||
|
} else {
|
||||||
|
schema = sg.conf.DBSchema
|
||||||
|
}
|
||||||
|
|
||||||
// If sg.di is not null then it's probably set
|
// If sg.di is not null then it's probably set
|
||||||
// for tests
|
// for tests
|
||||||
if sg.dbinfo == nil {
|
if sg.dbinfo == nil {
|
||||||
sg.dbinfo, err = psql.GetDBInfo(sg.db)
|
sg.dbinfo, err = psql.GetDBInfo(sg.db, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(sg.dbinfo.Tables) == 0 {
|
||||||
|
return fmt.Errorf("no tables found in database (schema: %s)", schema)
|
||||||
|
}
|
||||||
|
|
||||||
if err = addTables(sg.conf, sg.dbinfo); err != nil {
|
if err = addTables(sg.conf, sg.dbinfo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -80,8 +93,7 @@ func (sg *SuperGraph) initCompilers() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sg.qc, err = qcode.NewCompiler(qcode.Config{
|
sg.qc, err = qcode.NewCompiler(qcode.Config{
|
||||||
DefaultBlock: sg.conf.DefaultBlock,
|
Blocklist: sg.conf.Blocklist,
|
||||||
Blocklist: sg.conf.Blocklist,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -334,7 +346,7 @@ func (c *scontext) executeRoleQuery(tx *sql.Tx) (string, error) {
|
|||||||
return role, nil
|
return role, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Result) Operation() int {
|
func (r *Result) Operation() OpType {
|
||||||
switch r.op {
|
switch r.op {
|
||||||
case qcode.QTQuery:
|
case qcode.QTQuery:
|
||||||
return OpQuery
|
return OpQuery
|
||||||
|
74
core/init.go
74
core/init.go
@ -70,8 +70,8 @@ func (sg *SuperGraph) initConfig() error {
|
|||||||
sg.roles["user"] = &ur
|
sg.roles["user"] = &ur
|
||||||
}
|
}
|
||||||
|
|
||||||
// If anon role is not defined and DefaultBlock is not then then create it
|
// If anon role is not defined then create it
|
||||||
if _, ok := sg.roles["anon"]; !ok && !c.DefaultBlock {
|
if _, ok := sg.roles["anon"]; !ok {
|
||||||
ur := Role{
|
ur := Role{
|
||||||
Name: "anon",
|
Name: "anon",
|
||||||
tm: make(map[string]*RoleTable),
|
tm: make(map[string]*RoleTable),
|
||||||
@ -83,14 +83,14 @@ func (sg *SuperGraph) initConfig() error {
|
|||||||
// Roles: validate and sanitize
|
// Roles: validate and sanitize
|
||||||
c.RolesQuery = sanitizeVars(c.RolesQuery)
|
c.RolesQuery = sanitizeVars(c.RolesQuery)
|
||||||
|
|
||||||
if len(c.RolesQuery) == 0 {
|
if c.RolesQuery == "" {
|
||||||
sg.log.Printf("WRN roles_query not defined: attribute based access control disabled")
|
sg.log.Printf("WRN roles_query not defined: attribute based access control disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, userExists := sg.roles["user"]
|
_, userExists := sg.roles["user"]
|
||||||
_, sg.anonExists = sg.roles["anon"]
|
_, sg.anonExists = sg.roles["anon"]
|
||||||
|
|
||||||
sg.abacEnabled = userExists && len(c.RolesQuery) != 0
|
sg.abacEnabled = userExists && c.RolesQuery != ""
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ func getDBTableAliases(c *Config) map[string][]string {
|
|||||||
|
|
||||||
func addTables(c *Config, di *psql.DBInfo) error {
|
func addTables(c *Config, di *psql.DBInfo) error {
|
||||||
for _, t := range c.Tables {
|
for _, t := range c.Tables {
|
||||||
if len(t.Table) == 0 || len(t.Columns) == 0 {
|
if t.Table == "" || len(t.Columns) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := addTable(di, t.Columns, t); err != nil {
|
if err := addTable(di, t.Columns, t); err != nil {
|
||||||
@ -163,7 +163,7 @@ func addTable(di *psql.DBInfo, cols []Column, t Table) error {
|
|||||||
func addForeignKeys(c *Config, di *psql.DBInfo) error {
|
func addForeignKeys(c *Config, di *psql.DBInfo) error {
|
||||||
for _, t := range c.Tables {
|
for _, t := range c.Tables {
|
||||||
for _, c := range t.Columns {
|
for _, c := range t.Columns {
|
||||||
if len(c.ForeignKey) == 0 {
|
if c.ForeignKey == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := addForeignKey(di, c, t); err != nil {
|
if err := addForeignKey(di, c, t); err != nil {
|
||||||
@ -206,7 +206,7 @@ func addForeignKey(di *psql.DBInfo, c Column, t Table) error {
|
|||||||
func addRoles(c *Config, qc *qcode.Compiler) error {
|
func addRoles(c *Config, qc *qcode.Compiler) error {
|
||||||
for _, r := range c.Roles {
|
for _, r := range c.Roles {
|
||||||
for _, t := range r.Tables {
|
for _, t := range r.Tables {
|
||||||
if err := addRole(qc, r, t); err != nil {
|
if err := addRole(qc, r, t, c.DefaultAllow); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,54 +215,74 @@ func addRoles(c *Config, qc *qcode.Compiler) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addRole(qc *qcode.Compiler, r Role, t RoleTable) error {
|
func addRole(qc *qcode.Compiler, r Role, t RoleTable, defaultAllow bool) error {
|
||||||
blockFilter := []string{"false"}
|
ro := true // read-only
|
||||||
|
|
||||||
|
if defaultAllow {
|
||||||
|
ro = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Name != "anon" {
|
||||||
|
ro = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.ReadOnly != nil {
|
||||||
|
ro = *t.ReadOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
blocked := struct {
|
||||||
|
query bool
|
||||||
|
insert bool
|
||||||
|
update bool
|
||||||
|
delete bool
|
||||||
|
}{false, ro, ro, ro}
|
||||||
|
|
||||||
|
if t.Query.Block != nil {
|
||||||
|
blocked.query = *t.Query.Block
|
||||||
|
}
|
||||||
|
if t.Insert.Block != nil {
|
||||||
|
blocked.insert = *t.Insert.Block
|
||||||
|
}
|
||||||
|
if t.Update.Block != nil {
|
||||||
|
blocked.update = *t.Update.Block
|
||||||
|
}
|
||||||
|
if t.Delete.Block != nil {
|
||||||
|
blocked.delete = *t.Delete.Block
|
||||||
|
}
|
||||||
|
|
||||||
query := qcode.QueryConfig{
|
query := qcode.QueryConfig{
|
||||||
Limit: t.Query.Limit,
|
Limit: t.Query.Limit,
|
||||||
Filters: t.Query.Filters,
|
Filters: t.Query.Filters,
|
||||||
Columns: t.Query.Columns,
|
Columns: t.Query.Columns,
|
||||||
DisableFunctions: t.Query.DisableFunctions,
|
DisableFunctions: t.Query.DisableFunctions,
|
||||||
}
|
Block: blocked.query,
|
||||||
|
|
||||||
if t.Query.Block {
|
|
||||||
query.Filters = blockFilter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
insert := qcode.InsertConfig{
|
insert := qcode.InsertConfig{
|
||||||
Filters: t.Insert.Filters,
|
Filters: t.Insert.Filters,
|
||||||
Columns: t.Insert.Columns,
|
Columns: t.Insert.Columns,
|
||||||
Presets: t.Insert.Presets,
|
Presets: t.Insert.Presets,
|
||||||
}
|
Block: blocked.insert,
|
||||||
|
|
||||||
if t.Insert.Block {
|
|
||||||
insert.Filters = blockFilter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update := qcode.UpdateConfig{
|
update := qcode.UpdateConfig{
|
||||||
Filters: t.Update.Filters,
|
Filters: t.Update.Filters,
|
||||||
Columns: t.Update.Columns,
|
Columns: t.Update.Columns,
|
||||||
Presets: t.Update.Presets,
|
Presets: t.Update.Presets,
|
||||||
|
Block: blocked.update,
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Update.Block {
|
del := qcode.DeleteConfig{
|
||||||
update.Filters = blockFilter
|
|
||||||
}
|
|
||||||
|
|
||||||
delete := qcode.DeleteConfig{
|
|
||||||
Filters: t.Delete.Filters,
|
Filters: t.Delete.Filters,
|
||||||
Columns: t.Delete.Columns,
|
Columns: t.Delete.Columns,
|
||||||
}
|
Block: blocked.delete,
|
||||||
|
|
||||||
if t.Delete.Block {
|
|
||||||
delete.Filters = blockFilter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return qc.AddRole(r.Name, t.Name, qcode.TRConfig{
|
return qc.AddRole(r.Name, t.Name, qcode.TRConfig{
|
||||||
Query: query,
|
Query: query,
|
||||||
Insert: insert,
|
Insert: insert,
|
||||||
Update: update,
|
Update: update,
|
||||||
Delete: delete,
|
Delete: del,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/chirino/graphql/schema"
|
||||||
"github.com/dosco/super-graph/jsn"
|
"github.com/dosco/super-graph/jsn"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ type Config struct {
|
|||||||
func New(filename string, conf Config) (*List, error) {
|
func New(filename string, conf Config) (*List, error) {
|
||||||
al := List{}
|
al := List{}
|
||||||
|
|
||||||
if len(filename) != 0 {
|
if filename != "" {
|
||||||
fp := filename
|
fp := filename
|
||||||
|
|
||||||
if _, err := os.Stat(fp); err == nil {
|
if _, err := os.Stat(fp); err == nil {
|
||||||
@ -49,7 +50,7 @@ func New(filename string, conf Config) (*List, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(al.filepath) == 0 {
|
if al.filepath == "" {
|
||||||
fp := "./allow.list"
|
fp := "./allow.list"
|
||||||
|
|
||||||
if _, err := os.Stat(fp); err == nil {
|
if _, err := os.Stat(fp); err == nil {
|
||||||
@ -59,7 +60,7 @@ func New(filename string, conf Config) (*List, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(al.filepath) == 0 {
|
if al.filepath == "" {
|
||||||
fp := "./config/allow.list"
|
fp := "./config/allow.list"
|
||||||
|
|
||||||
if _, err := os.Stat(fp); err == nil {
|
if _, err := os.Stat(fp); err == nil {
|
||||||
@ -69,12 +70,12 @@ func New(filename string, conf Config) (*List, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(al.filepath) == 0 {
|
if al.filepath == "" {
|
||||||
if !conf.CreateIfNotExists {
|
if !conf.CreateIfNotExists {
|
||||||
return nil, errors.New("allow.list not found")
|
return nil, errors.New("allow.list not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(filename) == 0 {
|
if filename == "" {
|
||||||
al.filepath = "./config/allow.list"
|
al.filepath = "./config/allow.list"
|
||||||
} else {
|
} else {
|
||||||
al.filepath = filename
|
al.filepath = filename
|
||||||
@ -111,7 +112,7 @@ func (al *List) Set(vars []byte, query, comment string) error {
|
|||||||
return errors.New("allow.list is read-only")
|
return errors.New("allow.list is read-only")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(query) == 0 {
|
if query == "" {
|
||||||
return errors.New("empty query")
|
return errors.New("empty query")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +141,7 @@ func (al *List) Set(vars []byte, query, comment string) error {
|
|||||||
|
|
||||||
func (al *List) Load() ([]Item, error) {
|
func (al *List) Load() ([]Item, error) {
|
||||||
var list []Item
|
var list []Item
|
||||||
|
varString := "variables"
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(al.filepath)
|
b, err := ioutil.ReadFile(al.filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -180,9 +182,9 @@ func (al *List) Load() ([]Item, error) {
|
|||||||
s = e
|
s = e
|
||||||
}
|
}
|
||||||
ty = AL_QUERY
|
ty = AL_QUERY
|
||||||
} else if matchPrefix(b, e, "variables") {
|
} else if matchPrefix(b, e, varString) {
|
||||||
if c == 0 {
|
if c == 0 {
|
||||||
s = e + len("variables") + 1
|
s = e + len(varString) + 1
|
||||||
}
|
}
|
||||||
ty = AL_VARS
|
ty = AL_VARS
|
||||||
} else if b[e] == '{' {
|
} else if b[e] == '{' {
|
||||||
@ -234,10 +236,24 @@ func (al *List) Load() ([]Item, error) {
|
|||||||
func (al *List) save(item Item) error {
|
func (al *List) save(item Item) error {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
item.Name = QueryName(item.Query)
|
qd := &schema.QueryDocument{}
|
||||||
|
|
||||||
|
if err := qd.Parse(item.Query); err != nil {
|
||||||
|
fmt.Println("##", item.Query)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
qd.WriteTo(&buf)
|
||||||
|
query := buf.String()
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
// fmt.Println(">", query)
|
||||||
|
|
||||||
|
item.Name = QueryName(query)
|
||||||
item.key = strings.ToLower(item.Name)
|
item.key = strings.ToLower(item.Name)
|
||||||
|
|
||||||
if len(item.Name) == 0 {
|
if item.Name == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +272,7 @@ func (al *List) save(item Item) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if index != -1 {
|
if index != -1 {
|
||||||
if len(list[index].Comment) != 0 {
|
if list[index].Comment != "" {
|
||||||
item.Comment = list[index].Comment
|
item.Comment = list[index].Comment
|
||||||
}
|
}
|
||||||
list[index] = item
|
list[index] = item
|
||||||
@ -280,7 +296,7 @@ func (al *List) save(item Item) error {
|
|||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for _, c := range cmtLines {
|
for _, c := range cmtLines {
|
||||||
if c = strings.TrimSpace(c); len(c) == 0 {
|
if c = strings.TrimSpace(c); c == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestCockroachDB(t *testing.T) {
|
func TestCockroachDB(t *testing.T) {
|
||||||
|
|
||||||
dir, err := ioutil.TempDir("", "temp-cockraochdb-")
|
dir, err := ioutil.TempDir("", "temp-cockraochdb-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -33,6 +32,7 @@ func TestCockroachDB(t *testing.T) {
|
|||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Skip("is CockroachDB installed?: " + err.Error())
|
t.Skip("is CockroachDB installed?: " + err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("started temporary cockroach db")
|
fmt.Println("started temporary cockroach db")
|
||||||
|
|
||||||
|
@ -50,18 +50,20 @@ func DropSchema(t *testing.T, db *sql.DB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSuperGraph(t *testing.T, db *sql.DB, before func(t *testing.T)) {
|
func TestSuperGraph(t *testing.T, db *sql.DB, before func(t *testing.T)) {
|
||||||
config := core.Config{DefaultBlock: true}
|
config := core.Config{}
|
||||||
config.UseAllowList = false
|
config.UseAllowList = false
|
||||||
config.AllowListFile = "./allow.list"
|
config.AllowListFile = "./allow.list"
|
||||||
config.RolesQuery = `SELECT * FROM users WHERE id = $user_id`
|
config.RolesQuery = `SELECT * FROM users WHERE id = $user_id`
|
||||||
|
|
||||||
|
blockFalse := false
|
||||||
|
|
||||||
config.Roles = []core.Role{
|
config.Roles = []core.Role{
|
||||||
core.Role{
|
core.Role{
|
||||||
Name: "anon",
|
Name: "anon",
|
||||||
Tables: []core.RoleTable{
|
Tables: []core.RoleTable{
|
||||||
core.RoleTable{Name: "users", Query: core.Query{Limit: 100}},
|
core.RoleTable{Name: "users", ReadOnly: &blockFalse, Query: core.Query{Limit: 100}},
|
||||||
core.RoleTable{Name: "product", Query: core.Query{Limit: 100}},
|
core.RoleTable{Name: "product", ReadOnly: &blockFalse, Query: core.Query{Limit: 100}},
|
||||||
core.RoleTable{Name: "line_item", Query: core.Query{Limit: 100}},
|
core.RoleTable{Name: "line_item", ReadOnly: &blockFalse, Query: core.Query{Limit: 100}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,13 @@ func TestCockroachDB(t *testing.T) {
|
|||||||
url, found := os.LookupEnv("SG_POSTGRESQL_TEST_URL")
|
url, found := os.LookupEnv("SG_POSTGRESQL_TEST_URL")
|
||||||
if !found {
|
if !found {
|
||||||
t.Skip("set the SG_POSTGRESQL_TEST_URL env variable if you want to run integration tests against a PostgreSQL database")
|
t.Skip("set the SG_POSTGRESQL_TEST_URL env variable if you want to run integration tests against a PostgreSQL database")
|
||||||
|
} else {
|
||||||
|
db, err := sql.Open("pgx", url)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
integration_tests.DropSchema(t, db)
|
||||||
|
integration_tests.SetupSchema(t, db)
|
||||||
|
integration_tests.TestSuperGraph(t, db, func(t *testing.T) {
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
db, err := sql.Open("pgx", url)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
integration_tests.DropSchema(t, db)
|
|
||||||
integration_tests.SetupSchema(t, db)
|
|
||||||
integration_tests.TestSuperGraph(t, db, func(t *testing.T) {
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,6 @@ const (
|
|||||||
closeBlock = 500
|
closeBlock = 500
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrAllTablesSkipped = errors.New("all tables skipped. cannot render query")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Variables map[string]json.RawMessage
|
type Variables map[string]json.RawMessage
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -92,30 +88,35 @@ func (co *Compiler) compileQuery(qc *qcode.QCode, w io.Writer, vars Variables) (
|
|||||||
|
|
||||||
io.WriteString(c.w, `SELECT jsonb_build_object(`)
|
io.WriteString(c.w, `SELECT jsonb_build_object(`)
|
||||||
for _, id := range qc.Roots {
|
for _, id := range qc.Roots {
|
||||||
root := &qc.Selects[id]
|
|
||||||
if root.SkipRender || len(root.Cols) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
st.Push(root.ID + closeBlock)
|
|
||||||
st.Push(root.ID)
|
|
||||||
|
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
io.WriteString(c.w, `, `)
|
io.WriteString(c.w, `, `)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.renderRootSelect(root)
|
root := &qc.Selects[id]
|
||||||
|
|
||||||
|
if root.SkipRender || len(root.Cols) == 0 {
|
||||||
|
squoted(c.w, root.FieldName)
|
||||||
|
io.WriteString(c.w, `, `)
|
||||||
|
io.WriteString(c.w, `NULL`)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
st.Push(root.ID + closeBlock)
|
||||||
|
st.Push(root.ID)
|
||||||
|
c.renderRootSelect(root)
|
||||||
|
}
|
||||||
|
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
io.WriteString(c.w, `) as "__root" FROM `)
|
|
||||||
|
|
||||||
if i == 0 {
|
|
||||||
return 0, ErrAllTablesSkipped
|
|
||||||
}
|
|
||||||
|
|
||||||
var ignored uint32
|
var ignored uint32
|
||||||
|
|
||||||
|
if st.Len() != 0 {
|
||||||
|
io.WriteString(c.w, `) as "__root" FROM `)
|
||||||
|
} else {
|
||||||
|
io.WriteString(c.w, `) as "__root"`)
|
||||||
|
return ignored, nil
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if st.Len() == 0 {
|
if st.Len() == 0 {
|
||||||
break
|
break
|
||||||
|
@ -17,7 +17,7 @@ type DBInfo struct {
|
|||||||
colMap map[string]map[string]*DBColumn
|
colMap map[string]map[string]*DBColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDBInfo(db *sql.DB) (*DBInfo, error) {
|
func GetDBInfo(db *sql.DB, schema string) (*DBInfo, error) {
|
||||||
di := &DBInfo{}
|
di := &DBInfo{}
|
||||||
var version string
|
var version string
|
||||||
|
|
||||||
@ -31,13 +31,13 @@ func GetDBInfo(db *sql.DB) (*DBInfo, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
di.Tables, err = GetTables(db)
|
di.Tables, err = GetTables(db, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range di.Tables {
|
for _, t := range di.Tables {
|
||||||
cols, err := GetColumns(db, "public", t.Name)
|
cols, err := GetColumns(db, schema, t.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ func GetDBInfo(db *sql.DB) (*DBInfo, error) {
|
|||||||
|
|
||||||
di.colMap = newColMap(di.Tables, di.Columns)
|
di.colMap = newColMap(di.Tables, di.Columns)
|
||||||
|
|
||||||
di.Functions, err = GetFunctions(db)
|
di.Functions, err = GetFunctions(db, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ type DBTable struct {
|
|||||||
Type string
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTables(db *sql.DB) ([]DBTable, error) {
|
func GetTables(db *sql.DB, schema string) ([]DBTable, error) {
|
||||||
sqlStmt := `
|
sqlStmt := `
|
||||||
SELECT
|
SELECT
|
||||||
c.relname as "name",
|
c.relname as "name",
|
||||||
@ -108,14 +108,12 @@ SELECT
|
|||||||
FROM pg_catalog.pg_class c
|
FROM pg_catalog.pg_class c
|
||||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
||||||
WHERE c.relkind IN ('r','v','m','f','')
|
WHERE c.relkind IN ('r','v','m','f','')
|
||||||
AND n.nspname <> ('pg_catalog')
|
AND n.nspname = $1
|
||||||
AND n.nspname <> ('information_schema')
|
AND pg_catalog.pg_table_is_visible(c.oid);`
|
||||||
AND n.nspname !~ ('^pg_toast')
|
|
||||||
AND pg_catalog.pg_table_is_visible(c.oid);`
|
|
||||||
|
|
||||||
var tables []DBTable
|
var tables []DBTable
|
||||||
|
|
||||||
rows, err := db.Query(sqlStmt)
|
rows, err := db.Query(sqlStmt, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error fetching tables: %s", err)
|
return nil, fmt.Errorf("Error fetching tables: %s", err)
|
||||||
}
|
}
|
||||||
@ -264,7 +262,7 @@ type DBFuncParam struct {
|
|||||||
Type string
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFunctions(db *sql.DB) ([]DBFunction, error) {
|
func GetFunctions(db *sql.DB, schema string) ([]DBFunction, error) {
|
||||||
sqlStmt := `
|
sqlStmt := `
|
||||||
SELECT
|
SELECT
|
||||||
routines.routine_name,
|
routines.routine_name,
|
||||||
@ -278,11 +276,11 @@ RIGHT JOIN
|
|||||||
information_schema.parameters
|
information_schema.parameters
|
||||||
ON (routines.specific_name = parameters.specific_name and parameters.ordinal_position IS NOT NULL)
|
ON (routines.specific_name = parameters.specific_name and parameters.ordinal_position IS NOT NULL)
|
||||||
WHERE
|
WHERE
|
||||||
routines.specific_schema = 'public'
|
routines.specific_schema = $1
|
||||||
ORDER BY
|
ORDER BY
|
||||||
routines.routine_name, parameters.ordinal_position;`
|
routines.routine_name, parameters.ordinal_position;`
|
||||||
|
|
||||||
rows, err := db.Query(sqlStmt)
|
rows, err := db.Query(sqlStmt, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error fetching functions: %s", err)
|
return nil, fmt.Errorf("Error fetching functions: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Blocklist []string
|
Blocklist []string
|
||||||
DefaultBlock bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueryConfig struct {
|
type QueryConfig struct {
|
||||||
@ -16,23 +15,27 @@ type QueryConfig struct {
|
|||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
DisableFunctions bool
|
DisableFunctions bool
|
||||||
|
Block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type InsertConfig struct {
|
type InsertConfig struct {
|
||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Presets map[string]string
|
Presets map[string]string
|
||||||
|
Block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateConfig struct {
|
type UpdateConfig struct {
|
||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
Presets map[string]string
|
Presets map[string]string
|
||||||
|
Block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeleteConfig struct {
|
type DeleteConfig struct {
|
||||||
Filters []string
|
Filters []string
|
||||||
Columns []string
|
Columns []string
|
||||||
|
Block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type TRConfig struct {
|
type TRConfig struct {
|
||||||
@ -43,14 +46,14 @@ type TRConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type trval struct {
|
type trval struct {
|
||||||
query struct {
|
readOnly bool
|
||||||
|
query struct {
|
||||||
limit string
|
limit string
|
||||||
fil *Exp
|
fil *Exp
|
||||||
filNU bool
|
filNU bool
|
||||||
cols map[string]struct{}
|
cols map[string]struct{}
|
||||||
disable struct {
|
disable struct{ funcs bool }
|
||||||
funcs bool
|
block bool
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
insert struct {
|
insert struct {
|
||||||
@ -59,6 +62,7 @@ type trval struct {
|
|||||||
cols map[string]struct{}
|
cols map[string]struct{}
|
||||||
psmap map[string]string
|
psmap map[string]string
|
||||||
pslist []string
|
pslist []string
|
||||||
|
block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
update struct {
|
update struct {
|
||||||
@ -67,12 +71,14 @@ type trval struct {
|
|||||||
cols map[string]struct{}
|
cols map[string]struct{}
|
||||||
psmap map[string]string
|
psmap map[string]string
|
||||||
pslist []string
|
pslist []string
|
||||||
|
block bool
|
||||||
}
|
}
|
||||||
|
|
||||||
delete struct {
|
delete struct {
|
||||||
fil *Exp
|
fil *Exp
|
||||||
filNU bool
|
filNU bool
|
||||||
cols map[string]struct{}
|
cols map[string]struct{}
|
||||||
|
block bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ var expPool = sync.Pool{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewCompiler(c Config) (*Compiler, error) {
|
func NewCompiler(c Config) (*Compiler, error) {
|
||||||
co := &Compiler{db: c.DefaultBlock}
|
co := &Compiler{}
|
||||||
co.tr = make(map[string]map[string]*trval)
|
co.tr = make(map[string]map[string]*trval)
|
||||||
co.bl = make(map[string]struct{}, len(c.Blocklist))
|
co.bl = make(map[string]struct{}, len(c.Blocklist))
|
||||||
|
|
||||||
@ -219,6 +219,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
|||||||
}
|
}
|
||||||
trv.query.cols = listToMap(trc.Query.Columns)
|
trv.query.cols = listToMap(trc.Query.Columns)
|
||||||
trv.query.disable.funcs = trc.Query.DisableFunctions
|
trv.query.disable.funcs = trc.Query.DisableFunctions
|
||||||
|
trv.query.block = trc.Query.Block
|
||||||
|
|
||||||
// insert config
|
// insert config
|
||||||
trv.insert.fil, trv.insert.filNU, err = compileFilter(trc.Insert.Filters)
|
trv.insert.fil, trv.insert.filNU, err = compileFilter(trc.Insert.Filters)
|
||||||
@ -228,6 +229,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
|||||||
trv.insert.cols = listToMap(trc.Insert.Columns)
|
trv.insert.cols = listToMap(trc.Insert.Columns)
|
||||||
trv.insert.psmap = parsePresets(trc.Insert.Presets)
|
trv.insert.psmap = parsePresets(trc.Insert.Presets)
|
||||||
trv.insert.pslist = mapToList(trv.insert.psmap)
|
trv.insert.pslist = mapToList(trv.insert.psmap)
|
||||||
|
trv.insert.block = trc.Insert.Block
|
||||||
|
|
||||||
// update config
|
// update config
|
||||||
trv.update.fil, trv.update.filNU, err = compileFilter(trc.Update.Filters)
|
trv.update.fil, trv.update.filNU, err = compileFilter(trc.Update.Filters)
|
||||||
@ -237,6 +239,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
|||||||
trv.update.cols = listToMap(trc.Update.Columns)
|
trv.update.cols = listToMap(trc.Update.Columns)
|
||||||
trv.update.psmap = parsePresets(trc.Update.Presets)
|
trv.update.psmap = parsePresets(trc.Update.Presets)
|
||||||
trv.update.pslist = mapToList(trv.update.psmap)
|
trv.update.pslist = mapToList(trv.update.psmap)
|
||||||
|
trv.update.block = trc.Update.Block
|
||||||
|
|
||||||
// delete config
|
// delete config
|
||||||
trv.delete.fil, trv.delete.filNU, err = compileFilter(trc.Delete.Filters)
|
trv.delete.fil, trv.delete.filNU, err = compileFilter(trc.Delete.Filters)
|
||||||
@ -244,6 +247,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
trv.delete.cols = listToMap(trc.Delete.Columns)
|
trv.delete.cols = listToMap(trc.Delete.Columns)
|
||||||
|
trv.delete.block = trc.Delete.Block
|
||||||
|
|
||||||
singular := flect.Singularize(table)
|
singular := flect.Singularize(table)
|
||||||
plural := flect.Pluralize(table)
|
plural := flect.Pluralize(table)
|
||||||
@ -329,37 +333,82 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trv := com.getRole(role, field.Name)
|
trv := com.getRole(role, field.Name)
|
||||||
|
skipRender := false
|
||||||
|
|
||||||
|
if trv != nil {
|
||||||
|
switch action {
|
||||||
|
case QTQuery:
|
||||||
|
if trv.query.block {
|
||||||
|
skipRender = true
|
||||||
|
}
|
||||||
|
|
||||||
|
case QTInsert:
|
||||||
|
if trv.insert.block {
|
||||||
|
return fmt.Errorf("insert blocked: %s", field.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
case QTUpdate:
|
||||||
|
if trv.update.block {
|
||||||
|
return fmt.Errorf("update blocked: %s", field.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
case QTDelete:
|
||||||
|
if trv.delete.block {
|
||||||
|
return fmt.Errorf("delete blocked: %s", field.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if role == "anon" {
|
||||||
|
skipRender = true
|
||||||
|
}
|
||||||
|
|
||||||
selects = append(selects, Select{
|
selects = append(selects, Select{
|
||||||
ID: id,
|
ID: id,
|
||||||
ParentID: parentID,
|
ParentID: parentID,
|
||||||
Name: field.Name,
|
Name: field.Name,
|
||||||
Children: make([]int32, 0, 5),
|
SkipRender: skipRender,
|
||||||
Allowed: trv.allowedColumns(action),
|
|
||||||
Functions: true,
|
|
||||||
})
|
})
|
||||||
s := &selects[(len(selects) - 1)]
|
s := &selects[(len(selects) - 1)]
|
||||||
|
|
||||||
switch action {
|
|
||||||
case QTQuery:
|
|
||||||
s.Functions = !trv.query.disable.funcs
|
|
||||||
s.Paging.Limit = trv.query.limit
|
|
||||||
|
|
||||||
case QTInsert:
|
|
||||||
s.PresetMap = trv.insert.psmap
|
|
||||||
s.PresetList = trv.insert.pslist
|
|
||||||
|
|
||||||
case QTUpdate:
|
|
||||||
s.PresetMap = trv.update.psmap
|
|
||||||
s.PresetList = trv.update.pslist
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(field.Alias) != 0 {
|
if len(field.Alias) != 0 {
|
||||||
s.FieldName = field.Alias
|
s.FieldName = field.Alias
|
||||||
} else {
|
} else {
|
||||||
s.FieldName = s.Name
|
s.FieldName = s.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.ParentID == -1 {
|
||||||
|
qc.Roots = append(qc.Roots, s.ID)
|
||||||
|
} else {
|
||||||
|
p := &selects[s.ParentID]
|
||||||
|
p.Children = append(p.Children, s.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if skipRender {
|
||||||
|
id++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Children = make([]int32, 0, 5)
|
||||||
|
s.Functions = true
|
||||||
|
|
||||||
|
if trv != nil {
|
||||||
|
s.Allowed = trv.allowedColumns(action)
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case QTQuery:
|
||||||
|
s.Functions = !trv.query.disable.funcs
|
||||||
|
s.Paging.Limit = trv.query.limit
|
||||||
|
|
||||||
|
case QTInsert:
|
||||||
|
s.PresetMap = trv.insert.psmap
|
||||||
|
s.PresetList = trv.insert.pslist
|
||||||
|
|
||||||
|
case QTUpdate:
|
||||||
|
s.PresetMap = trv.update.psmap
|
||||||
|
s.PresetList = trv.update.pslist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := com.compileArgs(qc, s, field.Args, role)
|
err := com.compileArgs(qc, s, field.Args, role)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -368,13 +417,6 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
|
|||||||
// Order is important AddFilters must come after compileArgs
|
// Order is important AddFilters must come after compileArgs
|
||||||
com.AddFilters(qc, s, role)
|
com.AddFilters(qc, s, role)
|
||||||
|
|
||||||
if s.ParentID == -1 {
|
|
||||||
qc.Roots = append(qc.Roots, s.ID)
|
|
||||||
} else {
|
|
||||||
p := &selects[s.ParentID]
|
|
||||||
p.Children = append(p.Children, s.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Cols = make([]Column, 0, len(field.Children))
|
s.Cols = make([]Column, 0, len(field.Children))
|
||||||
action = QTQuery
|
action = QTQuery
|
||||||
|
|
||||||
@ -414,14 +456,10 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
|
|||||||
|
|
||||||
func (com *Compiler) AddFilters(qc *QCode, sel *Select, role string) {
|
func (com *Compiler) AddFilters(qc *QCode, sel *Select, role string) {
|
||||||
var fil *Exp
|
var fil *Exp
|
||||||
var nu bool // user required (or not) in this filter
|
var nu bool // need user_id (or not) in this filter
|
||||||
|
|
||||||
if trv, ok := com.tr[role][sel.Name]; ok {
|
if trv, ok := com.tr[role][sel.Name]; ok {
|
||||||
fil, nu = trv.filter(qc.Type)
|
fil, nu = trv.filter(qc.Type)
|
||||||
|
|
||||||
} else if com.db && role == "anon" {
|
|
||||||
// Tables not defined under the anon role will not be rendered
|
|
||||||
sel.SkipRender = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if fil == nil {
|
if fil == nil {
|
||||||
@ -812,14 +850,17 @@ func (com *Compiler) compileArgAfterBefore(sel *Select, arg *Arg, pt PagingType)
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeroTrv = &trval{}
|
// var zeroTrv = &trval{}
|
||||||
|
|
||||||
func (com *Compiler) getRole(role, field string) *trval {
|
func (com *Compiler) getRole(role, field string) *trval {
|
||||||
if trv, ok := com.tr[role][field]; ok {
|
if trv, ok := com.tr[role][field]; ok {
|
||||||
return trv
|
return trv
|
||||||
} else {
|
|
||||||
return zeroTrv
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
// } else {
|
||||||
|
// return zeroTrv
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddFilter(sel *Select, fil *Exp) {
|
func AddFilter(sel *Select, fil *Exp) {
|
||||||
@ -946,6 +987,9 @@ func newExp(st *util.Stack, node *Node, usePool bool) (*Exp, error) {
|
|||||||
ex.Op = OpDistinct
|
ex.Op = OpDistinct
|
||||||
ex.Val = node.Val
|
ex.Val = node.Val
|
||||||
default:
|
default:
|
||||||
|
if len(node.Children) == 0 {
|
||||||
|
return nil, fmt.Errorf("[Where] invalid operation: %s", name)
|
||||||
|
}
|
||||||
pushChildren(st, node.exp, node)
|
pushChildren(st, node.exp, node)
|
||||||
return nil, nil // skip node
|
return nil, nil // skip node
|
||||||
}
|
}
|
||||||
@ -965,8 +1009,9 @@ func newExp(st *util.Stack, node *Node, usePool bool) (*Exp, error) {
|
|||||||
case NodeVar:
|
case NodeVar:
|
||||||
ex.Type = ValVar
|
ex.Type = ValVar
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("[Where] valid values include string, int, float, boolean and list: %s", node.Type)
|
return nil, fmt.Errorf("[Where] invalid values for: %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
setWhereColName(ex, node)
|
setWhereColName(ex, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1015,6 +1060,7 @@ func setWhereColName(ex *Exp, node *Node) {
|
|||||||
ex.Col = list[listlen-1]
|
ex.Col = list[listlen-1]
|
||||||
ex.NestedCols = list[:listlen]
|
ex.NestedCols = list[:listlen]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setOrderByColName(ob *OrderBy, node *Node) {
|
func setOrderByColName(ob *OrderBy, node *Node) {
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/dosco/super-graph/core/internal/allow"
|
"github.com/dosco/super-graph/core/internal/allow"
|
||||||
"github.com/dosco/super-graph/core/internal/psql"
|
|
||||||
"github.com/dosco/super-graph/core/internal/qcode"
|
"github.com/dosco/super-graph/core/internal/qcode"
|
||||||
"github.com/valyala/fasttemplate"
|
"github.com/valyala/fasttemplate"
|
||||||
)
|
)
|
||||||
@ -103,9 +102,6 @@ func (sg *SuperGraph) prepareStmt(item allow.Item) error {
|
|||||||
// logger.Debug().Msgf("Prepared statement 'query %s' (anon)", item.Name)
|
// logger.Debug().Msgf("Prepared statement 'query %s' (anon)", item.Name)
|
||||||
|
|
||||||
stmts2, err := sg.buildRoleStmt(qb, vars, "anon")
|
stmts2, err := sg.buildRoleStmt(qb, vars, "anon")
|
||||||
if err == psql.ErrAllTablesSkipped {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -121,9 +117,6 @@ func (sg *SuperGraph) prepareStmt(item allow.Item) error {
|
|||||||
// logger.Debug().Msgf("Prepared statement 'mutation %s' (%s)", item.Name, role.Name)
|
// logger.Debug().Msgf("Prepared statement 'mutation %s' (%s)", item.Name, role.Name)
|
||||||
|
|
||||||
stmts, err := sg.buildRoleStmt(qb, vars, role.Name)
|
stmts, err := sg.buildRoleStmt(qb, vars, role.Name)
|
||||||
if err == psql.ErrAllTablesSkipped {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,41 +1,40 @@
|
|||||||
0e384e19.bc97038f.js,1589756749060,098da569a72fb34a077f0e411b009ccdcc0e98c04a1a403a952bbea6a51aa195
|
01a106d5.06939d67.js,1589776216137,2e1ce67f6cf79a8a8e2070fc4ea4a6104ac73a5b26a1ab10b62f6cd8e45a8074
|
||||||
01a106d5.e6fa2a6a.js,1589756749060,7ee597df32dc6163edea35383043c7e5affb12525acb3250f92aa18157ab8e41
|
1.1c32171f.js.LICENSE.txt,1589776216144,31b4d50dbbd144da150dcdcf0ccef8f6cf8b6b5204d5c9adde3b24466777fad5
|
||||||
1.1c32171f.js.LICENSE.txt,1589756749064,31b4d50dbbd144da150dcdcf0ccef8f6cf8b6b5204d5c9adde3b24466777fad5
|
0e384e19.7f29b403.js,1589776216137,e2c3882226f2a601b65e4bb1fdb771296c1946f9f125c90af4a8f451dfd2c867
|
||||||
19.fdfbe826.js.LICENSE.txt,1589756749064,6ad95a8099127a8d42b5ace6d148064b1d3e922174f08d75d0ee2220ebeacd0b
|
19.fdfbe826.js.LICENSE.txt,1589776216145,6ad95a8099127a8d42b5ace6d148064b1d3e922174f08d75d0ee2220ebeacd0b
|
||||||
17896441.183211f5.js,1589756749060,7736db62d7498a8d3a10a617b1bdfac08c8f29dc03329f4ad3320f2571c223c0
|
17896441.183211f5.js,1589776216137,7736db62d7498a8d3a10a617b1bdfac08c8f29dc03329f4ad3320f2571c223c0
|
||||||
20ac7829.c04b4a1e.js,1589756749060,5b95f479848ccd6959630d4a24bd551d0dbc74457911e9b6f3498655bfaf8ea7
|
20ac7829.c04b4a1e.js,1589776216137,5b95f479848ccd6959630d4a24bd551d0dbc74457911e9b6f3498655bfaf8ea7
|
||||||
404.html,1589756750606,fe7e6a0f354000328576c9a2d8794d55dae6de0a9883e2f9dda7be4c91aa8f2a
|
1.1c32171f.js,1589776216137,5441b74bfad9f5a37ba0e6123621c73c3e3b9064bda6b9dcf62fdb7381bf8e41
|
||||||
1.1c32171f.js,1589756749061,5441b74bfad9f5a37ba0e6123621c73c3e3b9064bda6b9dcf62fdb7381bf8e41
|
2.8f12478f.js,1589776216137,3ac7ca0df8fca86145f5decbd86c8adfbc6b5b11a5be96fc96cc9bc33d6306e6
|
||||||
395f47e2.9ce46e61.js,1589756749060,fad9479ae57496cd96b3daf191197ec9899c9571bba4d35723a7a29e33468999
|
395f47e2.28d67f37.js,1589776216137,8a9b6bc2afdd99ca2b1827c8289352fab6163e30151b9701c29a7863b6cd00b6
|
||||||
2.8f12478f.js,1589756749061,3ac7ca0df8fca86145f5decbd86c8adfbc6b5b11a5be96fc96cc9bc33d6306e6
|
404.html,1589776218438,0a748eaa7614b1982623360ba8554c0f498b0796ead3cc429a2c84d287084b50
|
||||||
3d9c95a4.5f37b350.js,1589756749061,9458017327095622c54f0716951d83affe3149089f7dc56025627d979255bf43
|
3d9c95a4.c89589de.js,1589776216137,d5c45e5a3671f303683451d448e2e5d5b464f041cde683af6e824b9e7f951412
|
||||||
969d212d.82b6da9d.js,1589756749061,444b2a6c59ec2a0847279a4fed62b148c967fecae0b550433885f71ed5d9e13b
|
9225b3a9.a5e6036b.js,1589776216137,ec9a0d4b34d8751f74348d0da369625a18f320c9ed5ab3c5ccf047ead2551bd8
|
||||||
c4f5d8e4.47e70b85.js,1589756749064,6f986b48720724e7c8a715812b5f6625c71c8eca258bb4b410a447eb5da52734
|
741df2ae.e13b96b2.js,1589776216137,12028f0cbdf783ac91ea42db64d91190ebd4df24cc74162f953aacc75d16d078
|
||||||
741df2ae.162c25b8.js,1589756749061,8a68c30fa75945a2bff9899a3447003bcfc33f3b46111d37842e1802ad6d3fca
|
969d212d.9fc45877.js,1589776216138,8323c9f2db042bfaa2ebba43d9500bed881a694d0bfc27fd796cec95bb032dc5
|
||||||
9225b3a9.a07e65fb.js,1589756749061,5a6bb09b0b56b1d14c482dc1423e2eca5128a23fd54ff0fd261865543225d8cf
|
c4f5d8e4.47e70b85.js,1589776216145,6f986b48720724e7c8a715812b5f6625c71c8eca258bb4b410a447eb5da52734
|
||||||
index.html,1589756750606,43c17105a27007e3368d4275ec5fd617eea945b78868c43c73ba32f74184cb62
|
index.html,1589776218438,89f81ec3d3be439a827bd61448dcaddb71c33422df7baa88a7bbcdf784dbc0b2
|
||||||
main.f771ef31.js.LICENSE.txt,1589756749064,1d906c3b83eacffe298d21eeb73e6e73e96310983224783d236195098e6765a7
|
98ce8162.b5ace15d.js,1589776216137,935e1c6dd08f7e9d0d00221559b95f0f649e28ddf64be6bbb7b3e65bae1aba72
|
||||||
98ce8162.1704a8b8.js,1589756749061,d109a5c0b42fa7f7753dfe95fddeca8db1520956f724e90219be70d1e40c18f2
|
main.e30d99cd.js.LICENSE.txt,1589776216144,1d906c3b83eacffe298d21eeb73e6e73e96310983224783d236195098e6765a7
|
||||||
sitemap.xml,1589756750623,660ed269bf0306ba47ecdfb638e487147784d614c43c6c4a8e84194973baf183
|
runtime~main.366c29ad.js,1589776216145,0e550cc9522cd99c5fa4097c7db629eef56127a7f8ade0b7c9954cc8f6a01239
|
||||||
99e04881.2a79a052.js,1589756749064,8f5258dd347ac81b78c9837f762d9f247607011dd16553f34c2031c4ccbd38ea
|
5043549d.62508ecf.js,1589776216137,383959b80d2b0c6416e83c9640ea03c666fe92c407e13a6f022b58072feeafd2
|
||||||
runtime~main.82a8fb74.js,1589756749064,d921e2c431192f04f24dd17747b3f87ddc673c8ad16fd59a769dae8c1a37e23b
|
99e04881.197dcef6.js,1589776216144,af99883cbd4d58fbac7cbf814be33032b77bc8daf856aed54bdf0bf27ed5708d
|
||||||
5043549d.cb3b9121.js,1589756749061,3e19828fe02c125eff01c388067ee2d817bdc6f963c063ff7d1be9fba440f658
|
sitemap.xml,1589776218455,660ed269bf0306ba47ecdfb638e487147784d614c43c6c4a8e84194973baf183
|
||||||
styles.9155f1d2.js,1589756749060,f1e0863928710e67338dc88c37f47ef3ff164d36c4bba40d005561094c9c3284
|
styles.9155f1d2.js,1589776216137,f1e0863928710e67338dc88c37f47ef3ff164d36c4bba40d005561094c9c3284
|
||||||
db32d859.d7e74c54.js,1589756749064,e800ed98ca5b6a8dcb800e1b8fd8fe57564e22a41899181f07147ae08a153f24
|
db32d859.a032827a.js,1589776216145,36d575ffad747898726a97cb7a3551e636f744218595bea5c060536eb8d8390f
|
||||||
docs/advanced/index.html,1589756750609,9f7260c581cb4e71c46896af29c537e0fb02fac3228d4a991435bdf995f542e8
|
docs/advanced/index.html,1589776218439,31171870786a597597de9417978a27253581c013962e39959ae4c0777bf86c28
|
||||||
docs/deploy/index.html,1589756750609,555db8271ebd923ff2ffebe51ade18aa2f7f78650bd9d358fdcd8fb2eecd8de3
|
docs/deploy/index.html,1589776218440,7a4735edb93006311b704e62b843bf89bc4354fdf0fdc22a0c5802e39878c193
|
||||||
docs/home/index.html,1589756750609,5b095aec72d5e0a50aac298598c1b27964656d67db94097dc1c8e0bfac4c59b9
|
docs/home/index.html,1589776218440,c7fbb0c1084c6ef8858775c5083b6b416b8188942d4402a5a625eadb3bc00942
|
||||||
docs/react/index.html,1589756750609,bea10eea368d0ae5848e4dd34ccd0215b1fef58940768dd2d9c8fad246aee172
|
docs/intro/index.html,1589776218440,c7a50ae98c0b279f422e55c2eeb9f7ba1c7c1a8bcac07be11fd6e05ced224094
|
||||||
img/super-graph-logo.svg,1589756750606,648bfe286ee36b88ad9accf8cda7eb016c8fe3c0aa7fe6777856ac1e2dac9b32
|
img/super-graph-logo.svg,1589776218438,66a865c4936f44ea811464b967f221b615b7553e85dca0d6f1ef620da3911857
|
||||||
docs/intro/index.html,1589756750609,f9eefab7ad7aefec779dc43f2ee17df1cb5c1edd8878e723bf3c136c18468f9a
|
docs/react/index.html,1589776218440,f76fc976f3491d9aacf19ce3b34bee1339f87c673a9da95f192683615618f210
|
||||||
docs/why/index.html,1589756750609,7e4ecb00fc6fb663f826e424c3f09727fbafa5323e1de71ea178946a9584eae2
|
docs/why/index.html,1589776218440,4aa380fe4e5d8476645e368d1f708d5d1344331c572383db823c3499fa0c99cc
|
||||||
docs/security/index.html,1589756750609,a612631d3364369d079780ed377b84d1570a15233ab4ed66392ffc7248eaf4fa
|
docs/security/index.html,1589776218440,0c7d466dc143935db8c02a448952cae2465635e4b6782b1682449bbd56807917
|
||||||
styles.8ee0cad4.css,1589756749060,34b2e79c5c5b1f7afda4376e422e8ccb2c3c04213ca09d788f0c68ecf153d6e6
|
styles.8ee0cad4.css,1589776216137,34b2e79c5c5b1f7afda4376e422e8ccb2c3c04213ca09d788f0c68ecf153d6e6
|
||||||
docs/config/index.html,1589756750609,964692badbdd80f41ab481b4753046ec17583692b57843becadb18c84bc5fa52
|
docs/config/index.html,1589776218440,25b6e87a42c163ac966e80acebca8708f56ae95ba8f3ed8b98ff7fd70ca5a222
|
||||||
docs/start/index.html,1589756750609,8b6da7abe0dc0bacb97c6ba04e9b63d0de47c7d8c7db51b1b1d03c3fad740043
|
docs/internals/index.html,1589776218440,b6f2136a1c832f421a46329fb1f39269d820c55a0dfc9351848271a5501d8e6e
|
||||||
img/favicon.png,1589756750610,1a9ddda9df7e965340c2b5fdfc9b1f76ec11c2fcc800ec7908ca8827f3c95741
|
docs/start/index.html,1589776218440,485ec2c61117d8940d8028f34d51d421995a814d5b9d4d5a1870adaed48aec2c
|
||||||
docs/internals/index.html,1589756750607,d69ff057c545f868959dc8d54c577947d6c25ea982d992d377646eaffbef255c
|
docs/graphql/index.html,1589776218440,3bd79f703fe67656884f3121bfddc3a4fc4d9e5bb2bf9271c94014058fbbd806
|
||||||
docs/graphql/index.html,1589756750609,f8c7f0f5d5566eca1f8ae39b941aee0ed82adc52ce50dc922982de8d02d2a59a
|
main.e30d99cd.js,1589776216144,98a4087d6f537aaddbc1225aaabfb4d12d1394772deb618d4d457685cee59311
|
||||||
main.f771ef31.js,1589756749064,2dcb5a6634b787512f51a25f69f7f862f027548def31c5c79894ffff7375c59a
|
19.fdfbe826.js,1589776216144,b8abb73aea5fc0aa50d7e8b8bd38984e3b3aec62de2faf66fb3e55fd1428f8a7
|
||||||
19.fdfbe826.js,1589756749064,b8abb73aea5fc0aa50d7e8b8bd38984e3b3aec62de2faf66fb3e55fd1428f8a7
|
server.bundle.js,1589776218438,826db37f1de931e8b088c1ff20b4a3c2fe0c3d54d9ff4020e500f0df1b83a616
|
||||||
server.bundle.js,1589756750606,aceff68a47f9236060259eca732a163a2e660e59f43195289cafba2abd244165
|
|
||||||
|
@ -1,21 +1,45 @@
|
|||||||
---
|
---
|
||||||
id: home
|
id: home
|
||||||
title: Super Graph
|
title: Super Graph
|
||||||
|
hide_title: true
|
||||||
sidebar_label: Home
|
sidebar_label: Home
|
||||||
---
|
---
|
||||||
|
|
||||||
import useBaseUrl from '@docusaurus/useBaseUrl'; // Add to the top of the file below the front matter.
|
import useBaseUrl from '@docusaurus/useBaseUrl'; // Add to the top of the file below the front matter.
|
||||||
|
|
||||||
<img alt="Super Graph Logo" src={useBaseUrl('img/super-graph-logo.svg')} height="60" />;
|
<div class="hero shadow--lw margin-bottom--lg">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col--2">
|
||||||
|
<img
|
||||||
|
class="avatar__photo avatar__photo--xl"
|
||||||
|
alt="Super Graph Logo"
|
||||||
|
src={useBaseUrl('img/super-graph-logo.svg')}
|
||||||
|
height="70"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col col--10"><h1 class="hero__title">Super Graph</h1></div>
|
||||||
|
</div>
|
||||||
|
<p class="hero__subtitle">Fetch data without code!</p>
|
||||||
|
<div class="margin-bottom--lg">
|
||||||
|
<a class="button button--secondary button--outline button--lg" href="start">
|
||||||
|
Skip Intro
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<p>Stop fighting ORM's and complex SQL just to fetch the data you need. Instead try Super Graph it automagically tranforms GraphQL into efficient SQL.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
## Fetch data without code!
|
:::info cut development time
|
||||||
|
|
||||||
### Stop strugging with ORM's and complex SQL just to fetch the data you need. Instead try asking nicely with GraphQL.
|
|
||||||
|
|
||||||
:::info
|
|
||||||
80% of all web app development is either reading from or writing to a database. 100x your developer productivity and save valuable time by making that super simple.
|
80% of all web app development is either reading from or writing to a database. 100x your developer productivity and save valuable time by making that super simple.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Fetching data with GraphQL
|
||||||
|
|
||||||
|
Just imagine the code or SQL you'll need to fetch this data, the user, all his posts, all the votes on the posts, the authors information and the related tags. Oh yeah and you also need efficient cursor based pagination. And Remember you also need to maintain this code forever.
|
||||||
|
|
||||||
|
Instead just describe the data you need in GraphQL and give that to Super Graph it'll automatically learn your database and generate the most efficient SQL query fetching your data in the JSON structure you expected.
|
||||||
|
|
||||||
```graphql
|
```graphql
|
||||||
query {
|
query {
|
||||||
user(id: 5) {
|
user(id: 5) {
|
||||||
@ -45,7 +69,10 @@ query {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Super Graph automatially compiles your GraphQL into an efficient SQL query giving you the results you wanted.
|
### Instant results
|
||||||
|
|
||||||
|
Here's the data Super Graph fetched using the GraphQL above, it's even in the JSON structure you
|
||||||
|
wanted it in. All this without you writing any code or SQL.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -77,6 +104,8 @@ query {
|
|||||||
"created_at": "2020-05-13T13:51:21.729501+00:00"
|
"created_at": "2020-05-13T13:51:21.729501+00:00"
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
|
],
|
||||||
|
"posts_cursor": "a8d4j2k9d83dy373hd2nskw2sjs8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -3,7 +3,7 @@ module.exports = {
|
|||||||
tagline: "Fetch data without code",
|
tagline: "Fetch data without code",
|
||||||
url: "https://supergraph.dev",
|
url: "https://supergraph.dev",
|
||||||
baseUrl: "/",
|
baseUrl: "/",
|
||||||
favicon: "img/favicon.svg",
|
favicon: "img/super-graph-logo.svg",
|
||||||
organizationName: "dosco", // Usually your GitHub org/user name.
|
organizationName: "dosco", // Usually your GitHub org/user name.
|
||||||
projectName: "super-graph", // Usually your repo name.
|
projectName: "super-graph", // Usually your repo name.
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
@ -11,7 +11,7 @@ module.exports = {
|
|||||||
title: "Super Graph",
|
title: "Super Graph",
|
||||||
logo: {
|
logo: {
|
||||||
alt: "Super Graph Logo",
|
alt: "Super Graph Logo",
|
||||||
src: "img/favicon.png",
|
src: "img/super-graph-logo.svg",
|
||||||
},
|
},
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
@ -56,13 +56,13 @@ module.exports = {
|
|||||||
sidebarPath: require.resolve("./sidebars.js"),
|
sidebarPath: require.resolve("./sidebars.js"),
|
||||||
// Please change this to your repo.
|
// Please change this to your repo.
|
||||||
editUrl:
|
editUrl:
|
||||||
"https://github.com/facebook/docusaurus/edit/master/website/",
|
"https://github.com/dosco/super-graph/edit/master/docs/website",
|
||||||
},
|
},
|
||||||
blog: {
|
blog: {
|
||||||
showReadingTime: true,
|
showReadingTime: true,
|
||||||
// Please change this to your repo.
|
// Please change this to your repo.
|
||||||
editUrl:
|
editUrl:
|
||||||
"https://github.com/facebook/docusaurus/edit/master/website/blog/",
|
"https://github.com/dosco/super-graph/edit/master/docs/website",
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
customCss: require.resolve("./src/css/custom.css"),
|
customCss: require.resolve("./src/css/custom.css"),
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
@ -2,7 +2,7 @@
|
|||||||
<svg width="378px" height="314px" viewBox="0 0 378 314" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="378px" height="314px" viewBox="0 0 378 314" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<title>battery-technology-svgrepo-com</title>
|
<title>battery-technology-svgrepo-com</title>
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
<g id="battery-technology-svgrepo-com" fill="#000000" fill-rule="nonzero">
|
<g id="battery-technology-svgrepo-com" fill="#444AA9" fill-rule="nonzero">
|
||||||
<path d="M234,269.076 L210,269.076 C196.8,269.076 186,258.276 186,245.076 L186,69.076 C186,55.876 196.8,45.076 210,45.076 L370,45.076 C374.4,45.076 378,41.476 378,37.076 C378,32.676 374.4,29.076 370,29.076 L210,29.076 C188,29.076 170,47.076 170,69.076 L170,245.076 C170,267.076 188,285.076 210,285.076 L234,285.076 C238.4,285.076 242,281.476 242,277.076 C242,272.676 238.4,269.076 234,269.076 Z" id="Path" transform="translate(274.000000, 157.076000) scale(-1, -1) translate(-274.000000, -157.076000) "></path>
|
<path d="M234,269.076 L210,269.076 C196.8,269.076 186,258.276 186,245.076 L186,69.076 C186,55.876 196.8,45.076 210,45.076 L370,45.076 C374.4,45.076 378,41.476 378,37.076 C378,32.676 374.4,29.076 370,29.076 L210,29.076 C188,29.076 170,47.076 170,69.076 L170,245.076 C170,267.076 188,285.076 210,285.076 L234,285.076 C238.4,285.076 242,281.476 242,277.076 C242,272.676 238.4,269.076 234,269.076 Z" id="Path" transform="translate(274.000000, 157.076000) scale(-1, -1) translate(-274.000000, -157.076000) "></path>
|
||||||
<path d="M64,269.076 L40,269.076 C26.8,269.076 16,258.276 16,245.076 L16,69.076 C16,55.876 26.8,45.076 40,45.076 L200,45.076 C204.4,45.076 208,41.476 208,37.076 C208,32.676 204.4,29.076 200,29.076 L40,29.076 C18,29.076 0,47.076 0,69.076 L0,245.076 C0,267.076 18,285.076 40,285.076 L64,285.076 C68.4,285.076 72,281.476 72,277.076 C72,272.676 68.4,269.076 64,269.076 Z" id="Path"></path>
|
<path d="M64,269.076 L40,269.076 C26.8,269.076 16,258.276 16,245.076 L16,69.076 C16,55.876 26.8,45.076 40,45.076 L200,45.076 C204.4,45.076 208,41.476 208,37.076 C208,32.676 204.4,29.076 200,29.076 L40,29.076 C18,29.076 0,47.076 0,69.076 L0,245.076 C0,267.076 18,285.076 40,285.076 L64,285.076 C68.4,285.076 72,281.476 72,277.076 C72,272.676 68.4,269.076 64,269.076 Z" id="Path"></path>
|
||||||
<path d="M196,269.076 L184,269.076 C179.6,269.076 176,272.676 176,277.076 C176,281.476 179.6,285.076 184,285.076 L196,285.076 C200.4,285.076 204,281.476 204,277.076 C204,272.676 200.4,269.076 196,269.076 Z" id="Path"></path>
|
<path d="M196,269.076 L184,269.076 C179.6,269.076 176,272.676 176,277.076 C176,281.476 179.6,285.076 184,285.076 L196,285.076 C200.4,285.076 204,281.476 204,277.076 C204,272.676 200.4,269.076 196,269.076 Z" id="Path"></path>
|
||||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
7
go.mod
7
go.mod
@ -1,6 +1,11 @@
|
|||||||
module github.com/dosco/super-graph
|
module github.com/dosco/super-graph
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
contrib.go.opencensus.io/exporter/aws v0.0.0-20190807220307-c50fb1bd7f21
|
||||||
|
contrib.go.opencensus.io/exporter/prometheus v0.1.0
|
||||||
|
contrib.go.opencensus.io/exporter/stackdriver v0.13.1
|
||||||
|
contrib.go.opencensus.io/exporter/zipkin v0.1.1
|
||||||
|
contrib.go.opencensus.io/integrations/ocsql v0.1.6
|
||||||
github.com/DATA-DOG/go-sqlmock v1.4.1
|
github.com/DATA-DOG/go-sqlmock v1.4.1
|
||||||
github.com/GeertJohan/go.rice v1.0.0
|
github.com/GeertJohan/go.rice v1.0.0
|
||||||
github.com/NYTimes/gziphandler v1.1.1
|
github.com/NYTimes/gziphandler v1.1.1
|
||||||
@ -21,6 +26,7 @@ require (
|
|||||||
github.com/jackc/pgtype v1.3.0
|
github.com/jackc/pgtype v1.3.0
|
||||||
github.com/jackc/pgx/v4 v4.6.0
|
github.com/jackc/pgx/v4 v4.6.0
|
||||||
github.com/mitchellh/mapstructure v1.2.2 // indirect
|
github.com/mitchellh/mapstructure v1.2.2 // indirect
|
||||||
|
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/rs/cors v1.7.0
|
github.com/rs/cors v1.7.0
|
||||||
@ -32,6 +38,7 @@ require (
|
|||||||
github.com/spf13/viper v1.6.3
|
github.com/spf13/viper v1.6.3
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
github.com/valyala/fasttemplate v1.1.0
|
github.com/valyala/fasttemplate v1.1.0
|
||||||
|
go.opencensus.io v0.22.3
|
||||||
go.uber.org/zap v1.14.1
|
go.uber.org/zap v1.14.1
|
||||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904
|
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904
|
||||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
|
||||||
|
167
go.sum
167
go.sum
@ -1,6 +1,25 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0=
|
||||||
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
contrib.go.opencensus.io/exporter/aws v0.0.0-20190807220307-c50fb1bd7f21 h1:H3O7Pfgex4O08w1PyXje7lhiRbPNd687lz48jfWWB1s=
|
||||||
|
contrib.go.opencensus.io/exporter/aws v0.0.0-20190807220307-c50fb1bd7f21/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
|
||||||
|
contrib.go.opencensus.io/exporter/prometheus v0.1.0 h1:SByaIoWwNgMdPSgl5sMqM2KDE5H/ukPWBRo314xiDvg=
|
||||||
|
contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A=
|
||||||
|
contrib.go.opencensus.io/exporter/stackdriver v0.13.1 h1:RX9W6FelAqTVnBi/bRXJLXr9n18v4QkQwZYIdnNS51I=
|
||||||
|
contrib.go.opencensus.io/exporter/stackdriver v0.13.1/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c=
|
||||||
|
contrib.go.opencensus.io/exporter/zipkin v0.1.1 h1:PR+1zWqY8ceXs1qDQQIlgXe+sdiwCf0n32bH4+Epk8g=
|
||||||
|
contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
|
||||||
|
contrib.go.opencensus.io/integrations/ocsql v0.1.6 h1:9qmZJBlnMtffShflmfhW4EZK7M+CujIDG4bEwUrg+ms=
|
||||||
|
contrib.go.opencensus.io/integrations/ocsql v0.1.6/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM=
|
github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg=
|
github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg=
|
||||||
@ -10,6 +29,8 @@ github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtix
|
|||||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3 h1:+qz9Ga6l6lKw6fgvk5RMV5HQznSLvI8Zxajwdj4FhFg=
|
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3 h1:+qz9Ga6l6lKw6fgvk5RMV5HQznSLvI8Zxajwdj4FhFg=
|
||||||
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=
|
||||||
@ -17,12 +38,19 @@ github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkK
|
|||||||
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/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/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||||
|
github.com/aws/aws-sdk-go v1.23.20 h1:2CBuL21P0yKdZN5urf2NxKa1ha8fhnY+A3pBCHFeZoA=
|
||||||
|
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
|
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||||
github.com/brianvoe/gofakeit/v5 v5.2.0 h1:De9X+2PQum9U2zCaIDxLV7wx0YBL6c7RN2sFBImzHGI=
|
github.com/brianvoe/gofakeit/v5 v5.2.0 h1:De9X+2PQum9U2zCaIDxLV7wx0YBL6c7RN2sFBImzHGI=
|
||||||
github.com/brianvoe/gofakeit/v5 v5.2.0/go.mod h1:/ZENnKqX+XrN8SORLe/fu5lZDIo1tuPncWuRD+eyhSI=
|
github.com/brianvoe/gofakeit/v5 v5.2.0/go.mod h1:/ZENnKqX+XrN8SORLe/fu5lZDIo1tuPncWuRD+eyhSI=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||||
@ -57,6 +85,10 @@ 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/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/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||||
github.com/friendsofgo/graphiql v0.2.2/go.mod h1:8Y2kZ36AoTGWs78+VRpvATyt3LJBx0SZXmay80ZTRWo=
|
github.com/friendsofgo/graphiql v0.2.2/go.mod h1:8Y2kZ36AoTGWs78+VRpvATyt3LJBx0SZXmay80ZTRWo=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
@ -65,6 +97,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
|
|||||||
github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=
|
github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=
|
||||||
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo=
|
||||||
|
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
@ -75,19 +109,41 @@ github.com/gobuffalo/flect v0.2.1 h1:GPoRjEN0QObosV4XwuoWvSd5uSiL0N3e91/xqyY4crQ
|
|||||||
github.com/gobuffalo/flect v0.2.1/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc=
|
github.com/gobuffalo/flect v0.2.1/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc=
|
||||||
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
||||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
|
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
@ -96,8 +152,11 @@ github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4
|
|||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||||
@ -144,8 +203,13 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f
|
|||||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
@ -164,6 +228,7 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
|||||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||||
@ -176,6 +241,7 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
|||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
@ -189,30 +255,47 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
|
|||||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg=
|
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg=
|
||||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
|
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
|
github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=
|
||||||
|
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
|
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
|
||||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||||
|
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||||
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||||
|
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
|
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
|
||||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
|
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
|
||||||
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||||
@ -261,6 +344,7 @@ github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
|||||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||||
github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs=
|
github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs=
|
||||||
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
|
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
|
||||||
|
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
@ -291,6 +375,12 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
|
|||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
|
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
|
||||||
|
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||||
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
|
||||||
@ -309,43 +399,74 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90Pveol
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8=
|
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8=
|
||||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
|
||||||
|
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
|
||||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -354,17 +475,29 @@ golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HX
|
|||||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@ -377,10 +510,37 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
|||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.10.0 h1:7tmAxx3oKE98VMZ+SBZzvYYWRQ9HODBxmC8mXUsraSQ=
|
||||||
|
google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.2 h1:j8RI1yW0SkI+paT6uGwMlrMI/6zwYA6/CFil8rxOzGI=
|
||||||
|
google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51 h1:Ex1mq5jaJof+kRnYi3SlYJ8KKa9Ao3NHyIT5XJ1gF6U=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
|
||||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.0/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/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
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=
|
||||||
@ -389,12 +549,14 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
|
gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
|
||||||
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
@ -402,7 +564,12 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099 h1:XJP7lxbSxWLOMNdBE4B/STaqVy6L73o0knwj2vIlxnw=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099 h1:XJP7lxbSxWLOMNdBE4B/STaqVy6L73o0knwj2vIlxnw=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
@ -24,8 +24,10 @@ type Config struct {
|
|||||||
Core `mapstructure:",squash"`
|
Core `mapstructure:",squash"`
|
||||||
Serv `mapstructure:",squash"`
|
Serv `mapstructure:",squash"`
|
||||||
|
|
||||||
cpath string
|
closeFn func()
|
||||||
vi *viper.Viper
|
hostPort string
|
||||||
|
cpath string
|
||||||
|
vi *viper.Viper
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serv struct contains config values used by the Super Graph service
|
// Serv struct contains config values used by the Super Graph service
|
||||||
@ -48,9 +50,30 @@ type Serv struct {
|
|||||||
APIPath string `mapstructure:"api_path"`
|
APIPath string `mapstructure:"api_path"`
|
||||||
CacheControl string `mapstructure:"cache_control"`
|
CacheControl string `mapstructure:"cache_control"`
|
||||||
|
|
||||||
|
// Telemetry struct contains OpenCensus metrics and tracing related config
|
||||||
|
Telemetry struct {
|
||||||
|
Debug bool
|
||||||
|
Interval *time.Duration
|
||||||
|
Metrics struct {
|
||||||
|
Exporter string
|
||||||
|
Endpoint string
|
||||||
|
Namespace string
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
Tracing struct {
|
||||||
|
Exporter string
|
||||||
|
Endpoint string
|
||||||
|
Sample string
|
||||||
|
IncludeQuery bool `mapstructure:"include_query"`
|
||||||
|
IncludeParams bool `mapstructure:"include_params"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Auth auth.Auth
|
Auth auth.Auth
|
||||||
Auths []auth.Auth
|
Auths []auth.Auth
|
||||||
|
|
||||||
|
// DB struct contains db config
|
||||||
DB struct {
|
DB struct {
|
||||||
Type string
|
Type string
|
||||||
Host string
|
Host string
|
||||||
|
@ -19,8 +19,8 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// These variables are set using -ldflags
|
// These variables are set using -ldflags
|
||||||
version string
|
version string = "unknown"
|
||||||
gitBranch string
|
gitBranch string = "unknown"
|
||||||
lastCommitSHA string
|
lastCommitSHA string
|
||||||
lastCommitTime string
|
lastCommitTime string
|
||||||
)
|
)
|
||||||
|
@ -55,7 +55,7 @@ func cmdDBReset(cmd *cobra.Command, args []string) {
|
|||||||
func cmdDBCreate(cmd *cobra.Command, args []string) {
|
func cmdDBCreate(cmd *cobra.Command, args []string) {
|
||||||
initConfOnce()
|
initConfOnce()
|
||||||
|
|
||||||
db, err := initDB(conf, false)
|
db, err := initDB(conf, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("ERR failed to connect to database: %s", err)
|
log.Fatalf("ERR failed to connect to database: %s", err)
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ func cmdDBCreate(cmd *cobra.Command, args []string) {
|
|||||||
func cmdDBDrop(cmd *cobra.Command, args []string) {
|
func cmdDBDrop(cmd *cobra.Command, args []string) {
|
||||||
initConfOnce()
|
initConfOnce()
|
||||||
|
|
||||||
db, err := initDB(conf, false)
|
db, err := initDB(conf, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("ERR failed to connect to database: %s", err)
|
log.Fatalf("ERR failed to connect to database: %s", err)
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ func cmdDBMigrate(cmd *cobra.Command, args []string) {
|
|||||||
initConfOnce()
|
initConfOnce()
|
||||||
dest := args[0]
|
dest := args[0]
|
||||||
|
|
||||||
conn, err := initDB(conf, true)
|
conn, err := initDB(conf, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("ERR failed to connect to database: %s", err)
|
log.Fatalf("ERR failed to connect to database: %s", err)
|
||||||
}
|
}
|
||||||
@ -224,7 +224,7 @@ func cmdDBMigrate(cmd *cobra.Command, args []string) {
|
|||||||
func cmdDBStatus(cmd *cobra.Command, args []string) {
|
func cmdDBStatus(cmd *cobra.Command, args []string) {
|
||||||
initConfOnce()
|
initConfOnce()
|
||||||
|
|
||||||
db, err := initDB(conf, true)
|
db, err := initDB(conf, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("ERR failed to connect to database: %s", err)
|
log.Fatalf("ERR failed to connect to database: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,9 @@ func cmdDBSeed(cmd *cobra.Command, args []string) {
|
|||||||
if conf, err = initConf(); err != nil {
|
if conf, err = initConf(); err != nil {
|
||||||
log.Fatalf("ERR failed to read config: %s", err)
|
log.Fatalf("ERR failed to read config: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Production = false
|
conf.Production = false
|
||||||
|
|
||||||
db, err = initDB(conf, true)
|
db, err = initDB(conf, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("ERR failed to connect to database: %s", err)
|
log.Fatalf("ERR failed to connect to database: %s", err)
|
||||||
}
|
}
|
||||||
@ -80,6 +79,8 @@ func graphQLFunc(sg *core.SuperGraph, query string, data interface{}, opt map[st
|
|||||||
|
|
||||||
if v, ok := opt["user_id"]; ok && len(v) != 0 {
|
if v, ok := opt["user_id"]; ok && len(v) != 0 {
|
||||||
ct = context.WithValue(ct, core.UserIDKey, v)
|
ct = context.WithValue(ct, core.UserIDKey, v)
|
||||||
|
} else {
|
||||||
|
ct = context.WithValue(ct, core.UserIDKey, "-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
// var role string
|
// var role string
|
||||||
@ -349,7 +350,6 @@ func setFakeFuncs(f *goja.Object) {
|
|||||||
f.Set("credit_card", gofakeit.CreditCard)
|
f.Set("credit_card", gofakeit.CreditCard)
|
||||||
f.Set("credit_card_cvv", gofakeit.CreditCardCvv)
|
f.Set("credit_card_cvv", gofakeit.CreditCardCvv)
|
||||||
f.Set("credit_card_number", gofakeit.CreditCardNumber)
|
f.Set("credit_card_number", gofakeit.CreditCardNumber)
|
||||||
f.Set("credit_card_number_luhn", gofakeit.CreditCardNumberLuhn)
|
|
||||||
f.Set("credit_card_type", gofakeit.CreditCardType)
|
f.Set("credit_card_type", gofakeit.CreditCardType)
|
||||||
f.Set("currency", gofakeit.Currency)
|
f.Set("currency", gofakeit.Currency)
|
||||||
f.Set("currency_long", gofakeit.CurrencyLong)
|
f.Set("currency_long", gofakeit.CurrencyLong)
|
||||||
@ -368,7 +368,6 @@ func setFakeFuncs(f *goja.Object) {
|
|||||||
// Hacker
|
// Hacker
|
||||||
f.Set("hacker_abbreviation", gofakeit.HackerAbbreviation)
|
f.Set("hacker_abbreviation", gofakeit.HackerAbbreviation)
|
||||||
f.Set("hacker_adjective", gofakeit.HackerAdjective)
|
f.Set("hacker_adjective", gofakeit.HackerAdjective)
|
||||||
f.Set("hacker_ingverb", gofakeit.HackerIngverb)
|
|
||||||
f.Set("hacker_noun", gofakeit.HackerNoun)
|
f.Set("hacker_noun", gofakeit.HackerNoun)
|
||||||
f.Set("hacker_phrase", gofakeit.HackerPhrase)
|
f.Set("hacker_phrase", gofakeit.HackerPhrase)
|
||||||
f.Set("hacker_verb", gofakeit.HackerVerb)
|
f.Set("hacker_verb", gofakeit.HackerVerb)
|
||||||
|
@ -19,7 +19,7 @@ func cmdServ(cmd *cobra.Command, args []string) {
|
|||||||
|
|
||||||
initWatcher()
|
initWatcher()
|
||||||
|
|
||||||
db, err = initDB(conf, true)
|
db, err = initDB(conf, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalInProd(err, "failed to connect to database")
|
fatalInProd(err, "failed to connect to database")
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,10 @@ func GetConfigName() string {
|
|||||||
return ge
|
return ge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) telemetryEnabled() bool {
|
||||||
|
return c.Telemetry.Debug || c.Telemetry.Metrics.Exporter != "" || c.Telemetry.Tracing.Exporter != ""
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) relPath(p string) string {
|
func (c *Config) relPath(p string) string {
|
||||||
if filepath.IsAbs(p) {
|
if filepath.IsAbs(p) {
|
||||||
return p
|
return p
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package serv
|
|
||||||
|
|
||||||
// func (c *coreContext) handleReq(w io.Writer, req *http.Request) error {
|
|
||||||
|
|
||||||
// return nil
|
|
||||||
|
|
||||||
// }
|
|
@ -10,6 +10,8 @@ import (
|
|||||||
"github.com/dosco/super-graph/core"
|
"github.com/dosco/super-graph/core"
|
||||||
"github.com/dosco/super-graph/internal/serv/internal/auth"
|
"github.com/dosco/super-graph/internal/serv/internal/auth"
|
||||||
"github.com/rs/cors"
|
"github.com/rs/cors"
|
||||||
|
"go.opencensus.io/plugin/ochttp"
|
||||||
|
"go.opencensus.io/trace"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ func apiV1Handler() http.Handler {
|
|||||||
AllowCredentials: true,
|
AllowCredentials: true,
|
||||||
Debug: conf.DebugCORS,
|
Debug: conf.DebugCORS,
|
||||||
})
|
})
|
||||||
h = c.Handler(h)
|
return c.Handler(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
return h
|
return h
|
||||||
@ -78,6 +80,22 @@ 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.telemetryEnabled() {
|
||||||
|
span := trace.FromContext(ct)
|
||||||
|
|
||||||
|
span.AddAttributes(
|
||||||
|
trace.StringAttribute("operation", res.OperationName()),
|
||||||
|
trace.StringAttribute("query_name", res.QueryName()),
|
||||||
|
trace.StringAttribute("role", res.Role()),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
span.AddAttributes(trace.StringAttribute("error", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
ochttp.SetRoute(ct, apiRoute)
|
||||||
|
}
|
||||||
|
|
||||||
if !conf.Production && res.QueryName() == introspectionQuery {
|
if !conf.Production && res.QueryName() == introspectionQuery {
|
||||||
doLog = false
|
doLog = false
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"contrib.go.opencensus.io/integrations/ocsql"
|
||||||
"github.com/jackc/pgx/v4"
|
"github.com/jackc/pgx/v4"
|
||||||
"github.com/jackc/pgx/v4/stdlib"
|
"github.com/jackc/pgx/v4/stdlib"
|
||||||
//_ "github.com/jackc/pgx/v4/stdlib"
|
//_ "github.com/jackc/pgx/v4/stdlib"
|
||||||
@ -45,6 +46,16 @@ func initConf() (*Config, error) {
|
|||||||
logLevel = LogLevelNone
|
logLevel = LogLevelNone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy over db_schema from the core config
|
||||||
|
if c.DB.Schema == "" {
|
||||||
|
c.DB.Schema = c.DBSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
// set default database schema
|
||||||
|
if c.DB.Schema == "" {
|
||||||
|
c.DB.Schema = "public"
|
||||||
|
}
|
||||||
|
|
||||||
// Auths: validate and sanitize
|
// Auths: validate and sanitize
|
||||||
am := make(map[string]struct{})
|
am := make(map[string]struct{})
|
||||||
|
|
||||||
@ -100,13 +111,10 @@ func initConf() (*Config, error) {
|
|||||||
c.UseAllowList = true
|
c.UseAllowList = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// In anon role block all tables that are not defined in the role
|
|
||||||
c.DefaultBlock = true
|
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initDB(c *Config, useDB bool) (*sql.DB, error) {
|
func initDB(c *Config, useDB, useTelemetry bool) (*sql.DB, error) {
|
||||||
var db *sql.DB
|
var db *sql.DB
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -200,16 +208,56 @@ func initDB(c *Config, useDB bool) (*sql.DB, error) {
|
|||||||
// config.MaxConns = conf.DB.PoolSize
|
// config.MaxConns = conf.DB.PoolSize
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for i := 1; i < 10; i++ {
|
connString := stdlib.RegisterConnConfig(config)
|
||||||
db = stdlib.OpenDB(*config)
|
driverName := "pgx"
|
||||||
if db == nil {
|
// if db = stdlib.OpenDB(*config); db == nil {
|
||||||
break
|
// return errors.New("failed to open db")
|
||||||
|
// }
|
||||||
|
|
||||||
|
if useTelemetry && conf.telemetryEnabled() {
|
||||||
|
opts := ocsql.TraceOptions{
|
||||||
|
AllowRoot: false,
|
||||||
|
Ping: true,
|
||||||
|
RowsNext: true,
|
||||||
|
RowsClose: true,
|
||||||
|
RowsAffected: true,
|
||||||
|
LastInsertID: true,
|
||||||
|
Query: conf.Telemetry.Tracing.IncludeQuery,
|
||||||
|
QueryParams: conf.Telemetry.Tracing.IncludeParams,
|
||||||
}
|
}
|
||||||
|
opt := ocsql.WithOptions(opts)
|
||||||
|
name := ocsql.WithInstanceName(conf.AppName)
|
||||||
|
|
||||||
|
driverName, err = ocsql.Register(driverName, opt, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to register ocsql driver: %v", err)
|
||||||
|
}
|
||||||
|
ocsql.RegisterAllViews()
|
||||||
|
|
||||||
|
var interval time.Duration
|
||||||
|
|
||||||
|
if conf.Telemetry.Interval != nil {
|
||||||
|
interval = *conf.Telemetry.Interval
|
||||||
|
} else {
|
||||||
|
interval = 5 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
defer ocsql.RecordStats(db, interval)()
|
||||||
|
|
||||||
|
log.Println("INF OpenCensus telemetry enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i < 10; i++ {
|
||||||
|
db, err = sql.Open(driverName, connString)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
time.Sleep(time.Duration(i*100) * time.Millisecond)
|
time.Sleep(time.Duration(i*100) * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("unable to open db connection: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return db, nil
|
return db, nil
|
||||||
|
File diff suppressed because one or more lines are too long
@ -13,6 +13,11 @@ import (
|
|||||||
rice "github.com/GeertJohan/go.rice"
|
rice "github.com/GeertJohan/go.rice"
|
||||||
"github.com/NYTimes/gziphandler"
|
"github.com/NYTimes/gziphandler"
|
||||||
"github.com/dosco/super-graph/internal/serv/internal/auth"
|
"github.com/dosco/super-graph/internal/serv/internal/auth"
|
||||||
|
"go.opencensus.io/plugin/ochttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
apiRoute string = "/api/v1/graphql"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initWatcher() {
|
func initWatcher() {
|
||||||
@ -37,7 +42,6 @@ func initWatcher() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startHTTP() {
|
func startHTTP() {
|
||||||
var hostPort string
|
|
||||||
var appName string
|
var appName string
|
||||||
|
|
||||||
defaultHP := "0.0.0.0:8080"
|
defaultHP := "0.0.0.0:8080"
|
||||||
@ -56,12 +60,12 @@ func startHTTP() {
|
|||||||
hp[1] = conf.Port
|
hp[1] = conf.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
hostPort = fmt.Sprintf("%s:%s", hp[0], hp[1])
|
conf.hostPort = fmt.Sprintf("%s:%s", hp[0], hp[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(hostPort) == 0 {
|
if len(conf.hostPort) == 0 {
|
||||||
hostPort = defaultHP
|
conf.hostPort = defaultHP
|
||||||
}
|
}
|
||||||
|
|
||||||
routes, err := routeHandler()
|
routes, err := routeHandler()
|
||||||
@ -70,13 +74,17 @@ func startHTTP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
Addr: hostPort,
|
Addr: conf.hostPort,
|
||||||
Handler: routes,
|
Handler: routes,
|
||||||
ReadTimeout: 5 * time.Second,
|
ReadTimeout: 5 * time.Second,
|
||||||
WriteTimeout: 10 * time.Second,
|
WriteTimeout: 10 * time.Second,
|
||||||
MaxHeaderBytes: 1 << 20,
|
MaxHeaderBytes: 1 << 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.telemetryEnabled() {
|
||||||
|
srv.Handler = &ochttp.Handler{Handler: routes}
|
||||||
|
}
|
||||||
|
|
||||||
idleConnsClosed := make(chan struct{})
|
idleConnsClosed := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
sigint := make(chan os.Signal, 1)
|
sigint := make(chan os.Signal, 1)
|
||||||
@ -90,13 +98,15 @@ func startHTTP() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
srv.RegisterOnShutdown(func() {
|
srv.RegisterOnShutdown(func() {
|
||||||
|
if conf.closeFn != nil {
|
||||||
|
conf.closeFn()
|
||||||
|
}
|
||||||
db.Close()
|
db.Close()
|
||||||
|
log.Fatalln("INF shutdown complete")
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Printf("INF version: %s, git-branch: %s, host-port: %s, app-name: %s, env: %s\n",
|
log.Printf("INF Super Graph started, version: %s, git-branch: %s, host-port: %s, app-name: %s, env: %s\n",
|
||||||
version, gitBranch, hostPort, appName, env)
|
version, gitBranch, conf.hostPort, appName, env)
|
||||||
|
|
||||||
log.Printf("INF %s started\n", serverName)
|
|
||||||
|
|
||||||
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
||||||
log.Fatalln("INF server closed")
|
log.Fatalln("INF server closed")
|
||||||
@ -106,14 +116,13 @@ func startHTTP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func routeHandler() (http.Handler, error) {
|
func routeHandler() (http.Handler, error) {
|
||||||
|
var err error
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
return mux, nil
|
return mux, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
apiRoute := "/api/v1/graphql"
|
|
||||||
|
|
||||||
if len(conf.APIPath) != 0 {
|
if len(conf.APIPath) != 0 {
|
||||||
apiRoute = path.Join("/", conf.APIPath, "/v1/graphql")
|
apiRoute = path.Join("/", conf.APIPath, "/v1/graphql")
|
||||||
}
|
}
|
||||||
@ -142,6 +151,13 @@ func routeHandler() (http.Handler, error) {
|
|||||||
mux.Handle(k, v)
|
mux.Handle(k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.telemetryEnabled() {
|
||||||
|
conf.closeFn, err = enableObservability(mux)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Server", serverName)
|
w.Header().Set("Server", serverName)
|
||||||
mux.ServeHTTP(w, r)
|
mux.ServeHTTP(w, r)
|
||||||
@ -169,6 +185,10 @@ func setActionRoutes(routes map[string]http.Handler) error {
|
|||||||
routes[p] = fn
|
routes[p] = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.telemetryEnabled() {
|
||||||
|
routes[p] = ochttp.WithRouteTag(routes[p], p)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
141
internal/serv/telemetry.go
Normal file
141
internal/serv/telemetry.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package serv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"contrib.go.opencensus.io/exporter/aws"
|
||||||
|
"contrib.go.opencensus.io/exporter/prometheus"
|
||||||
|
"contrib.go.opencensus.io/exporter/stackdriver"
|
||||||
|
|
||||||
|
"contrib.go.opencensus.io/exporter/zipkin"
|
||||||
|
"contrib.go.opencensus.io/integrations/ocsql"
|
||||||
|
stdzipkin "github.com/openzipkin/zipkin-go"
|
||||||
|
httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
|
||||||
|
"go.opencensus.io/stats/view"
|
||||||
|
"go.opencensus.io/trace"
|
||||||
|
"go.opencensus.io/zpages"
|
||||||
|
)
|
||||||
|
|
||||||
|
func enableObservability(mux *http.ServeMux) (func(), error) {
|
||||||
|
// Enable OpenCensus zPages
|
||||||
|
if conf.Telemetry.Debug {
|
||||||
|
zpages.Handle(mux, "/telemetry")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable ocsql metrics with OpenCensus
|
||||||
|
ocsql.RegisterAllViews()
|
||||||
|
|
||||||
|
var mex view.Exporter
|
||||||
|
var tex trace.Exporter
|
||||||
|
|
||||||
|
var mCloseFn, tCloseFn func()
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Set up the metrics exporter
|
||||||
|
switch conf.Telemetry.Metrics.Exporter {
|
||||||
|
case "prometheus":
|
||||||
|
ep := "/metrics"
|
||||||
|
|
||||||
|
if conf.Telemetry.Metrics.Endpoint != "" {
|
||||||
|
ep = conf.Telemetry.Metrics.Endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
ex, err1 := prometheus.NewExporter(prometheus.Options{Namespace: conf.Telemetry.Metrics.Namespace})
|
||||||
|
if err == nil {
|
||||||
|
mux.Handle(ep, ex)
|
||||||
|
log.Printf("INF Prometheus exporter listening on: %s", ep)
|
||||||
|
}
|
||||||
|
mex, err = view.Exporter(ex), err1
|
||||||
|
|
||||||
|
case "stackdriver":
|
||||||
|
mex, err = stackdriver.NewExporter(stackdriver.Options{ProjectID: conf.Telemetry.Metrics.Key})
|
||||||
|
if err == nil {
|
||||||
|
log.Println("INF Google Stackdriver exporter initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
case "":
|
||||||
|
log.Println("WRN OpenCensus: no metrics exporter defined")
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid metrics exporter")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("ERR OpenCensus: %s: %v", conf.Telemetry.Metrics, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mex != nil {
|
||||||
|
// Register the exporter
|
||||||
|
view.RegisterExporter(mex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the tracing exporter
|
||||||
|
switch conf.Telemetry.Tracing.Exporter {
|
||||||
|
case "xray", "aws":
|
||||||
|
ex, err1 := aws.NewExporter(aws.WithVersion("latest"))
|
||||||
|
if err == nil {
|
||||||
|
tCloseFn = func() { ex.Flush() }
|
||||||
|
log.Println("INF Amazon X-Ray exporter initialized")
|
||||||
|
}
|
||||||
|
tex, err = trace.Exporter(ex), err1
|
||||||
|
|
||||||
|
case "zipkin":
|
||||||
|
// The local endpoint stores the name and address of the local service
|
||||||
|
lep, err := stdzipkin.NewEndpoint(conf.AppName, conf.hostPort)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Zipkin reporter takes collected spans from the app and reports them to the backend
|
||||||
|
// http://localhost:9411/api/v2/spans is the default for the Zipkin Span v2
|
||||||
|
re := httpreporter.NewReporter(conf.Telemetry.Tracing.Endpoint)
|
||||||
|
tCloseFn = func() { re.Close() }
|
||||||
|
tex = zipkin.NewExporter(re, lep)
|
||||||
|
|
||||||
|
case "":
|
||||||
|
log.Println("WRN OpenCensus: no traceing exporter defined")
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid tracing exporter")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("ERR OpenCensus: %s: %v",
|
||||||
|
conf.Telemetry.Tracing.Exporter,
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tex != nil {
|
||||||
|
trace.RegisterExporter(tex)
|
||||||
|
sample := conf.Telemetry.Tracing.Sample
|
||||||
|
|
||||||
|
if sample == "always" {
|
||||||
|
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
prob := 0.5
|
||||||
|
if v, err := strconv.ParseFloat(sample, 10); err == nil {
|
||||||
|
prob = v
|
||||||
|
}
|
||||||
|
trace.ApplyConfig(trace.Config{DefaultSampler: trace.ProbabilitySampler(prob)})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var closeOnce sync.Once
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
// Flush and shutdown the Zipkin HTTP reporter
|
||||||
|
closeOnce.Do(func() {
|
||||||
|
if mCloseFn != nil {
|
||||||
|
mCloseFn()
|
||||||
|
}
|
||||||
|
if tCloseFn != nil {
|
||||||
|
tCloseFn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, err
|
||||||
|
}
|
@ -69,6 +69,16 @@ cors_debug: false
|
|||||||
# person: people
|
# person: people
|
||||||
# sheep: sheep
|
# sheep: sheep
|
||||||
|
|
||||||
|
# open opencensus tracing and metrics
|
||||||
|
# telemetry:
|
||||||
|
# debug: true
|
||||||
|
# metrics:
|
||||||
|
# exporter: "prometheus"
|
||||||
|
# tracing:
|
||||||
|
# exporter: "zipkin"
|
||||||
|
# endpoint: "http://zipkin:9411/api/v2/spans"
|
||||||
|
# sample: 0.6
|
||||||
|
|
||||||
auth:
|
auth:
|
||||||
# Can be 'rails', 'jwt' or 'header'
|
# Can be 'rails', 'jwt' or 'header'
|
||||||
type: rails
|
type: rails
|
||||||
|
@ -68,6 +68,16 @@ reload_on_config_change: false
|
|||||||
# SG_AUTH_RAILS_REDIS_PASSWORD
|
# SG_AUTH_RAILS_REDIS_PASSWORD
|
||||||
# SG_AUTH_JWT_PUBLIC_KEY_FILE
|
# SG_AUTH_JWT_PUBLIC_KEY_FILE
|
||||||
|
|
||||||
|
# open opencensus tracing and metrics
|
||||||
|
# telemetry:
|
||||||
|
# debug: false
|
||||||
|
# metrics:
|
||||||
|
# exporter: "prometheus"
|
||||||
|
# tracing:
|
||||||
|
# exporter: "zipkin"
|
||||||
|
# endpoint: "http://zipkin:9411/api/v2/spans"
|
||||||
|
# sample: 0.6
|
||||||
|
|
||||||
database:
|
database:
|
||||||
type: postgres
|
type: postgres
|
||||||
host: db
|
host: db
|
||||||
|
@ -3,6 +3,8 @@ package serv
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/brianvoe/gofakeit/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGQLHash1(t *testing.T) {
|
func TestGQLHash1(t *testing.T) {
|
||||||
@ -229,3 +231,7 @@ func TestGQLHashWithVars2(t *testing.T) {
|
|||||||
t.Fatal("Hashes don't match they should")
|
t.Fatal("Hashes don't match they should")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGoFake(t *testing.T) {
|
||||||
|
gofakeit.Person()
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user