Tweak rv sanitizer->value expression interaction
When record value expression returns null the value gets omitted. Tweak value sanitizer logic for more consistency.
This commit is contained in:
@@ -3,8 +3,10 @@ package values
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
func makeInvalidExprErr(field *types.ModuleField, expr string, err error) types.RecordValueError {
|
||||
@@ -78,24 +80,27 @@ func Expression(ctx context.Context, m *types.Module, r *types.Record, old *type
|
||||
}
|
||||
|
||||
var strings []string
|
||||
if values, isSlice := tmp.([]interface{}); isSlice {
|
||||
if !f.Multi {
|
||||
rve.Push(makeValueExprIncompErr(f))
|
||||
continue
|
||||
}
|
||||
// When the expression results in null (nil) delete that record value.
|
||||
// The below Values.Replace already does it so we simply ignore strings
|
||||
if !reflect2.IsNil(tmp) {
|
||||
if values, isSlice := tmp.([]interface{}); isSlice {
|
||||
if !f.Multi {
|
||||
rve.Push(makeValueExprIncompErr(f))
|
||||
continue
|
||||
}
|
||||
|
||||
strings = make([]string, len(values))
|
||||
for i, value := range values {
|
||||
strings[i] = sanitize(f, value)
|
||||
}
|
||||
} else {
|
||||
if f.Multi {
|
||||
rve.Push(makeValueExprIncompErr(f))
|
||||
continue
|
||||
}
|
||||
|
||||
strings = []string{sanitize(f, tmp)}
|
||||
strings = make([]string, len(values))
|
||||
for i, value := range values {
|
||||
strings[i] = sanitize(f, value)
|
||||
}
|
||||
} else {
|
||||
if f.Multi {
|
||||
rve.Push(makeValueExprIncompErr(f))
|
||||
continue
|
||||
}
|
||||
|
||||
strings = []string{sanitize(f, tmp)}
|
||||
}
|
||||
}
|
||||
|
||||
r.Values = r.Values.Replace(f.Name, strings...)
|
||||
|
||||
@@ -2,9 +2,10 @@ package values
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExpressions(t *testing.T) {
|
||||
@@ -162,4 +163,17 @@ func TestExpressions(t *testing.T) {
|
||||
req.Equal("b", new.Values.Get("f1", 1).Value)
|
||||
req.Equal("c", new.Values.Get("f1", 2).Value)
|
||||
})
|
||||
|
||||
t.Run("omit record value when expr returns null (nil)", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
m = makeModule("f1", "String", `null`)
|
||||
r = &types.Record{}
|
||||
rve = &types.RecordValueErrorSet{}
|
||||
)
|
||||
|
||||
Expression(ctx, m, r, nil, rve)
|
||||
req.True(rve.IsValid())
|
||||
req.Empty(r.Values)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"github.com/cortezaproject/corteza-server/pkg/logger"
|
||||
"github.com/cortezaproject/corteza-server/pkg/xss"
|
||||
"github.com/spf13/cast"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
@@ -117,34 +118,7 @@ func (s sanitizer) Run(m *types.Module, vv types.RecordValueSet) (out types.Reco
|
||||
}
|
||||
}
|
||||
|
||||
// Per field type validators
|
||||
switch kind {
|
||||
case "bool":
|
||||
v.Value = sBool(v.Value)
|
||||
|
||||
case "datetime":
|
||||
v.Value = sDatetime(v.Value, f.Options.Bool("onlyDate"), f.Options.Bool("onlyTime"))
|
||||
|
||||
case "number":
|
||||
v.Value = sNumber(v.Value, f.Options.Precision())
|
||||
|
||||
case "string":
|
||||
v.Value = sString(v.Value)
|
||||
|
||||
// Uncomment when they become relevant for sanitization
|
||||
//case "email":
|
||||
// v = s.sEmail(v, f, m)
|
||||
//case "file":
|
||||
// v = s.sFile(v, f, m)
|
||||
//case "record":
|
||||
// v = s.sRecord(v, f, m)
|
||||
//case "select":
|
||||
// v = s.sSelect(v, f, m)
|
||||
//case "url":
|
||||
// v = s.sUrl(v, f, m)
|
||||
//case "user":
|
||||
// v = s.sUser(v, f, m)
|
||||
}
|
||||
v.Value = sanitize(f, v.Value)
|
||||
}
|
||||
|
||||
return
|
||||
@@ -284,8 +258,13 @@ func sNumber(num interface{}, p uint) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func sString(str string) string {
|
||||
return xss.RichText(str)
|
||||
func sString(str interface{}) string {
|
||||
base, err := cast.ToStringE(str)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return xss.RichText(base)
|
||||
}
|
||||
|
||||
// sanitize casts value to field kind format
|
||||
@@ -297,6 +276,8 @@ func sanitize(f *types.ModuleField, v interface{}) string {
|
||||
v = sDatetime(v, f.Options.Bool("onlyDate"), f.Options.Bool("onlyTime"))
|
||||
case "number":
|
||||
v = sNumber(v, f.Options.Precision())
|
||||
case "string":
|
||||
v = sString(v)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", v)
|
||||
|
||||
Reference in New Issue
Block a user