Fix encoding on save & re-encoding on fetch
This commit is contained in:
parent
6645ac0c66
commit
d1ccbc3e17
@ -1,6 +1,7 @@
|
||||
package actionlog
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -95,13 +96,6 @@ func (m Meta) Set(key string, in interface{}, omitempty bool) {
|
||||
return
|
||||
}
|
||||
|
||||
if !omitempty {
|
||||
// Nothing special,
|
||||
// assign value and quit
|
||||
m[key] = in
|
||||
return
|
||||
}
|
||||
|
||||
// for the rest, we need to determine what kind of
|
||||
|
||||
if str, is := in.(string); is {
|
||||
@ -125,62 +119,64 @@ func (m Meta) Set(key string, in interface{}, omitempty bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// cast to (int|uint|float)64
|
||||
num := func(n interface{}) interface{} {
|
||||
switch n := n.(type) {
|
||||
case int:
|
||||
return int64(n)
|
||||
case int8:
|
||||
return int64(n)
|
||||
case int16:
|
||||
return int64(n)
|
||||
case int32:
|
||||
return int64(n)
|
||||
{
|
||||
// properly encode big numbers
|
||||
// before storing them as JSON
|
||||
|
||||
num := func(n interface{}) interface{} {
|
||||
switch n := n.(type) {
|
||||
case int:
|
||||
return int64(n)
|
||||
case int8:
|
||||
return int64(n)
|
||||
case int16:
|
||||
return int64(n)
|
||||
case int32:
|
||||
return int64(n)
|
||||
case int64:
|
||||
return int64(n)
|
||||
case uint:
|
||||
return uint64(n)
|
||||
case uintptr:
|
||||
return uint64(n)
|
||||
case uint8:
|
||||
return uint64(n)
|
||||
case uint16:
|
||||
return uint64(n)
|
||||
case uint32:
|
||||
return uint64(n)
|
||||
case uint64:
|
||||
return uint64(n)
|
||||
case float32:
|
||||
return float64(n)
|
||||
case float64:
|
||||
return n
|
||||
}
|
||||
return n
|
||||
}(in)
|
||||
|
||||
switch num := num.(type) {
|
||||
case int64:
|
||||
return n
|
||||
case uint:
|
||||
return uint64(n)
|
||||
case uintptr:
|
||||
return uint64(n)
|
||||
case uint8:
|
||||
return uint64(n)
|
||||
case uint16:
|
||||
return uint64(n)
|
||||
case uint32:
|
||||
return uint64(n)
|
||||
if !omitempty || num > 0 {
|
||||
m[key] = strconv.FormatInt(num, 10)
|
||||
}
|
||||
return
|
||||
case uint64:
|
||||
return n
|
||||
case float32:
|
||||
return float64(n)
|
||||
if !omitempty || num > 0 {
|
||||
m[key] = strconv.FormatUint(num, 10)
|
||||
}
|
||||
return
|
||||
|
||||
case float64:
|
||||
return n
|
||||
}
|
||||
return n
|
||||
}(in)
|
||||
if !omitempty || num > 0 {
|
||||
m[key] = in
|
||||
}
|
||||
|
||||
switch num := num.(type) {
|
||||
case nil:
|
||||
case uint64:
|
||||
if !omitempty || num > 0 {
|
||||
m[key] = in
|
||||
return
|
||||
}
|
||||
return
|
||||
|
||||
case int64:
|
||||
if !omitempty || num > 0 {
|
||||
m[key] = in
|
||||
}
|
||||
return
|
||||
|
||||
case float64:
|
||||
if !omitempty || num > 0 {
|
||||
m[key] = in
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// for the rest (slices, etc..)
|
||||
// for the rest (string, slices, etc..)
|
||||
// just set the value
|
||||
m[key] = in
|
||||
}
|
||||
|
||||
@ -36,10 +36,18 @@ func TestMeta_Set(t *testing.T) {
|
||||
{"bool true", true, false, Meta{"t": true}},
|
||||
{"bool false", false, false, Meta{"t": false}},
|
||||
|
||||
{"int value, omit", 1, true, Meta{"t": 1}},
|
||||
{"int value, keep", 1, false, Meta{"t": 1}},
|
||||
{"int value, omit", 1, true, Meta{"t": "1"}},
|
||||
{"int value, keep", 1, false, Meta{"t": "1"}},
|
||||
{"int empty, omit", 0, true, Meta{}},
|
||||
{"int empty, keep", 0, false, Meta{"t": 0}},
|
||||
{"int empty, keep", 0, false, Meta{"t": "0"}},
|
||||
{"uint64 empty, omit", uint64(0), true, Meta{}},
|
||||
{"uint64 empty, keep", uint64(0), false, Meta{"t": "0"}},
|
||||
{"bigint", 244783268048994492, false, Meta{"t": "244783268048994492"}},
|
||||
{"int64", int64(244783268048994492), false, Meta{"t": "244783268048994492"}},
|
||||
{"uint64()", uint64(244783268048994492), false, Meta{"t": "244783268048994492"}},
|
||||
{"int", 42, false, Meta{"t": "42"}},
|
||||
{"float64", float64(42), false, Meta{"t": float64(42)}},
|
||||
{"float64", float64(244783268048994492), false, Meta{"t": 2.447832680489945e+17}},
|
||||
|
||||
{"slice", []int{0, 1}, false, Meta{"t": []int{0, 1}}},
|
||||
|
||||
|
||||
@ -2,6 +2,8 @@ package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
@ -26,7 +28,8 @@ type (
|
||||
// provide user's email
|
||||
actionlogActionPayload struct {
|
||||
*actionlog.Action
|
||||
Actor string `json:"actor,omitempty"`
|
||||
Actor string `json:"actor,omitempty"`
|
||||
Meta map[string]interface{} `json:"meta,omitempty"`
|
||||
}
|
||||
|
||||
actionlogPayload struct {
|
||||
@ -78,6 +81,9 @@ func (ctrl Actionlog) makeFilterPayload(ctx context.Context, ee []*actionlog.Act
|
||||
// Remap events to payload structs
|
||||
for e := range ee {
|
||||
pp[e] = &actionlogActionPayload{Action: ee[e]}
|
||||
pp[e].Meta = ee[e].Meta
|
||||
|
||||
sanitizeMapStringInterface(pp[e].Meta)
|
||||
}
|
||||
|
||||
err = userPreloader(
|
||||
@ -115,6 +121,23 @@ func (ctrl Actionlog) makeFilterPayload(ctx context.Context, ee []*actionlog.Act
|
||||
return &actionlogPayload{Filter: f, Set: pp}, nil
|
||||
}
|
||||
|
||||
// Making sure JS can read our values
|
||||
func sanitizeMapStringInterface(m map[string]interface{}) {
|
||||
for k := range m {
|
||||
switch v := m[k].(type) {
|
||||
case float64:
|
||||
if strings.HasSuffix(k, "ID") {
|
||||
// make sure uint64 values on fields ending with ID
|
||||
// are properly encoded as strings
|
||||
m[k] = strconv.FormatUint(uint64(v), 10)
|
||||
}
|
||||
|
||||
case map[string]interface{}:
|
||||
sanitizeMapStringInterface(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Preloader collects all ids of users, loads them and sets them back
|
||||
//
|
||||
// We'll be accessing the store directly since this is protected with action-log.read operation check.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user