3
0

Implement value validators on fields

This commit is contained in:
Denis Arh
2020-11-11 23:23:41 +01:00
parent d2142d6448
commit 3d2a3130f6
4 changed files with 99 additions and 33 deletions

View File

@@ -96,6 +96,9 @@ func (vldtr *validator) FileRefChecker(fn ReferenceChecker) {
func (vldtr validator) Run(ctx context.Context, s store.Storer, m *types.Module, r *types.Record) (out *types.RecordValueErrorSet) {
var (
f *types.ModuleField
valParser = parser()
valDict = r.Values.Dict(m.Fields)
)
out = &types.RecordValueErrorSet{}
@@ -132,7 +135,7 @@ fields:
}
for _, v := range r.Values {
if !v.IsUpdated() || v.IsUpdated() {
if !v.IsUpdated() || v.IsDeleted() {
// We'll validate only updated (and non-deleted) values
continue
}
@@ -141,33 +144,67 @@ fields:
continue
}
if v.Value == "" {
// Nothing to do with empty value
return nil
if !(f.Expressions.DisableDefaultValidators && len(f.Expressions.Validators) > 0) {
if v.Value == "" {
// Nothing to do with empty value
return nil
}
// Per field type validators
switch strings.ToLower(f.Kind) {
case "bool":
out.Push(vldtr.vBool(v, f, r, m)...)
case "datetime":
out.Push(vldtr.vDatetime(v, f, r, m)...)
case "email":
out.Push(vldtr.vEmail(v, f, r, m)...)
case "file":
out.Push(vldtr.vFile(ctx, s, v, f, r, m)...)
case "number":
out.Push(vldtr.vNumber(v, f, r, m)...)
case "record":
out.Push(vldtr.vRecord(ctx, s, v, f, r, m)...)
case "select":
out.Push(vldtr.vSelect(v, f, r, m)...)
//case "string":
// out.Push(vldtr.vString(v, f, r, m)...)
case "url":
out.Push(vldtr.vUrl(v, f, r, m)...)
case "user":
out.Push(vldtr.vUser(ctx, s, v, f, r, m)...)
}
}
// Per field type validators
switch strings.ToLower(f.Kind) {
case "bool":
out.Push(vldtr.vBool(v, f, r, m)...)
case "datetime":
out.Push(vldtr.vDatetime(v, f, r, m)...)
case "email":
out.Push(vldtr.vEmail(v, f, r, m)...)
case "file":
out.Push(vldtr.vFile(ctx, s, v, f, r, m)...)
case "number":
out.Push(vldtr.vNumber(v, f, r, m)...)
case "record":
out.Push(vldtr.vRecord(ctx, s, v, f, r, m)...)
case "select":
out.Push(vldtr.vSelect(v, f, r, m)...)
//case "string":
// out.Push(vldtr.vString(v, f, r, m)...)
case "url":
out.Push(vldtr.vUrl(v, f, r, m)...)
case "user":
out.Push(vldtr.vUser(ctx, s, v, f, r, m)...)
if len(f.Expressions.Validators) > 0 {
for _, cv := range f.Expressions.Validators {
eval, err := valParser.NewEvaluable(cv.Test)
if err != nil {
out.Push(makeInternalErr(f, err))
break
}
invalid, err := eval.EvalBool(ctx, map[string]interface{}{
"value": v.Value,
"oldValue": v.OldValue,
"values": valDict,
})
if err != nil {
out.Push(makeInternalErr(f, err))
break
}
if invalid {
out.Push(types.RecordValueError{
Kind: "error",
Message: cv.Error,
Meta: map[string]interface{}{"field": f.Name}},
)
// break at first failed test
break
}
}
}
}

View File

@@ -1,7 +1,9 @@
package values
import (
"context"
"github.com/cortezaproject/corteza-server/compose/types"
"github.com/stretchr/testify/require"
"reflect"
"testing"
"time"
@@ -218,3 +220,25 @@ func Test_validator_vSelect(t *testing.T) {
})
}
}
func Test_validator_customExpr(t *testing.T) {
var (
vldtr = validator{}
m = &types.Module{}
f = &types.ModuleField{Name: "num", Kind: "Number"}
r = &types.Record{}
)
f.Expressions.Validators = []types.ModuleFieldValidator{
{Test: "value > 5", Error: "value is lower than 5"},
}
m.Fields = append(m.Fields, f)
r.Values = r.Values.Replace("num", "1")
rve := vldtr.Run(context.Background(), nil, m, r)
require.False(t, rve.IsValid())
r.Values = r.Values.Replace("num", "10")
rve = vldtr.Run(context.Background(), nil, m, r)
require.True(t, rve.IsValid())
}

View File

@@ -45,14 +45,18 @@ type (
ModuleFieldExpr struct {
Value string `json:"value,omitempty"`
Sanitizers []string `json:"sanitizers,omitempty"`
//Validators []struct {
// Test string `json:"test,omitempty"`
// Error string `json:"error,omitempty"`
//} `json:"validators,omitempty"`
Validators []ModuleFieldValidator `json:"validators,omitempty"`
DisableDefaultValidators bool `json:"disableDefaultValidators,omitempty"`
Formatters []string `json:"formatters,omitempty"`
DisableDefaultFormatters bool `json:"disableDefaultFormatters,omitempty"`
}
ModuleFieldValidator struct {
Test string `json:"test,omitempty"`
Error string `json:"error,omitempty"`
}
)
var (

View File

@@ -96,9 +96,10 @@ func (set RecordValueSet) Replace(name string, values ...string) (vv RecordValue
for p, v := range values {
vv = append(vv, &RecordValue{
Name: name,
Value: v,
Place: uint(p),
Name: name,
Value: v,
Place: uint(p),
Updated: true,
})
}