Beter ref handling, some cleanups, added tests
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"github.com/spf13/cast"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -289,7 +290,7 @@ func composeRecordValuesTypedValueSelector(res *types.Record, k string) (expr.Ty
|
||||
case len(vv) == 1 && !multiValueField:
|
||||
return recordValueToExprTypedValue(field, vv[0])
|
||||
default:
|
||||
return recordValueSetoToExprArray(field, vv...)
|
||||
return recordValueSetToExprArray(field, vv...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +340,7 @@ func assignToComposeRecordValues(res *types.Record, pp []string, val interface{}
|
||||
)
|
||||
|
||||
// @todo this needs to be implemented properly
|
||||
// we're just guessing here and puting out fires
|
||||
// we're just guessing here and putting out fires
|
||||
switch utval := expr.UntypedValue(val).(type) {
|
||||
case time.Time:
|
||||
rv.Value = utval.Format(time.RFC3339)
|
||||
@@ -435,7 +436,14 @@ func recordValueToExprTypedValue(field *types.ModuleField, rv *types.RecordValue
|
||||
return expr.NewString(rv.Value)
|
||||
|
||||
case field.IsRef():
|
||||
return expr.NewID(rv.Ref)
|
||||
ref := rv.Ref
|
||||
if ref == 0 && len(rv.Value) > 0 {
|
||||
// Cover cases when we Ref is not set but Value is
|
||||
// This happens when RVS is transferred as JSON
|
||||
ref, _ = strconv.ParseUint(rv.Value, 10, 64)
|
||||
}
|
||||
|
||||
return expr.NewID(ref)
|
||||
|
||||
default:
|
||||
if v, err := rv.Cast(field); err != nil {
|
||||
@@ -446,7 +454,7 @@ func recordValueToExprTypedValue(field *types.ModuleField, rv *types.RecordValue
|
||||
}
|
||||
}
|
||||
|
||||
func recordValueSetoToExprArray(field *types.ModuleField, vv ...*types.RecordValue) (arr *expr.Array, err error) {
|
||||
func recordValueSetToExprArray(field *types.ModuleField, vv ...*types.RecordValue) (arr *expr.Array, err error) {
|
||||
var (
|
||||
tv expr.TypedValue
|
||||
)
|
||||
|
||||
@@ -99,6 +99,7 @@ func TestRecordFieldValuesAccess(t *testing.T) {
|
||||
// expecting valid value (false) even when boolean fields are not set
|
||||
{false, "rec.values.b0"},
|
||||
{true, "rec.values.b1"},
|
||||
{uint64(2), "rec.values.ref2"},
|
||||
}
|
||||
|
||||
for _, tc := range tcc {
|
||||
@@ -167,6 +168,7 @@ func TestRecordFieldValuesAccess(t *testing.T) {
|
||||
|
||||
{true, `rec.values.ref1 != 2`},
|
||||
{true, `rec.values.ref2 == 2`},
|
||||
{true, `rec.values.ref2 == "2"`},
|
||||
}
|
||||
|
||||
for _, tc := range tcc {
|
||||
|
||||
@@ -601,7 +601,7 @@ func moduleFieldDefaultPreparer(ctx context.Context, s store.Storer, m *types.Mo
|
||||
return nil
|
||||
})
|
||||
|
||||
if err = RecordValueSanitazion(m, vv); err != nil {
|
||||
if err = RecordValueSanitization(m, vv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -475,7 +475,7 @@ func (svc record) create(ctx context.Context, new *types.Record) (rec *types.Rec
|
||||
return nil, RecordErrNotAllowedToCreate()
|
||||
}
|
||||
|
||||
if err = RecordValueSanitazion(m, new.Values); err != nil {
|
||||
if err = RecordValueSanitization(m, new.Values); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -531,7 +531,7 @@ func (svc record) create(ctx context.Context, new *types.Record) (rec *types.Rec
|
||||
return
|
||||
}
|
||||
|
||||
// RecordValueSanitazion does basic field and format validation
|
||||
// RecordValueSanitization does basic field and format validation
|
||||
//
|
||||
// Received values must fit the data model: on unknown fields
|
||||
// or multi/single value mismatch we return an error
|
||||
@@ -540,7 +540,7 @@ func (svc record) create(ctx context.Context, new *types.Record) (rec *types.Rec
|
||||
// we can assume that form builder (or whatever it was that assembled the record values)
|
||||
// was misconfigured and will most likely failed to properly parse the
|
||||
// record value errors payload too
|
||||
func RecordValueSanitazion(m *types.Module, vv types.RecordValueSet) (err error) {
|
||||
func RecordValueSanitization(m *types.Module, vv types.RecordValueSet) (err error) {
|
||||
var (
|
||||
aProps = &recordActionProps{}
|
||||
numeric = regexp.MustCompile(`^[1-9](\d+)$`)
|
||||
@@ -725,7 +725,7 @@ func (svc record) update(ctx context.Context, upd *types.Record) (rec *types.Rec
|
||||
return nil, RecordErrStaleData()
|
||||
}
|
||||
|
||||
if err = RecordValueSanitazion(m, upd.Values); err != nil {
|
||||
if err = RecordValueSanitization(m, upd.Values); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -34,36 +34,36 @@ func TestGeneralValueSetValidation(t *testing.T) {
|
||||
)
|
||||
|
||||
rvs = types.RecordValueSet{{Name: "single1", Value: "single"}}
|
||||
err = RecordValueSanitazion(module, rvs)
|
||||
err = RecordValueSanitization(module, rvs)
|
||||
req.NoError(err)
|
||||
|
||||
rvs = types.RecordValueSet{{Name: "unknown", Value: "single"}}
|
||||
err = RecordValueSanitazion(module, rvs)
|
||||
req.True(err != nil, "expecting RecordValueSanitazion() to return an error, got nil")
|
||||
err = RecordValueSanitization(module, rvs)
|
||||
req.True(err != nil, "expecting RecordValueSanitization() to return an error, got nil")
|
||||
|
||||
rvs = types.RecordValueSet{{Name: "single1", Value: "single"}, {Name: "single1", Value: "single2"}}
|
||||
err = RecordValueSanitazion(module, rvs)
|
||||
err = RecordValueSanitization(module, rvs)
|
||||
req.Error(err)
|
||||
|
||||
rvs = types.RecordValueSet{{Name: "multi1", Value: "multi1"}, {Name: "multi1", Value: "multi1"}}
|
||||
err = RecordValueSanitazion(module, rvs)
|
||||
err = RecordValueSanitization(module, rvs)
|
||||
req.NoError(err)
|
||||
|
||||
rvs = types.RecordValueSet{{Name: "ref1", Value: "non numeric value"}}
|
||||
err = RecordValueSanitazion(module, rvs)
|
||||
err = RecordValueSanitization(module, rvs)
|
||||
req.Error(err)
|
||||
|
||||
rvs = types.RecordValueSet{{Name: "ref1", Value: "12345"}}
|
||||
err = RecordValueSanitazion(module, rvs)
|
||||
err = RecordValueSanitization(module, rvs)
|
||||
req.NoError(err)
|
||||
|
||||
rvs = types.RecordValueSet{{Name: "multiRef1", Value: "12345"}, {Name: "multiRef1", Value: "67890"}}
|
||||
err = RecordValueSanitazion(module, rvs)
|
||||
err = RecordValueSanitization(module, rvs)
|
||||
req.NoError(err)
|
||||
req.Len(rvs, 2, "expecting 2 record values after sanitization, got %d", len(rvs))
|
||||
|
||||
rvs = types.RecordValueSet{{Name: "ref1", Value: ""}}
|
||||
err = RecordValueSanitazion(module, rvs)
|
||||
err = RecordValueSanitization(module, rvs)
|
||||
req.NoError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cast"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -59,6 +60,12 @@ func (v RecordValue) Cast(f *ModuleField) (interface{}, error) {
|
||||
|
||||
switch {
|
||||
case f.IsRef():
|
||||
if v.Ref == 0 && len(v.Value) > 0 {
|
||||
// Cover cases when we Ref is not set but Value is
|
||||
// This happens when RVS is transferred as JSON
|
||||
v.Ref, _ = strconv.ParseUint(v.Value, 10, 64)
|
||||
}
|
||||
|
||||
return v.Ref, nil
|
||||
|
||||
case f.IsDateTime():
|
||||
|
||||
@@ -301,7 +301,7 @@ func (n *composeRecord) Encode(ctx context.Context, pl *payload) (err error) {
|
||||
rvs = append(rvs, rv)
|
||||
}
|
||||
|
||||
if err = service.RecordValueSanitazion(mod, rvs); err != nil {
|
||||
if err = service.RecordValueSanitization(mod, rvs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user