From b26496f0af5144515c32164e686d1320c35b33f8 Mon Sep 17 00:00:00 2001 From: Viorel Craescu Date: Sat, 1 Jun 2024 15:39:25 +0300 Subject: [PATCH] token expiresIn can be either string or integer --- api_auth.go | 11 ++-- api_auth_test.go | 5 +- client.go | 8 +-- types/types.go | 28 +++++++++- types/types_test.go | 131 ++++++++++++++++++++++++++++++++++++++------ util_test.go | 10 ++-- 6 files changed, 156 insertions(+), 37 deletions(-) diff --git a/api_auth.go b/api_auth.go index 85ff820..552a521 100644 --- a/api_auth.go +++ b/api_auth.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" + "github.com/vcraescu/go-oblio-api/types" "github.com/vcraescu/go-reqbuilder" ) @@ -26,11 +27,11 @@ func (r *generateTokenRequest) Validate() error { } type GenerateTokenResponse struct { - AccessToken string `json:"access_token,omitempty"` - ExpiresIn string `json:"expires_in,omitempty"` - TokenType string `json:"token_type,omitempty"` - Scope string `json:"scope,omitempty"` - RequestTime string `json:"request_time,omitempty"` + AccessToken string `json:"access_token,omitempty"` + ExpiresIn types.Int `json:"expires_in,omitempty"` + TokenType string `json:"token_type,omitempty"` + Scope string `json:"scope,omitempty"` + RequestTime types.Timestamp `json:"request_time,omitempty"` } func (c *Client) GenerateToken(ctx context.Context) (*GenerateTokenResponse, error) { diff --git a/api_auth_test.go b/api_auth_test.go index 4f15fd1..9fe570e 100644 --- a/api_auth_test.go +++ b/api_auth_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/vcraescu/go-oblio-api" "github.com/vcraescu/go-oblio-api/internal/testutil" + "github.com/vcraescu/go-oblio-api/types" "github.com/vcraescu/go-reqbuilder" ) @@ -52,9 +53,9 @@ func TestClient_GenerateAuthorizeToken(t *testing.T) { }, want: &oblio.GenerateTokenResponse{ AccessToken: accessToken, - ExpiresIn: "3600", + ExpiresIn: types.Int(3600), TokenType: "Bearer", - RequestTime: "100", + RequestTime: types.Timestamp(now), }, }, } diff --git a/client.go b/client.go index a1513bf..5c005ef 100644 --- a/client.go +++ b/client.go @@ -6,7 +6,6 @@ import ( "fmt" "net/http" "net/url" - "strconv" "sync" "time" @@ -116,12 +115,7 @@ func (c *Client) generateToken(ctx context.Context) (string, error) { return "", fmt.Errorf("generateAuthorizeToken: %w", err) } - ttl, err := strconv.Atoi(resp.ExpiresIn) - if err != nil { - return "", fmt.Errorf("invalid expiresIn: %w", err) - } - - if err := c.tokenStorage.Set(ctx, resp.AccessToken, time.Duration(ttl)-time.Second*10); err != nil { + if err := c.tokenStorage.Set(ctx, resp.AccessToken, time.Duration(resp.ExpiresIn)-time.Second*10); err != nil { return "", fmt.Errorf("set: %w", err) } diff --git a/types/types.go b/types/types.go index d516771..26a9d30 100644 --- a/types/types.go +++ b/types/types.go @@ -4,11 +4,12 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/google/go-querystring/query" "net/url" "strconv" "strings" "time" + + "github.com/google/go-querystring/query" ) type Marshaler interface { @@ -127,7 +128,7 @@ func (b Bool) EncodeValues(key string, v *url.Values) error { return nil } -type Int int +type Int int64 var _ Marshaler = (*Int)(nil) @@ -163,3 +164,26 @@ func (i *Int) UnmarshalJSON(data []byte) error { func (i Int) MarshalJSON() ([]byte, error) { return json.Marshal(fmt.Sprint(i)) } + +type Timestamp time.Time + +func (t *Timestamp) UnmarshalJSON(data []byte) error { + data = bytes.ReplaceAll(bytes.Trim(data, `"`), []byte("null"), nil) + + if len(data) == 0 { + return nil + } + + v, err := strconv.ParseInt(string(data), 10, 64) + if err != nil { + return fmt.Errorf("parseInt: %w", err) + } + + *t = Timestamp(time.Unix(v, 0)) + + return nil +} + +func (t Timestamp) MarshalJSON() ([]byte, error) { + return json.Marshal(time.Time(t).Unix()) +} diff --git a/types/types_test.go b/types/types_test.go index 66ca8a1..872dd39 100644 --- a/types/types_test.go +++ b/types/types_test.go @@ -2,14 +2,19 @@ package types_test import ( "encoding/json" - "github.com/google/go-querystring/query" + "fmt" "testing" + "time" + + "github.com/google/go-querystring/query" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/vcraescu/go-oblio-api/types" ) +var now = time.Now() + func TestDate_MarshalJSON(t *testing.T) { t.Parallel() @@ -33,8 +38,6 @@ func TestDate_MarshalJSON(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -93,8 +96,6 @@ func TestDate_UnmarshalJSON(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -140,8 +141,6 @@ func TestDate_EncodeValues(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -189,8 +188,6 @@ func TestBool_MarshalJSON(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -238,8 +235,6 @@ func TestBool_EncodeValues(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -320,8 +315,6 @@ func TestBool_UnmarshalJSON(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -370,8 +363,6 @@ func TestInt_MarshalJSON(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -445,8 +436,6 @@ func TestInt_UnmarshalJSON(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -464,3 +453,111 @@ func TestInt_UnmarshalJSON(t *testing.T) { }) } } + +func TestTimestamp_MarshalJSON(t *testing.T) { + t.Parallel() + + type args struct { + Date types.Timestamp `json:"timestamp"` + } + + tests := []struct { + name string + args args + want string + wantErr assert.ErrorAssertionFunc + }{ + { + name: "success", + args: args{ + Date: types.Timestamp(now), + }, + want: fmt.Sprintf(`{"timestamp":%d}`, now.Unix()), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := json.Marshal(tt.args) + + if tt.wantErr != nil { + tt.wantErr(t, err) + + return + } + + require.NoError(t, err) + require.JSONEq(t, tt.want, string(got)) + }) + } +} + +func TestTimestamp_UnmarshalJSON(t *testing.T) { + t.Parallel() + + type args struct { + js string + } + + type Got struct { + Timestamp types.Timestamp + } + + tests := []struct { + name string + args args + want types.Timestamp + wantErr assert.ErrorAssertionFunc + }{ + { + name: "empty string", + args: args{ + js: `{"timestamp":""}`, + }, + }, + { + name: "null", + args: args{ + js: `{"timestamp":null}`, + }, + }, + { + name: "string", + args: args{ + js: fmt.Sprintf(`{"timestamp":"%d"}`, now.Unix()), + }, + want: types.Timestamp(now), + }, + { + name: "integer", + args: args{ + js: fmt.Sprintf(`{"timestamp":%d}`, now.Unix()), + }, + want: types.Timestamp(now), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got := Got{} + err := json.Unmarshal([]byte(tt.args.js), &got) + + if tt.wantErr != nil { + tt.wantErr(t, err) + + return + } + + require.NoError(t, err) + require.Equal( + t, + time.Time(tt.want).Format(time.RFC3339), + time.Time(got.Timestamp).Format(time.RFC3339), + ) + }) + } +} diff --git a/util_test.go b/util_test.go index 30046fd..bd813dd 100644 --- a/util_test.go +++ b/util_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "net/http" "net/http/httptest" @@ -16,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/vcraescu/go-oblio-api" "github.com/vcraescu/go-oblio-api/internal/testutil" + "github.com/vcraescu/go-oblio-api/types" ) const ( @@ -24,6 +24,8 @@ const ( clientSecret = "test-client-secret" ) +var now = time.Now() + func StartServer(t *testing.T, respBody []byte, wantRequest testutil.HTTPRequestAssertionFunc) string { t.Helper() @@ -68,9 +70,9 @@ func NewAuthorizationHandler(t *testing.T) http.HandlerFunc { err = json.NewEncoder(w).Encode(oblio.GenerateTokenResponse{ AccessToken: accessToken, - ExpiresIn: fmt.Sprint(time.Hour.Seconds()), + ExpiresIn: types.Int(3600), TokenType: "Bearer", - RequestTime: "100", + RequestTime: types.Timestamp(now), }) require.NoError(t, err) } @@ -119,5 +121,5 @@ func RunTest(t *testing.T, test Test) { } require.NoError(t, err) - require.Equal(t, test.want, got) + require.EqualExportedValues(t, test.want, got) }