Skip to content
This repository has been archived by the owner on Feb 16, 2022. It is now read-only.

Fix JSON encode/decode of lifetime_in_seconds #213

Merged
merged 1 commit into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 62 additions & 1 deletion management/client.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package management

import (
"encoding/json"
"fmt"
"strconv"

"gopkg.in/auth0.v5"
)

type Client struct {
// The name of the client
Name *string `json:"name,omitempty"`
Expand Down Expand Up @@ -88,7 +96,7 @@ type Client struct {

type ClientJWTConfiguration struct {
// The amount of seconds the JWT will be valid (affects exp claim)
LifetimeInSeconds *int `json:"lifetime_in_seconds,omitempty"`
LifetimeInSeconds *int `json:"-"`

// True if the client secret is base64 encoded, false otherwise. Defaults to
// true
Expand Down Expand Up @@ -196,3 +204,56 @@ func (m *ClientManager) RotateSecret(id string, opts ...RequestOption) (c *Clien
func (m *ClientManager) Delete(id string, opts ...RequestOption) error {
return m.Request("DELETE", m.URI("clients", id), nil, opts...)
}

// UnmarshalJSON implements the json.Unmarshaler interface.
//
// It is required to handle the json field lifetime_in_seconds, which can either
// be an int, or a string in older tenants.
func (jc *ClientJWTConfiguration) UnmarshalJSON(b []byte) error {
type clientJWTConfiguration ClientJWTConfiguration
type clientJWTConfigurationWrapper struct {
*clientJWTConfiguration
RawLifetimeInSeconds interface{} `json:"lifetime_in_seconds,omitempty"`
}

alias := &clientJWTConfigurationWrapper{(*clientJWTConfiguration)(jc), nil}

err := json.Unmarshal(b, alias)
if err != nil {
return err
}

unexpectedTypeError := fmt.Errorf("unexpected type for field lifetime_in_seconds")

if alias.RawLifetimeInSeconds != nil {
switch rawLifetimeInSeconds := alias.RawLifetimeInSeconds.(type) {
case float64:
jc.LifetimeInSeconds = auth0.Int(int(rawLifetimeInSeconds))
case string:
value, err := strconv.Atoi(rawLifetimeInSeconds)
if err != nil {
return unexpectedTypeError
}
jc.LifetimeInSeconds = &value
default:
return unexpectedTypeError
}
}

return nil
}

func (jc *ClientJWTConfiguration) MarshalJSON() ([]byte, error) {
type clientJWTConfiguration ClientJWTConfiguration
type clientJWTConfigurationWrapper struct {
*clientJWTConfiguration
RawLifetimeInSeconds interface{} `json:"lifetime_in_seconds,omitempty"`
}

alias := &clientJWTConfigurationWrapper{(*clientJWTConfiguration)(jc), nil}
if jc.LifetimeInSeconds != nil {
alias.RawLifetimeInSeconds = jc.LifetimeInSeconds
}

return json.Marshal(alias)
}
34 changes: 34 additions & 0 deletions management/client_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package management

import (
"encoding/json"
"strings"
"testing"
"time"

"gopkg.in/auth0.v5"
"gopkg.in/auth0.v5/internal/testing/expect"
)

func TestClient(t *testing.T) {
Expand Down Expand Up @@ -78,3 +80,35 @@ func TestClient(t *testing.T) {
}
})
}

func TestJWTConfiguration(t *testing.T) {

t.Run("MarshalJSON", func(t *testing.T) {
for u, expected := range map[*ClientJWTConfiguration]string{
{}: `{}`,
{LifetimeInSeconds: auth0.Int(1000)}: `{"lifetime_in_seconds":1000}`,
} {
b, err := json.Marshal(u)
if err != nil {
t.Error(err)
}
expect.Expect(t, string(b), expected)
}
})

t.Run("UnmarshalJSON", func(t *testing.T) {
for b, expected := range map[string]*ClientJWTConfiguration{
`{}`: {LifetimeInSeconds: nil},
`{"lifetime_in_seconds":1000}`: {LifetimeInSeconds: auth0.Int(1000)},
`{"lifetime_in_seconds":"1000"}`: {LifetimeInSeconds: auth0.Int(1000)},
} {
var jc ClientJWTConfiguration
err := json.Unmarshal([]byte(b), &jc)
if err != nil {
t.Error(err)
}
expect.Expect(t, jc.GetLifetimeInSeconds(), expected.GetLifetimeInSeconds())
}
})

}