From 585d6896eb71f085dbddb69209ab783ab0b8d5b6 Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Thu, 16 Sep 2021 17:30:06 +0200 Subject: [PATCH] Fix DecodeKV issue with empty strings This fix enables app-settings struct updates even if we pass in the empty or missing string value to settings. --- system/service/settings.go | 1 + system/types/kv_decoder.go | 8 ++++++++ system/types/kv_decoder_test.go | 19 ++++++++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/system/service/settings.go b/system/service/settings.go index 9e5f78608..a87551318 100644 --- a/system/service/settings.go +++ b/system/service/settings.go @@ -152,6 +152,7 @@ func (svc *settings) UpdateCurrent(ctx context.Context) error { } func (svc *settings) updateCurrent(ctx context.Context, vv types.SettingValueSet) (err error) { + // update current settings with new values if err = vv.KV().Decode(svc.current); err != nil { return diff --git a/system/types/kv_decoder.go b/system/types/kv_decoder.go index f09d19e91..ba89ecc1d 100644 --- a/system/types/kv_decoder.go +++ b/system/types/kv_decoder.go @@ -145,6 +145,14 @@ func DecodeKV(kv SettingsKV, dst interface{}, pp ...string) (err error) { // Native type if val, ok := kv[key]; ok { // Always use pointer to value + if val == nil { + switch structFType.Type.Kind() { + case reflect.String: + structField.SetString("") + continue + } + } + if val.Unmarshal(structField.Addr().Interface()) != nil { // Try to get numbers encoded as strings... var tmp interface{} diff --git a/system/types/kv_decoder_test.go b/system/types/kv_decoder_test.go index c4e5a95f8..17acbe870 100644 --- a/system/types/kv_decoder_test.go +++ b/system/types/kv_decoder_test.go @@ -35,14 +35,21 @@ func TestDecode(t *testing.T) { Map map[string]string `kv:"sub.map"` S2I map[string]int `kv:"sub.s2i"` + + PrefilledString1 string + PrefilledString2 string } ) var ( ptr = "point-me" - aux = dst{} - kv = SettingsKV{ + aux = dst{ + PrefilledString1: "values", + PrefilledString2: "values", + } + + kv = SettingsKV{ "s": types.JSONText(`"string"`), "b": types.JSONText("true"), "n": types.JSONText("42"), @@ -60,6 +67,9 @@ func TestDecode(t *testing.T) { "sub.s2i.one": types.JSONText(`1`), "sub.s2i.two": types.JSONText(`2`), + + "prefilledString1": nil, + "prefilledString2": types.JSONText(`""`), } eq = dst{ @@ -85,10 +95,13 @@ func TestDecode(t *testing.T) { "one": 1, "two": 2, }, + + PrefilledString1: "", + PrefilledString2: "", } ) - // setting this externaly (embedded structs) + // setting this externally (embedded structs) eq.Sub.Bar.Foo = "foobar" require.NoError(t, DecodeKV(kv, &aux))