get raw bytes
Some checks failed
Build and Publish / BuildAndDeployArm64 (push) Failing after 1m38s
Build and Publish / BuildAndDeployAmd64 (push) Failing after 1m41s

This commit is contained in:
matst80
2025-11-18 22:27:49 +01:00
parent 7a7c577374
commit ba0e820956
2 changed files with 59 additions and 34 deletions

View File

@@ -2,6 +2,8 @@ package cart
import ( import (
"context" "context"
"encoding/json"
"fmt"
"reflect" "reflect"
"slices" "slices"
"strings" "strings"
@@ -9,7 +11,6 @@ import (
"time" "time"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
anypb "google.golang.org/protobuf/types/known/anypb"
"git.tornberg.me/go-cart-actor/pkg/actor" "git.tornberg.me/go-cart-actor/pkg/actor"
messages "git.tornberg.me/go-cart-actor/pkg/messages" messages "git.tornberg.me/go-cart-actor/pkg/messages"
@@ -462,12 +463,12 @@ func TestSubscriptionDetailsJSONValidation(t *testing.T) {
g := newTestGrain() g := newTestGrain()
// Valid JSON on create // Valid JSON on create
validCreate := &messages.UpsertSubscriptionDetails{ jsonStr := `{"offeringCode": "OFFJSON", "signingType": "TYPEJSON", "data": {"value": "eyJvayI6dHJ1ZX0="}}`
OfferingCode: "OFFJSON", var validCreate messages.UpsertSubscriptionDetails
SigningType: "TYPEJSON", if err := json.Unmarshal([]byte(jsonStr), &validCreate); err != nil {
Data: &anypb.Any{Value: []byte(`{"ok":true}`)}, t.Fatal(err)
} }
applyOK(t, reg, g, validCreate) applyOK(t, reg, g, &validCreate)
if len(g.SubscriptionDetails) != 1 { if len(g.SubscriptionDetails) != 1 {
t.Fatalf("expected one subscription detail after valid create, got %d", len(g.SubscriptionDetails)) t.Fatalf("expected one subscription detail after valid create, got %d", len(g.SubscriptionDetails))
} }
@@ -480,41 +481,45 @@ func TestSubscriptionDetailsJSONValidation(t *testing.T) {
} }
// Update with valid JSON replaces meta // Update with valid JSON replaces meta
updateValid := &messages.UpsertSubscriptionDetails{ jsonStr2 := fmt.Sprintf(`{"id": "%s", "data": {"value": "eyJjaGFuZ2VkIjoxMjN9"}}`, id)
Id: &id, var updateValid messages.UpsertSubscriptionDetails
Data: &anypb.Any{Value: []byte(`{"changed":123}`)}, if err := json.Unmarshal([]byte(jsonStr2), &updateValid); err != nil {
t.Fatal(err)
} }
applyOK(t, reg, g, updateValid) applyOK(t, reg, g, &updateValid)
if string(g.SubscriptionDetails[id].Meta) != `{"changed":123}` { if string(g.SubscriptionDetails[id].Meta) != `{"changed":123}` {
t.Fatalf("expected meta updated to new json, got %s", string(g.SubscriptionDetails[id].Meta)) t.Fatalf("expected meta updated to new json, got %s", string(g.SubscriptionDetails[id].Meta))
} }
// Invalid JSON on create // Invalid JSON on create
invalidCreate := &messages.UpsertSubscriptionDetails{ jsonStr3 := `{"offeringCode": "BAD", "signingType": "TYPE", "data": {"value": "eyJicm9rZW4iO30="}}`
OfferingCode: "BAD", var invalidCreate messages.UpsertSubscriptionDetails
Data: &anypb.Any{Value: []byte(`{"broken":}`)}, if err := json.Unmarshal([]byte(jsonStr3), &invalidCreate); err != nil {
t.Fatal(err)
} }
res := applyOne(t, reg, g, invalidCreate) res := applyOne(t, reg, g, &invalidCreate)
if res.Error == nil || !strings.Contains(res.Error.Error(), "invalid json") { if res.Error == nil || !strings.Contains(res.Error.Error(), "invalid json") {
t.Fatalf("expected invalid json error on create, got %v", res.Error) t.Fatalf("expected invalid json error on create, got %v", res.Error)
} }
// Invalid JSON on update // Invalid JSON on update
badUpdate := &messages.UpsertSubscriptionDetails{ jsonStr4 := fmt.Sprintf(`{"id": "%s", "data": {"value": "e29vcHM="}}`, id)
Id: &id, var badUpdate messages.UpsertSubscriptionDetails
Data: &anypb.Any{Value: []byte(`{oops`)}, if err := json.Unmarshal([]byte(jsonStr4), &badUpdate); err != nil {
t.Fatal(err)
} }
res2 := applyOne(t, reg, g, badUpdate) res2 := applyOne(t, reg, g, &badUpdate)
if res2.Error == nil || !strings.Contains(res2.Error.Error(), "invalid json") { if res2.Error == nil || !strings.Contains(res2.Error.Error(), "invalid json") {
t.Fatalf("expected invalid json error on update, got %v", res2.Error) t.Fatalf("expected invalid json error on update, got %v", res2.Error)
} }
// Empty Data.Value should not overwrite existing meta // Empty Data should not overwrite existing meta
emptyUpdate := &messages.UpsertSubscriptionDetails{ jsonStr5 := fmt.Sprintf(`{"id": "%s", "data": {"value": ""}}`, id)
Id: &id, var emptyUpdate messages.UpsertSubscriptionDetails
Data: &anypb.Any{Value: []byte{}}, if err := json.Unmarshal([]byte(jsonStr5), &emptyUpdate); err != nil {
t.Fatal(err)
} }
applyOK(t, reg, g, emptyUpdate) applyOK(t, reg, g, &emptyUpdate)
if string(g.SubscriptionDetails[id].Meta) != `{"changed":123}` { if string(g.SubscriptionDetails[id].Meta) != `{"changed":123}` {
t.Fatalf("empty update should not change meta, got %s", string(g.SubscriptionDetails[id].Meta)) t.Fatalf("empty update should not change meta, got %s", string(g.SubscriptionDetails[id].Meta))
} }

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
messages "git.tornberg.me/go-cart-actor/pkg/messages" messages "git.tornberg.me/go-cart-actor/pkg/messages"
"google.golang.org/protobuf/types/known/anypb"
) )
func UpsertSubscriptionDetails(g *CartGrain, m *messages.UpsertSubscriptionDetails) error { func UpsertSubscriptionDetails(g *CartGrain, m *messages.UpsertSubscriptionDetails) error {
@@ -12,15 +13,33 @@ func UpsertSubscriptionDetails(g *CartGrain, m *messages.UpsertSubscriptionDetai
return nil return nil
} }
// Helper to get data bytes from Data field
getDataBytes := func(data *anypb.Any) ([]byte, error) {
if data == nil {
return nil, nil
}
if len(data.Value) > 0 {
return data.Value, nil
}
if data.TypeUrl != "" {
return []byte(data.TypeUrl), nil
}
return nil, nil
}
// Create new subscription details when Id is nil. // Create new subscription details when Id is nil.
if m.Id == nil { if m.Id == nil {
// Validate JSON if provided. // Validate JSON if provided.
var meta json.RawMessage var meta json.RawMessage
if m.Data != nil && len(m.Data.Value) > 0 { dataBytes, err := getDataBytes(m.Data)
if !json.Valid(m.Data.Value) { if err != nil {
return err
}
if dataBytes != nil {
if !json.Valid(dataBytes) {
return fmt.Errorf("subscription details invalid json") return fmt.Errorf("subscription details invalid json")
} }
meta = json.RawMessage(m.Data.Value) meta = json.RawMessage(dataBytes)
} }
id := MustNewCartId().String() id := MustNewCartId().String()
@@ -49,16 +68,17 @@ func UpsertSubscriptionDetails(g *CartGrain, m *messages.UpsertSubscriptionDetai
existing.SigningType = m.SigningType existing.SigningType = m.SigningType
changed = true changed = true
} }
if m.Data != nil { dataBytes, err := getDataBytes(m.Data)
// Only validate & assign if there is content; empty -> leave as-is. if err != nil {
if len(m.Data.Value) > 0 { return err
if !json.Valid(m.Data.Value) { }
if dataBytes != nil {
if !json.Valid(dataBytes) {
return fmt.Errorf("subscription details invalid json") return fmt.Errorf("subscription details invalid json")
} }
existing.Meta = m.Data.Value existing.Meta = dataBytes
changed = true changed = true
} }
}
if changed { if changed {
existing.Version++ existing.Version++
} }