Skip to content

Commit a315391

Browse files
fix: allow clearing organization domains by sending empty arrays (#522)
Co-authored-by: Garen J. Torikian <gjtorikian@users.noreply.github.com>
1 parent 0212325 commit a315391

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

pkg/organizations/client.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,38 @@ type UpdateOrganizationOpts struct {
228228
Metadata map[string]*string `json:"metadata,omitempty"`
229229
}
230230

231+
// MarshalJSON implements custom JSON marshaling for UpdateOrganizationOpts.
232+
// The standard omitempty tag omits both nil and empty slices, making it
233+
// impossible to send an empty array to clear domains. This marshaler omits
234+
// Domains and DomainData only when nil, while preserving empty slices as [].
235+
func (o UpdateOrganizationOpts) MarshalJSON() ([]byte, error) {
236+
m := make(map[string]interface{})
237+
238+
if o.Name != "" {
239+
m["name"] = o.Name
240+
}
241+
if o.AllowProfilesOutsideOrganization {
242+
m["allow_profiles_outside_organization"] = o.AllowProfilesOutsideOrganization
243+
}
244+
if o.Domains != nil {
245+
m["domains"] = o.Domains
246+
}
247+
if o.DomainData != nil {
248+
m["domain_data"] = o.DomainData
249+
}
250+
if o.ExternalID != "" {
251+
m["external_id"] = o.ExternalID
252+
}
253+
if o.StripeCustomerID != "" {
254+
m["stripe_customer_id"] = o.StripeCustomerID
255+
}
256+
if o.Metadata != nil {
257+
m["metadata"] = o.Metadata
258+
}
259+
260+
return json.Marshal(m)
261+
}
262+
231263
// ListOrganizationsOpts contains the options to request Organizations.
232264
type ListOrganizationRolesOpts struct {
233265
// The Organization's unique identifier.

pkg/organizations/client_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,87 @@ func TestUpdateOrganization(t *testing.T) {
624624
}
625625
}
626626

627+
func TestUpdateOrganizationOptsMarshalJSON(t *testing.T) {
628+
tests := []struct {
629+
scenario string
630+
opts UpdateOrganizationOpts
631+
shouldExist map[string]bool
632+
wantValue map[string]string
633+
}{
634+
{
635+
scenario: "nil Domains and DomainData are omitted",
636+
opts: UpdateOrganizationOpts{
637+
Name: "Foo Corp",
638+
},
639+
shouldExist: map[string]bool{
640+
"domains": false,
641+
"domain_data": false,
642+
"name": true,
643+
},
644+
},
645+
{
646+
scenario: "empty Domains slice serializes as empty array",
647+
opts: UpdateOrganizationOpts{
648+
Name: "Foo Corp",
649+
Domains: []string{},
650+
},
651+
shouldExist: map[string]bool{
652+
"domains": true,
653+
"name": true,
654+
},
655+
wantValue: map[string]string{
656+
"domains": "[]",
657+
},
658+
},
659+
{
660+
scenario: "empty DomainData slice serializes as empty array",
661+
opts: UpdateOrganizationOpts{
662+
Name: "Foo Corp",
663+
DomainData: []OrganizationDomainData{},
664+
},
665+
shouldExist: map[string]bool{
666+
"domain_data": true,
667+
"name": true,
668+
},
669+
wantValue: map[string]string{
670+
"domain_data": "[]",
671+
},
672+
},
673+
{
674+
scenario: "populated Domains serializes normally",
675+
opts: UpdateOrganizationOpts{
676+
Name: "Foo Corp",
677+
Domains: []string{"foo.com"},
678+
},
679+
shouldExist: map[string]bool{
680+
"domains": true,
681+
},
682+
wantValue: map[string]string{
683+
"domains": `["foo.com"]`,
684+
},
685+
},
686+
}
687+
688+
for _, test := range tests {
689+
t.Run(test.scenario, func(t *testing.T) {
690+
data, err := json.Marshal(test.opts)
691+
require.NoError(t, err)
692+
693+
var raw map[string]json.RawMessage
694+
require.NoError(t, json.Unmarshal(data, &raw))
695+
696+
for key, shouldExist := range test.shouldExist {
697+
_, exists := raw[key]
698+
require.Equal(t, shouldExist, exists, "key %q existence mismatch", key)
699+
}
700+
701+
for key, want := range test.wantValue {
702+
require.JSONEq(t, want, string(raw[key]), "key %q value mismatch", key)
703+
}
704+
})
705+
}
706+
}
707+
627708
func updateOrganizationTestHandler(w http.ResponseWriter, r *http.Request) {
628709
auth := r.Header.Get("Authorization")
629710
if auth != "Bearer test" {

0 commit comments

Comments
 (0)