Skip to content

Commit 8aff7fd

Browse files
authored
Merge pull request #54 from DenitsaTH/ztat-1014-handle-codeless-error
Handle StatResult.Code is empty string
2 parents cb17708 + 2d1f351 commit 8aff7fd

File tree

3 files changed

+78
-6
lines changed

3 files changed

+78
-6
lines changed

authapi/authapi.go

+8
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func (api *AuthApi) Ping() (*PingResult, error) {
4848
if err = json.Unmarshal(body, ret); err != nil {
4949
return nil, err
5050
}
51+
ret.SyncCode()
5152
return ret, nil
5253
}
5354

@@ -72,6 +73,7 @@ func (api *AuthApi) Check() (*CheckResult, error) {
7273
if err = json.Unmarshal(body, ret); err != nil {
7374
return nil, err
7475
}
76+
ret.SyncCode()
7577
return ret, nil
7678
}
7779

@@ -98,6 +100,7 @@ func (api *AuthApi) Logo() (*LogoResult, error) {
98100
if err = json.Unmarshal(body, ret); err != nil {
99101
return nil, err
100102
}
103+
ret.SyncCode()
101104
return ret, nil
102105
}
103106

@@ -145,6 +148,7 @@ func (api *AuthApi) Enroll(options ...func(*url.Values)) (*EnrollResult, error)
145148
if err = json.Unmarshal(body, ret); err != nil {
146149
return nil, err
147150
}
151+
ret.SyncCode()
148152
return ret, nil
149153
}
150154

@@ -174,6 +178,7 @@ func (api *AuthApi) EnrollStatus(userid string,
174178
if err = json.Unmarshal(body, ret); err != nil {
175179
return nil, err
176180
}
181+
ret.SyncCode()
177182
return ret, nil
178183
}
179184

@@ -239,6 +244,7 @@ func (api *AuthApi) Preauth(options ...func(*url.Values)) (*PreauthResult, error
239244
if err = json.Unmarshal(body, ret); err != nil {
240245
return nil, err
241246
}
247+
ret.SyncCode()
242248
return ret, nil
243249
}
244250

@@ -348,6 +354,7 @@ func (api *AuthApi) Auth(factor string, options ...func(*url.Values)) (*AuthResu
348354
if err = json.Unmarshal(body, ret); err != nil {
349355
return nil, err
350356
}
357+
ret.SyncCode()
351358
return ret, nil
352359
}
353360

@@ -377,5 +384,6 @@ func (api *AuthApi) AuthStatus(txid string) (*AuthStatusResult, error) {
377384
if err = json.Unmarshal(body, ret); err != nil {
378385
return nil, err
379386
}
387+
ret.SyncCode()
380388
return ret, nil
381389
}

authapi/authapi_test.go

+39-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"testing"
1313
"time"
1414

15-
"github.com/duosecurity/duo_api_golang"
15+
duoapi "github.com/duosecurity/duo_api_golang"
1616
)
1717

1818
func buildAuthApi(url string, proxy func(*http.Request) (*url.URL, error)) *AuthApi {
@@ -203,7 +203,7 @@ func TestLogo(t *testing.T) {
203203
}
204204
}
205205

206-
// Test a failure logo reqeust / response.
206+
// Test a failure logo request / response.
207207
func TestLogoError(t *testing.T) {
208208
ts := httptest.NewTLSServer(
209209
http.HandlerFunc(
@@ -602,3 +602,40 @@ func TestAuthStatus(t *testing.T) {
602602
t.Error("Unexpected response status msg: " + res.Response.Status_Msg)
603603
}
604604
}
605+
606+
// Test a response with empty code.
607+
func TestEmptyResponseCode(t *testing.T) {
608+
ts := httptest.NewTLSServer(
609+
http.HandlerFunc(
610+
func(w http.ResponseWriter, r *http.Request) {
611+
// Return a 400, as if the logo was not found.
612+
w.WriteHeader(400)
613+
fmt.Fprintln(w, `
614+
{
615+
"stat": "FAIL",
616+
"code": "",
617+
"message": "Code is empty",
618+
"message_detail": "Deal with it"
619+
}`)
620+
}))
621+
defer ts.Close()
622+
623+
duo := buildAuthApi(ts.URL, nil)
624+
625+
res, err := duo.Logo()
626+
if err != nil {
627+
t.Error("Failed TestCheck: " + err.Error())
628+
}
629+
if res.Stat != "FAIL" {
630+
t.Error("Expected FAIL, but got " + res.Stat)
631+
}
632+
if res.Code == nil || *res.Code != 0 {
633+
t.Error("Unexpected response code.")
634+
}
635+
if res.Message == nil || *res.Message != "Code is empty" {
636+
t.Error("Unexpected message.")
637+
}
638+
if res.Message_Detail == nil || *res.Message_Detail != "Deal with it" {
639+
t.Error("Unexpected message detail.")
640+
}
641+
}

duoapi.go

+31-4
Original file line numberDiff line numberDiff line change
@@ -259,14 +259,41 @@ func (duoapi *DuoApi) buildOptions(options ...DuoApiOption) *requestOptions {
259259
return opts
260260
}
261261

262+
type NullableInt32 struct {
263+
value *int32
264+
}
265+
262266
// API calls will return a StatResult object. On success, Stat is 'OK'.
263267
// On error, Stat is 'FAIL', and Code, Message, and Message_Detail
264268
// contain error information.
265269
type StatResult struct {
266-
Stat string
267-
Code *int32
268-
Message *string
269-
Message_Detail *string
270+
Stat string `json:"stat"`
271+
Ncode NullableInt32 `json:"code"`
272+
Code *int32 `json:"-"`
273+
Message *string `json:"message"`
274+
Message_Detail *string `json:"message_detail"`
275+
}
276+
277+
func (n *NullableInt32) UnmarshalJSON(data []byte) error {
278+
var raw interface{}
279+
280+
if err := json.Unmarshal(data, &raw); err != nil {
281+
return err
282+
}
283+
284+
switch v := raw.(type) {
285+
case float64:
286+
intVal := int32(v)
287+
n.value = &intVal
288+
case string:
289+
intVal := int32(0)
290+
n.value = &intVal
291+
}
292+
return nil
293+
}
294+
295+
func (s *StatResult) SyncCode() {
296+
s.Code = s.Ncode.value
270297
}
271298

272299
// SetCustomHTTPClient allows one to set a completely custom http client that

0 commit comments

Comments
 (0)