fix: allow unauthenticated operations in seed script
This commit is contained in:
parent
cd69b5a78f
commit
d572b4f753
|
@ -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)
|
||||||
|
|
|
@ -93,7 +93,6 @@ 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 {
|
||||||
|
|
12
core/init.go
12
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),
|
||||||
|
@ -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,9 +215,13 @@ 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 {
|
||||||
ro := true // read-only
|
ro := true // read-only
|
||||||
|
|
||||||
|
if defaultAllow {
|
||||||
|
ro = false
|
||||||
|
}
|
||||||
|
|
||||||
if r.Name != "anon" {
|
if r.Name != "anon" {
|
||||||
ro = false
|
ro = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ 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`
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Blocklist []string
|
Blocklist []string
|
||||||
DefaultBlock bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueryConfig struct {
|
type QueryConfig struct {
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ type Serv struct {
|
||||||
// Telemetry struct contains OpenCensus metrics and tracing related config
|
// Telemetry struct contains OpenCensus metrics and tracing related config
|
||||||
Telemetry struct {
|
Telemetry struct {
|
||||||
Debug bool
|
Debug bool
|
||||||
|
Interval *time.Duration
|
||||||
Metrics struct {
|
Metrics struct {
|
||||||
Exporter string
|
Exporter string
|
||||||
Endpoint string
|
Endpoint 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
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ func GetConfigName() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) telemetryEnabled() bool {
|
func (c *Config) telemetryEnabled() bool {
|
||||||
return c.Telemetry.Metrics.Exporter != "" || c.Telemetry.Tracing.Exporter != ""
|
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 {
|
||||||
|
|
|
@ -111,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 bool, useTelemetry bool) (*sql.DB, error) {
|
||||||
var db *sql.DB
|
var db *sql.DB
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -217,14 +214,22 @@ func initDB(c *Config, useDB bool) (*sql.DB, error) {
|
||||||
// return errors.New("failed to open db")
|
// return errors.New("failed to open db")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if conf.telemetryEnabled() {
|
if useTelemetry && conf.telemetryEnabled() {
|
||||||
driverName, err = ocsql.Register(driverName, ocsql.WithAllTraceOptions(), ocsql.WithInstanceName(conf.AppName))
|
driverName, err = ocsql.Register(driverName, ocsql.WithAllTraceOptions(), ocsql.WithInstanceName(conf.AppName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to register ocsql driver: %v", err)
|
return nil, fmt.Errorf("unable to register ocsql driver: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ocsql.RegisterAllViews()
|
ocsql.RegisterAllViews()
|
||||||
//defer ocsql.RecordStats(db, 2*time.Second)()
|
|
||||||
|
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")
|
log.Println("INF OpenCensus telemetry enabled")
|
||||||
}
|
}
|
||||||
|
@ -242,9 +247,5 @@ func initDB(c *Config, useDB bool) (*sql.DB, error) {
|
||||||
return nil, fmt.Errorf("unable to open db connection: %v", err)
|
return nil, fmt.Errorf("unable to open db connection: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.telemetryEnabled() {
|
|
||||||
defer ocsql.RecordStats(db, 2*time.Second)()
|
|
||||||
}
|
|
||||||
|
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ func enableObservability(mux *http.ServeMux) (func(), error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case "":
|
case "":
|
||||||
log.Println("INF No OpenCensus metrics exporter initialized")
|
log.Println("WRN OpenCensus: no metrics exporter defined")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("invalid metrics exporter")
|
err = fmt.Errorf("invalid metrics exporter")
|
||||||
|
@ -96,7 +96,7 @@ func enableObservability(mux *http.ServeMux) (func(), error) {
|
||||||
tex = zipkin.NewExporter(re, lep)
|
tex = zipkin.NewExporter(re, lep)
|
||||||
|
|
||||||
case "":
|
case "":
|
||||||
log.Println("INF No OpenCensus tracing exporter initialized")
|
log.Println("WRN OpenCensus: no traceing exporter defined")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("invalid tracing exporter")
|
err = fmt.Errorf("invalid tracing exporter")
|
||||||
|
|
Loading…
Reference in New Issue