Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle StatResult.Code is empty string #54

Merged
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
8 changes: 8 additions & 0 deletions authapi/authapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func (api *AuthApi) Ping() (*PingResult, error) {
if err = json.Unmarshal(body, ret); err != nil {
return nil, err
}
ret.SyncCode()
return ret, nil
}

Expand All @@ -72,6 +73,7 @@ func (api *AuthApi) Check() (*CheckResult, error) {
if err = json.Unmarshal(body, ret); err != nil {
return nil, err
}
ret.SyncCode()
return ret, nil
}

Expand All @@ -98,6 +100,7 @@ func (api *AuthApi) Logo() (*LogoResult, error) {
if err = json.Unmarshal(body, ret); err != nil {
return nil, err
}
ret.SyncCode()
return ret, nil
}

Expand Down Expand Up @@ -145,6 +148,7 @@ func (api *AuthApi) Enroll(options ...func(*url.Values)) (*EnrollResult, error)
if err = json.Unmarshal(body, ret); err != nil {
return nil, err
}
ret.SyncCode()
return ret, nil
}

Expand Down Expand Up @@ -174,6 +178,7 @@ func (api *AuthApi) EnrollStatus(userid string,
if err = json.Unmarshal(body, ret); err != nil {
return nil, err
}
ret.SyncCode()
return ret, nil
}

Expand Down Expand Up @@ -239,6 +244,7 @@ func (api *AuthApi) Preauth(options ...func(*url.Values)) (*PreauthResult, error
if err = json.Unmarshal(body, ret); err != nil {
return nil, err
}
ret.SyncCode()
return ret, nil
}

Expand Down Expand Up @@ -348,6 +354,7 @@ func (api *AuthApi) Auth(factor string, options ...func(*url.Values)) (*AuthResu
if err = json.Unmarshal(body, ret); err != nil {
return nil, err
}
ret.SyncCode()
return ret, nil
}

Expand Down Expand Up @@ -377,5 +384,6 @@ func (api *AuthApi) AuthStatus(txid string) (*AuthStatusResult, error) {
if err = json.Unmarshal(body, ret); err != nil {
return nil, err
}
ret.SyncCode()
return ret, nil
}
41 changes: 39 additions & 2 deletions authapi/authapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"testing"
"time"

"github.com/duosecurity/duo_api_golang"
duoapi "github.com/duosecurity/duo_api_golang"
)

func buildAuthApi(url string, proxy func(*http.Request) (*url.URL, error)) *AuthApi {
Expand Down Expand Up @@ -203,7 +203,7 @@ func TestLogo(t *testing.T) {
}
}

// Test a failure logo reqeust / response.
// Test a failure logo request / response.
func TestLogoError(t *testing.T) {
ts := httptest.NewTLSServer(
http.HandlerFunc(
Expand Down Expand Up @@ -602,3 +602,40 @@ func TestAuthStatus(t *testing.T) {
t.Error("Unexpected response status msg: " + res.Response.Status_Msg)
}
}

// Test a response with empty code.
func TestEmptyResponseCode(t *testing.T) {
ts := httptest.NewTLSServer(
http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// Return a 400, as if the logo was not found.
w.WriteHeader(400)
fmt.Fprintln(w, `
{
"stat": "FAIL",
"code": "",
"message": "Code is empty",
"message_detail": "Deal with it"
}`)
}))
defer ts.Close()

duo := buildAuthApi(ts.URL, nil)

res, err := duo.Logo()
if err != nil {
t.Error("Failed TestCheck: " + err.Error())
}
if res.Stat != "FAIL" {
t.Error("Expected FAIL, but got " + res.Stat)
}
if res.Code == nil || *res.Code != 0 {
t.Error("Unexpected response code.")
}
if res.Message == nil || *res.Message != "Code is empty" {
t.Error("Unexpected message.")
}
if res.Message_Detail == nil || *res.Message_Detail != "Deal with it" {
t.Error("Unexpected message detail.")
}
}
35 changes: 31 additions & 4 deletions duoapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,41 @@ func (duoapi *DuoApi) buildOptions(options ...DuoApiOption) *requestOptions {
return opts
}

type NullableInt32 struct {
value *int32
}

// API calls will return a StatResult object. On success, Stat is 'OK'.
// On error, Stat is 'FAIL', and Code, Message, and Message_Detail
// contain error information.
type StatResult struct {
Stat string
Code *int32
Message *string
Message_Detail *string
Stat string `json:"stat"`
Ncode NullableInt32 `json:"code"`
Code *int32 `json:"-"`
Message *string `json:"message"`
Message_Detail *string `json:"message_detail"`
}

func (n *NullableInt32) UnmarshalJSON(data []byte) error {
var raw interface{}

if err := json.Unmarshal(data, &raw); err != nil {
return err
}

switch v := raw.(type) {
case float64:
intVal := int32(v)
n.value = &intVal
case string:
intVal := int32(0)
n.value = &intVal
}
return nil
}

func (s *StatResult) SyncCode() {
s.Code = s.Ncode.value
}

// SetCustomHTTPClient allows one to set a completely custom http client that
Expand Down
Loading