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: ""
# max_idle: 80
# max_active: 12000
# In most cases you don't need these
# salt: "encrypted cookie"
# sign_salt: "signed encrypted cookie"
@ -165,7 +164,6 @@ tables:
- name: email
related_to: products.name
roles_query: "SELECT * FROM users WHERE id = $user_id"
roles:

View File

@ -107,6 +107,7 @@ type Role struct {
// RoleTable struct contains role specific access control values for a database table
type RoleTable struct {
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

@ -216,49 +216,70 @@ 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,
}
if t.Update.Block {
update.Filters = blockFilter
Block: blocked.update,
}
delete := 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{
ReadOnly: blocked.readOnly,
Query: query,
Insert: insert,
Update: update,

View File

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