fix: add config for per role operation blocking by type
This commit is contained in:
parent
f7d3760af7
commit
448e6bb72a
|
@ -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:
|
||||||
|
|
|
@ -106,7 +106,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
|
||||||
|
@ -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
|
||||||
|
|
63
core/init.go
63
core/init.go
|
@ -216,53 +216,74 @@ 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{
|
||||||
Query: query,
|
ReadOnly: blocked.readOnly,
|
||||||
Insert: insert,
|
Query: query,
|
||||||
Update: update,
|
Insert: insert,
|
||||||
Delete: delete,
|
Update: update,
|
||||||
|
Delete: delete,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,41 +16,46 @@ 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 {
|
||||||
Query QueryConfig
|
ReadOnly bool
|
||||||
Insert InsertConfig
|
Query QueryConfig
|
||||||
Update UpdateConfig
|
Insert InsertConfig
|
||||||
Delete DeleteConfig
|
Update UpdateConfig
|
||||||
|
Delete DeleteConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue