From 581be9c1712e0774512fa3104fb760df76543133 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Mon, 14 Sep 2026 11:41:19 -0300 Subject: [PATCH] Added UnmarshalJson for the new token struct --- dtos/token.go | 30 ++++++++++++++++++++++++++++++ dtos/token_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/dtos/token.go b/dtos/token.go index 314d2d2b..1c013ec4 100644 --- a/dtos/token.go +++ b/dtos/token.go @@ -19,6 +19,36 @@ type Token struct { PushEnabled bool `json:"pushEnabled"` } +// UnmarshalJSON parses the legacy `pushEnabled` boolean when present, and otherwise falls back to +// `config.streaming.enabled` - some auth backends (e.g. the Configs auth service) have moved +// streaming capability there instead of the top-level field. When neither is present, PushEnabled +// defaults to false, matching the pre-existing zero-value behavior. +func (t *Token) UnmarshalJSON(raw []byte) error { + var shadow struct { + Token string `json:"token"` + PushEnabled *bool `json:"pushEnabled"` + Config *struct { + Streaming *struct { + Enabled *bool `json:"enabled"` + } `json:"streaming"` + } `json:"config"` + } + if err := json.Unmarshal(raw, &shadow); err != nil { + return err + } + + t.Token = shadow.Token + switch { + case shadow.PushEnabled != nil: + t.PushEnabled = *shadow.PushEnabled + case shadow.Config != nil && shadow.Config.Streaming != nil && shadow.Config.Streaming.Enabled != nil: + t.PushEnabled = *shadow.Config.Streaming.Enabled + default: + t.PushEnabled = false + } + return nil +} + // TokenPayload payload dto type TokenPayload struct { Capabilitites string `json:"x-ably-capability"` diff --git a/dtos/token_test.go b/dtos/token_test.go index 2441f757..c39ead66 100644 --- a/dtos/token_test.go +++ b/dtos/token_test.go @@ -1,12 +1,53 @@ package dtos import ( + "encoding/json" "testing" "time" "github.com/splitio/go-toolkit/v5/datastructures/set" ) +func TestTokenUnmarshalJSON(t *testing.T) { + // Legacy shape: top-level pushEnabled wins, config.streaming.enabled is ignored if present. + var legacy Token + if err := json.Unmarshal([]byte(`{"token":"abc","pushEnabled":true,"config":{"streaming":{"enabled":false}}}`), &legacy); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !legacy.PushEnabled { + t.Error("expected top-level pushEnabled to take precedence") + } + + var legacyFalse Token + if err := json.Unmarshal([]byte(`{"token":"abc","pushEnabled":false}`), &legacyFalse); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if legacyFalse.PushEnabled { + t.Error("expected pushEnabled=false to be honored") + } + + // New shape: no top-level pushEnabled, fall back to config.streaming.enabled. + var viaConfig Token + if err := json.Unmarshal([]byte(`{"token":"abc","config":{"streaming":{"enabled":true}}}`), &viaConfig); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !viaConfig.PushEnabled { + t.Error("expected config.streaming.enabled fallback to enable push") + } + if viaConfig.Token != "abc" { + t.Error("expected token field to still be parsed") + } + + // Neither field present: defaults to false, same as the zero value. + var neither Token + if err := json.Unmarshal([]byte(`{"token":"abc"}`), &neither); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if neither.PushEnabled { + t.Error("expected PushEnabled to default to false") + } +} + func TestTokenChannels(t *testing.T) { token := Token{ PushEnabled: false,