Compare commits

...

5 Commits

14 changed files with 214 additions and 84 deletions

View File

@ -7,7 +7,7 @@
![Docker build](https://img.shields.io/docker/cloud/build/dosco/super-graph.svg?style=flat-square)
[![Discord Chat](https://img.shields.io/discord/628796009539043348.svg)](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

View File

@ -8,7 +8,7 @@ log_level: "debug"
# enable or disable http compression (uses gzip)
http_compress: true
# When production mode is 'true' only queries
# When production mode is 'true' only queries
# from the allow list are permitted.
# When it's 'false' all queries are saved to the
# 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
migrations_path: ./migrations
# Secret key for general encryption operations like
# Secret key for general encryption operations like
# encrypting the cursor data
secret_key: supercalifajalistics
# 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.
# An origin may contain a wildcard (*) to replace 0 or more
# 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.
# An origin may contain a wildcard (*) to replace 0 or more
# characters (i.e.: http://*.domain.com).
cors_allowed_origins: ["*"]
@ -48,8 +48,8 @@ cors_debug: true
# Default API path prefix is /api you can change it if you like
# api_path: "/data"
# Cache-Control header can help cache queries if your CDN supports cache-control
# on POST requests (does not work with not mutations)
# Cache-Control header can help cache queries if your CDN supports cache-control
# on POST requests (does not work with not mutations)
# cache_control: "public, max-age=300, s-maxage=600"
# Postgres related environment Variables
@ -68,13 +68,17 @@ cors_debug: true
# person: people
# sheep: sheep
# open opencensus tracing and metrics
telemetry:
enable: false
auth:
# Can be 'rails' or 'jwt'
type: rails
cookie: _app_session
# 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
creds_in_header: true
@ -91,7 +95,6 @@ auth:
# password: ""
# max_idle: 80
# max_active: 12000
# In most cases you don't need these
# salt: "encrypted cookie"
# sign_salt: "signed encrypted cookie"
@ -144,7 +147,7 @@ tables:
url: http://rails_app:3000/stripe/$id
path: data
# debug: true
pass_headers:
pass_headers:
- cookie
set_headers:
- name: Host
@ -165,7 +168,6 @@ tables:
- name: email
related_to: products.name
roles_query: "SELECT * FROM users WHERE id = $user_id"
roles:
@ -174,12 +176,12 @@ roles:
- name: products
query:
limit: 10
columns: ["id", "name", "description" ]
columns: ["id", "name", "description"]
aggregation: false
insert:
block: false
update:
block: false

View File

@ -12,7 +12,7 @@ log_level: "info"
# enable or disable http compression (uses gzip)
http_compress: true
# When production mode is 'true' only queries
# When production mode is 'true' only queries
# from the allow list are permitted.
# When it's 'false' all queries are saved to the
# the allow list in ./config/allow.list
@ -32,7 +32,7 @@ enable_tracing: true
# Path pointing to where the migrations can be found
# migrations_path: ./migrations
# Secret key for general encryption operations like
# Secret key for general encryption operations like
# encrypting the cursor data
# secret_key: supercalifajalistics
@ -57,11 +57,15 @@ database:
password: postgres
#pool_size: 10
#max_retries: 0
#log_level: "debug"
#log_level: "debug"
# Set session variable "user.id" to the user id
# Enable this if you need the user id in triggers, etc
set_user_id: false
# database ping timeout is used for db health checking
ping_timeout: 5m
ping_timeout: 5m
# open opencensus tracing and metrics
telemetry:
enable: false

View File

@ -106,7 +106,8 @@ type Role struct {
// RoleTable struct contains role specific access control values for a database table
type RoleTable struct {
Name string
Name string
ReadOnly *bool `mapstructure:"read_only"`
Query Query
Insert Insert
@ -120,7 +121,7 @@ type Query struct {
Filters []string
Columns []string
DisableFunctions bool `mapstructure:"disable_functions"`
Block bool
Block *bool
}
// Insert struct contains access control values for insert operations
@ -128,7 +129,7 @@ type Insert struct {
Filters []string
Columns []string
Presets map[string]string
Block bool
Block *bool
}
// Insert struct contains access control values for update operations
@ -136,14 +137,14 @@ type Update struct {
Filters []string
Columns []string
Presets map[string]string
Block bool
Block *bool
}
// Delete struct contains access control values for delete operations
type Delete struct {
Filters []string
Columns []string
Block bool
Block *bool
}
// ReadInConfig function reads in the config file for the environment specified in the GO_ENV

View File

@ -83,14 +83,14 @@ func (sg *SuperGraph) initConfig() error {
// Roles: validate and sanitize
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")
}
_, userExists := sg.roles["user"]
_, sg.anonExists = sg.roles["anon"]
sg.abacEnabled = userExists && len(c.RolesQuery) != 0
sg.abacEnabled = userExists && c.RolesQuery != ""
return nil
}
@ -112,7 +112,7 @@ func getDBTableAliases(c *Config) map[string][]string {
func addTables(c *Config, di *psql.DBInfo) error {
for _, t := range c.Tables {
if len(t.Table) == 0 || len(t.Columns) == 0 {
if t.Table == "" || len(t.Columns) == 0 {
continue
}
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 {
for _, t := range c.Tables {
for _, c := range t.Columns {
if len(c.ForeignKey) == 0 {
if c.ForeignKey == "" {
continue
}
if err := addForeignKey(di, c, t); err != nil {
@ -216,53 +216,74 @@ func addRoles(c *Config, qc *qcode.Compiler) error {
}
func addRole(qc *qcode.Compiler, r Role, t RoleTable) error {
blockFilter := []string{"false"}
blocked := struct {
readOnly bool
query bool
insert bool
update bool
delete bool
}{true, true, true, true, true}
if r.Name == "anon" {
blocked.query = false
} else {
blocked.readOnly = false
blocked.query = false
blocked.insert = false
blocked.update = false
blocked.delete = false
}
if t.ReadOnly != nil {
blocked.readOnly = *t.ReadOnly
}
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{
Limit: t.Query.Limit,
Filters: t.Query.Filters,
Columns: t.Query.Columns,
DisableFunctions: t.Query.DisableFunctions,
}
if t.Query.Block {
query.Filters = blockFilter
Block: blocked.query,
}
insert := qcode.InsertConfig{
Filters: t.Insert.Filters,
Columns: t.Insert.Columns,
Presets: t.Insert.Presets,
}
if t.Insert.Block {
insert.Filters = blockFilter
Block: blocked.insert,
}
update := qcode.UpdateConfig{
Filters: t.Update.Filters,
Columns: t.Update.Columns,
Presets: t.Update.Presets,
Block: blocked.update,
}
if t.Update.Block {
update.Filters = blockFilter
}
delete := qcode.DeleteConfig{
del := qcode.DeleteConfig{
Filters: t.Delete.Filters,
Columns: t.Delete.Columns,
}
if t.Delete.Block {
delete.Filters = blockFilter
Block: blocked.delete,
}
return qc.AddRole(r.Name, t.Name, qcode.TRConfig{
Query: query,
Insert: insert,
Update: update,
Delete: delete,
ReadOnly: blocked.readOnly,
Query: query,
Insert: insert,
Update: update,
Delete: del,
})
}

View File

@ -10,6 +10,7 @@ import (
"sort"
"strings"
"github.com/chirino/graphql/schema"
"github.com/dosco/super-graph/jsn"
)
@ -39,7 +40,7 @@ type Config struct {
func New(filename string, conf Config) (*List, error) {
al := List{}
if len(filename) != 0 {
if filename != "" {
fp := filename
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"
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"
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 {
return nil, errors.New("allow.list not found")
}
if len(filename) == 0 {
if filename == "" {
al.filepath = "./config/allow.list"
} else {
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")
}
if len(query) == 0 {
if 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) {
var list []Item
varString := "variables"
b, err := ioutil.ReadFile(al.filepath)
if err != nil {
@ -180,9 +182,9 @@ func (al *List) Load() ([]Item, error) {
s = e
}
ty = AL_QUERY
} else if matchPrefix(b, e, "variables") {
} else if matchPrefix(b, e, varString) {
if c == 0 {
s = e + len("variables") + 1
s = e + len(varString) + 1
}
ty = AL_VARS
} else if b[e] == '{' {
@ -234,10 +236,24 @@ func (al *List) Load() ([]Item, error) {
func (al *List) save(item Item) error {
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)
if len(item.Name) == 0 {
if item.Name == "" {
return nil
}
@ -256,7 +272,7 @@ func (al *List) save(item Item) error {
}
if index != -1 {
if len(list[index].Comment) != 0 {
if list[index].Comment != "" {
item.Comment = list[index].Comment
}
list[index] = item
@ -280,7 +296,7 @@ func (al *List) save(item Item) error {
i := 0
for _, c := range cmtLines {
if c = strings.TrimSpace(c); len(c) == 0 {
if c = strings.TrimSpace(c); c == "" {
continue
}

View File

@ -16,41 +16,46 @@ type QueryConfig struct {
Filters []string
Columns []string
DisableFunctions bool
Block bool
}
type InsertConfig struct {
Filters []string
Columns []string
Presets map[string]string
Block bool
}
type UpdateConfig struct {
Filters []string
Columns []string
Presets map[string]string
Block bool
}
type DeleteConfig struct {
Filters []string
Columns []string
Block bool
}
type TRConfig struct {
Query QueryConfig
Insert InsertConfig
Update UpdateConfig
Delete DeleteConfig
ReadOnly bool
Query QueryConfig
Insert InsertConfig
Update UpdateConfig
Delete DeleteConfig
}
type trval struct {
query struct {
readOnly bool
query struct {
limit string
fil *Exp
filNU bool
cols map[string]struct{}
disable struct {
funcs bool
}
disable struct{ funcs bool }
block bool
}
insert struct {
@ -59,6 +64,7 @@ type trval struct {
cols map[string]struct{}
psmap map[string]string
pslist []string
block bool
}
update struct {
@ -67,12 +73,14 @@ type trval struct {
cols map[string]struct{}
psmap map[string]string
pslist []string
block bool
}
delete struct {
fil *Exp
filNU bool
cols map[string]struct{}
block bool
}
}

View File

@ -207,7 +207,7 @@ func NewFilter() *Exp {
func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
var err error
trv := &trval{}
trv := &trval{readOnly: trc.ReadOnly}
// query config
trv.query.fil, trv.query.filNU, err = compileFilter(trc.Query.Filters)
@ -219,6 +219,7 @@ func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
}
trv.query.cols = listToMap(trc.Query.Columns)
trv.query.disable.funcs = trc.Query.DisableFunctions
trv.query.block = trc.Query.Block
// insert config
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.psmap = parsePresets(trc.Insert.Presets)
trv.insert.pslist = mapToList(trv.insert.psmap)
trv.insert.block = trc.Insert.Block
// update config
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.psmap = parsePresets(trc.Update.Presets)
trv.update.pslist = mapToList(trv.update.psmap)
trv.update.block = trc.Update.Block
// delete config
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
}
trv.delete.cols = listToMap(trc.Delete.Columns)
trv.delete.block = trc.Delete.Block
singular := flect.Singularize(table)
plural := flect.Pluralize(table)
@ -330,6 +334,28 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
trv := com.getRole(role, field.Name)
switch action {
case QTQuery:
if trv.query.block {
continue
}
case QTInsert:
if trv.insert.block || trv.readOnly {
return fmt.Errorf("insert blocked: %s", field.Name)
}
case QTUpdate:
if trv.update.block || trv.readOnly {
return fmt.Errorf("update blocked: %s", field.Name)
}
case QTDelete:
if trv.delete.block || trv.readOnly {
return fmt.Errorf("delete blocked: %s", field.Name)
}
}
selects = append(selects, Select{
ID: id,
ParentID: parentID,

View File

@ -36,7 +36,7 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; // Add to the top of the file b
### Fetching data with GraphQL
Just image 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 ya you also need efficient cursor based pagination. And Remember you also need to maintain this code forever.
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.
@ -71,7 +71,7 @@ query {
### Instant results
Here's the data Super Graph fetched using the GraphQL above it's even in the JSON structure you
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

2
go.mod
View File

@ -1,6 +1,7 @@
module github.com/dosco/super-graph
require (
contrib.go.opencensus.io/integrations/ocsql v0.1.6
github.com/DATA-DOG/go-sqlmock v1.4.1
github.com/GeertJohan/go.rice v1.0.0
github.com/NYTimes/gziphandler v1.1.1
@ -32,6 +33,7 @@ require (
github.com/spf13/viper v1.6.3
github.com/stretchr/testify v1.5.1
github.com/valyala/fasttemplate v1.1.0
go.opencensus.io v0.22.3 // indirect
go.uber.org/zap v1.14.1
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect

27
go.sum
View File

@ -1,4 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
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/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM=
@ -18,6 +20,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
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/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/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
@ -79,11 +82,16 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
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/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/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/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.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
@ -176,6 +184,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.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
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/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
@ -203,12 +212,16 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
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_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/common v0.0.0-20181113130724-41aa239b4cce/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/procfs v0.0.0-20181005140218-185b4288413d/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/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
@ -291,6 +304,8 @@ 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/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
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.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
@ -314,15 +329,19 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
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-20190313153728-d0100b6bd8b3/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/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
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/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-20181114220301-adae6a3d119a/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-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/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -334,6 +353,7 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
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-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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -346,6 +366,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
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-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-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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -360,6 +381,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@ -378,8 +400,13 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
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=
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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
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/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
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=
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=

View File

@ -48,9 +48,15 @@ type Serv struct {
APIPath string `mapstructure:"api_path"`
CacheControl string `mapstructure:"cache_control"`
// Telemetry struct contains OpenCensus metrics and tracing related config
Telemetry struct {
Enable bool
}
Auth auth.Auth
Auths []auth.Auth
// DB struct contains db config
DB struct {
Type string
Host string

View File

@ -1,7 +0,0 @@
package serv
// func (c *coreContext) handleReq(w io.Writer, req *http.Request) error {
// return nil
// }

View File

@ -12,6 +12,7 @@ import (
"strings"
"time"
"contrib.go.opencensus.io/integrations/ocsql"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/stdlib"
//_ "github.com/jackc/pgx/v4/stdlib"
@ -210,16 +211,39 @@ func initDB(c *Config, useDB bool) (*sql.DB, error) {
// config.MaxConns = conf.DB.PoolSize
// }
for i := 1; i < 10; i++ {
db = stdlib.OpenDB(*config)
if db == nil {
break
connString := stdlib.RegisterConnConfig(config)
driverName := "pgx"
// if db = stdlib.OpenDB(*config); db == nil {
// return errors.New("failed to open db")
// }
if conf.Telemetry.Enable {
driverName, err = ocsql.Register(driverName, ocsql.WithAllTraceOptions(), ocsql.WithInstanceName(conf.AppName))
if err != nil {
return nil, fmt.Errorf("unable to register ocsql driver: %v", err)
}
ocsql.RegisterAllViews()
//defer ocsql.RecordStats(db, 2*time.Second)()
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)
}
if err != nil {
return nil, err
return nil, fmt.Errorf("unable to open db connection: %v", err)
}
if conf.Telemetry.Enable {
defer ocsql.RecordStats(db, 2*time.Second)()
}
return db, nil