fix: add config for per role operation blocking by type

This commit is contained in:
Vikram Rangnekar 2020-05-22 02:24:13 -04:00
parent f7d3760af7
commit 448e6bb72a
5 changed files with 102 additions and 48 deletions

View File

@ -91,7 +91,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"
@ -165,7 +164,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,7 +172,7 @@ 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:

View File

@ -107,6 +107,7 @@ 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
@ -120,7 +121,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
@ -128,7 +129,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
@ -136,14 +137,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

View File

@ -216,49 +216,70 @@ func addRoles(c *Config, qc *qcode.Compiler) error {
} }
func addRole(qc *qcode.Compiler, r Role, t RoleTable) 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{ 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 {
update.Filters = blockFilter
} }
delete := qcode.DeleteConfig{ 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{
ReadOnly: blocked.readOnly,
Query: query, Query: query,
Insert: insert, Insert: insert,
Update: update, Update: update,

View File

@ -16,26 +16,31 @@ 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 {
ReadOnly bool
Query QueryConfig Query QueryConfig
Insert InsertConfig Insert InsertConfig
Update UpdateConfig Update UpdateConfig
@ -43,14 +48,14 @@ type TRConfig struct {
} }
type trval struct { type trval struct {
readOnly bool
query struct { 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 +64,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 +73,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
} }
} }

View File

@ -207,7 +207,7 @@ func NewFilter() *Exp {
func (com *Compiler) AddRole(role, table string, trc TRConfig) error { func (com *Compiler) AddRole(role, table string, trc TRConfig) error {
var err error var err error
trv := &trval{} trv := &trval{readOnly: trc.ReadOnly}
// query config // query config
trv.query.fil, trv.query.filNU, err = compileFilter(trc.Query.Filters) 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.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)
@ -330,6 +334,28 @@ func (com *Compiler) compileQuery(qc *QCode, op *Operation, role string) error {
trv := com.getRole(role, field.Name) 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{ selects = append(selects, Select{
ID: id, ID: id,
ParentID: parentID, ParentID: parentID,