Disallow use of reserved names for module fields
List of reserved names: - recordID - ownedBy - createdBy - createdAt - updatedBy - updatedAt - deletedBy - deletedAt
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/handle"
|
||||
"github.com/cortezaproject/corteza-server/pkg/label"
|
||||
"github.com/cortezaproject/corteza-server/pkg/locale"
|
||||
"github.com/cortezaproject/corteza-server/pkg/slice"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
)
|
||||
|
||||
@@ -63,6 +64,19 @@ const (
|
||||
moduleFieldsChanged moduleChanges = 4
|
||||
)
|
||||
|
||||
var (
|
||||
systemFields = slice.ToStringBoolMap([]string{
|
||||
"recordID",
|
||||
"ownedBy",
|
||||
"createdBy",
|
||||
"createdAt",
|
||||
"updatedBy",
|
||||
"updatedAt",
|
||||
"deletedBy",
|
||||
"deletedAt",
|
||||
})
|
||||
)
|
||||
|
||||
func Module() *module {
|
||||
return &module{
|
||||
ac: DefaultAccessControl,
|
||||
@@ -217,6 +231,16 @@ func (svc module) Create(ctx context.Context, new *types.Module) (*types.Module,
|
||||
return ModuleErrInvalidHandle()
|
||||
}
|
||||
|
||||
for _, f := range new.Fields {
|
||||
if systemFields[f.Name] {
|
||||
return ModuleErrFieldNameReserved()
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
|
||||
if ns, err = loadNamespace(ctx, s, new.NamespaceID); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -574,6 +598,13 @@ func updateModuleFields(ctx context.Context, s store.Storer, new, old *types.Mod
|
||||
f.NamespaceID = new.NamespaceID
|
||||
}
|
||||
|
||||
if systemFields[f.Name] && !old.Fields.HasName(f.Name) {
|
||||
// make sure we're backward compatible, or better:
|
||||
// if, by some weird case, someone managed to get invalid field name into
|
||||
// the store, we'll turn a blind eye.
|
||||
return ModuleErrFieldNameReserved()
|
||||
}
|
||||
|
||||
if f.ModuleID != new.ID {
|
||||
return fmt.Errorf("module id of field %q does not match the module", f.Name)
|
||||
}
|
||||
|
||||
36
compose/service/module_actions.gen.go
generated
36
compose/service/module_actions.gen.go
generated
@@ -628,7 +628,7 @@ func ModuleErrNameNotUnique(mm ...*moduleActionProps) *errors.Error {
|
||||
errors.Meta("resource", "compose:module"),
|
||||
|
||||
// action log entry; no formatting, it will be applied inside recordAction fn.
|
||||
errors.Meta(moduleLogMetaKey{}, "used duplicate username ({{module.name}}) for module"),
|
||||
errors.Meta(moduleLogMetaKey{}, "used duplicate name ({{module.name}}) for module"),
|
||||
errors.Meta(modulePropsMetaKey{}, p),
|
||||
|
||||
// translation namespace & key
|
||||
@@ -644,6 +644,40 @@ func ModuleErrNameNotUnique(mm ...*moduleActionProps) *errors.Error {
|
||||
return e
|
||||
}
|
||||
|
||||
// ModuleErrFieldNameReserved returns "compose:module.fieldNameReserved" as *errors.Error
|
||||
//
|
||||
//
|
||||
// This function is auto-generated.
|
||||
//
|
||||
func ModuleErrFieldNameReserved(mm ...*moduleActionProps) *errors.Error {
|
||||
var p = &moduleActionProps{}
|
||||
if len(mm) > 0 {
|
||||
p = mm[0]
|
||||
}
|
||||
|
||||
var e = errors.New(
|
||||
errors.KindInternal,
|
||||
|
||||
p.Format("field name is reserved for system fields", nil),
|
||||
|
||||
errors.Meta("type", "fieldNameReserved"),
|
||||
errors.Meta("resource", "compose:module"),
|
||||
|
||||
errors.Meta(modulePropsMetaKey{}, p),
|
||||
|
||||
// translation namespace & key
|
||||
errors.Meta(locale.ErrorMetaNamespace{}, "compose"),
|
||||
errors.Meta(locale.ErrorMetaKey{}, "module.errors.fieldNameReserved"),
|
||||
|
||||
errors.StackSkip(1),
|
||||
)
|
||||
|
||||
if len(mm) > 0 {
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
// ModuleErrStaleData returns "compose:module.staleData" as *errors.Error
|
||||
//
|
||||
//
|
||||
|
||||
@@ -71,9 +71,12 @@ errors:
|
||||
|
||||
- error: nameNotUnique
|
||||
message: "name not unique"
|
||||
log: "used duplicate username ({{module.name}}) for module"
|
||||
log: "used duplicate name ({{module.name}}) for module"
|
||||
severity: warning
|
||||
|
||||
- error: fieldNameReserved
|
||||
message: "field name is reserved for system fields"
|
||||
|
||||
- error: staleData
|
||||
message: "stale data"
|
||||
severity: warning
|
||||
|
||||
@@ -266,6 +266,57 @@ func TestModuleFieldsUpdate(t *testing.T) {
|
||||
h.a.Equal(m.Fields[1].Kind, "DateTime")
|
||||
}
|
||||
|
||||
func TestModuleUpdateWithReservedFieldName(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.clearModules()
|
||||
|
||||
helpers.AllowMe(h, types.NamespaceRbacResource(0), "read", "modules.search")
|
||||
ns := h.makeNamespace("some-namespace")
|
||||
m := h.makeModule(ns, "some-module", &types.ModuleField{ID: id.Next(), Kind: "String", Name: "ownedBy"})
|
||||
helpers.AllowMe(h, types.ModuleRbacResource(0, 0), "update")
|
||||
|
||||
f := m.Fields[0]
|
||||
fjs := fmt.Sprintf(`{ "name": "%s", "fields": [{ "fieldID": "%d", "name": "ownedBy", "kind": "Number" }]}`, m.Name, f.ID)
|
||||
h.apiInit().
|
||||
Post(fmt.Sprintf("/namespace/%d/module/%d", ns.ID, m.ID)).
|
||||
Header("Accept", "application/json").
|
||||
JSON(fjs).
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
|
||||
f = m.Fields[0]
|
||||
fjs = fmt.Sprintf(`{ "name": "%s", "fields": [{ "fieldID": "%d", "name": "updatedBy", "kind": "Number" }]}`, m.Name, f.ID)
|
||||
h.apiInit().
|
||||
Post(fmt.Sprintf("/namespace/%d/module/%d", ns.ID, m.ID)).
|
||||
Header("Accept", "application/json").
|
||||
JSON(fjs).
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertError("module.errors.fieldNameReserved")).
|
||||
End()
|
||||
}
|
||||
|
||||
func TestModuleCreateWithReservedFieldName(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.clearModules()
|
||||
|
||||
helpers.AllowMe(h, types.NamespaceRbacResource(0), "read", "modules.search")
|
||||
ns := h.makeNamespace("some-namespace")
|
||||
helpers.AllowMe(h, types.ModuleRbacResource(0, 0), "update")
|
||||
|
||||
fjs := fmt.Sprintf(`{ "name": "foo", "fields": [{ "name": "ownedBy", "kind": "Number" }]}`)
|
||||
h.apiInit().
|
||||
Post(fmt.Sprintf("/namespace/%d/module/", ns.ID)).
|
||||
Header("Accept", "application/json").
|
||||
JSON(fjs).
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertError("module.errors.fieldNameReserved")).
|
||||
End()
|
||||
}
|
||||
|
||||
func TestModuleFieldsUpdate_defaults(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.clearModules()
|
||||
|
||||
Reference in New Issue
Block a user