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

Commit

Permalink
Fix potential panics when making API calls that result in an HTTP 403…
Browse files Browse the repository at this point in the history
… response

* Add test to trigger panic on requesting addresses
* Fix panic on requsting addresses
* Add test for panic on forbidden when requesting cards
* Add test for panic on forbidden when requesting accounts
* Add test for panic on forbidden when requesting customers
* Add test for panic on forbidden when requesting direct-debits
* Add test for panic on forbidden when requesting merchants
* Return nil when an error is received fetching merchants
* Add test for panic on forbidden when requesting payments
* Return nil when an error is received creating scheduled payments
* Add test for panic on forbidden when requesting receipts
* Add test for panic on forbidden when working with savings-goals
* Add test for panic on forbidden when working with transactions
* Return nil when an error is received fetching transactions
* Fix test for panic on forbidden when working with payments
* Add test for panic on forbidden when working with users

Fixes #24
  • Loading branch information
billglover committed Jun 21, 2018
1 parent c845636 commit 8bf27dc
Show file tree
Hide file tree
Showing 15 changed files with 854 additions and 16 deletions.
42 changes: 42 additions & 0 deletions accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,45 @@ func testAccountBalance(t *testing.T, name, mock string) {
t.Error("should return an account balance matching the mock response", cross)
}
}

func TestAccountForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/accounts", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.Account(context.Background())
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return an account")
}
}

func TestBalanceForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/accounts/balance", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.AccountBalance(context.Background())
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return an account")
}
}
2 changes: 1 addition & 1 deletion addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (c *Client) AddressHistory(ctx context.Context) (*AddressHistory, *http.Res
var addr *AddressHistory
resp, err := c.Do(ctx, req, &addr)
if err != nil {
return addr, resp, err
return nil, resp, err
}

return addr, resp, nil
Expand Down
21 changes: 21 additions & 0 deletions addresses_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,24 @@ func testAddressHistory(t *testing.T, name, mock string) {
t.Error("should return addresses matching the mock response", cross)
}
}

func TestAddressHistoryForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/addresses", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.AddressHistory(context.Background())
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return any addresses")
}
}
21 changes: 21 additions & 0 deletions cards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,24 @@ func testCard(t *testing.T, name, mock string) {
t.Error("should return a card matching the mock response", cross)
}
}

func TestCardForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/cards", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.Card(context.Background())
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return a card")
}
}
21 changes: 21 additions & 0 deletions customers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,24 @@ func testCustomer(t *testing.T, name, mock string) {
t.Error("should return an identity matching the mock response", cross)
}
}

func TestCustomerForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/customers", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.Customer(context.Background())
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return a customer")
}
}
59 changes: 59 additions & 0 deletions directdebit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@ func testDirectDebits(t *testing.T, name, mock string) {
}
}

func TestDDMandatesForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/direct-debit/mandates", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.DirectDebitMandates(context.Background())
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return direct-debit mandates")
}
}

var ddMandateCases = []struct {
name string
uid string
Expand Down Expand Up @@ -142,6 +163,27 @@ func testDDMandate(t *testing.T, name, uid, mock string) {
}
}

func TestDDMandateForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/direct-debit/mandates/", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.DirectDebitMandate(context.Background(), "949404bd-d32e-4f1e-9759-4d6caee3137c")
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return a direct-debit mandate")
}
}

var deleteDDMandateCases = []struct {
name string
uid string
Expand Down Expand Up @@ -189,3 +231,20 @@ func testDeleteDDMandate(t *testing.T, name, uid string) {
t.Error("should return an empty body", cross, len(body))
}
}

func TestDDMandateDeleteForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/direct-debit/mandates/", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodDelete)
w.WriteHeader(http.StatusForbidden)
})

resp, err := client.DeleteDirectDebitMandate(context.Background(), "949404bd-d32e-4f1e-9759-4d6caee3137c")
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}
}
8 changes: 8 additions & 0 deletions merchants.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ func (c *Client) Merchant(ctx context.Context, uid string) (*Merchant, *http.Res

mer := new(Merchant)
resp, err := c.Do(ctx, req, mer)
if err != nil {
return nil, resp, err
}

return mer, resp, err
}

Expand All @@ -47,5 +51,9 @@ func (c *Client) MerchantLocation(ctx context.Context, mUID, lUID string) (*Merc

merLoc := new(MerchantLocation)
resp, err := c.Do(ctx, req, merLoc)
if err != nil {
return nil, resp, err
}

return merLoc, resp, err
}
42 changes: 42 additions & 0 deletions merchants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,27 @@ func testMerchant(t *testing.T, name, uid, mock string) {
}
}

func TestMerchantForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/merchants/", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.Merchant(context.Background(), "949404bd-d32e-4f1e-9759-4d6caee3137c")
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return a merchant")
}
}

var merchantLocationCases = []struct {
name string
mUID string
Expand Down Expand Up @@ -129,3 +150,24 @@ func testMerchantLocation(t *testing.T, name, mUID, lUID, mock string) {
t.Error("should return a merchant matching the mock response", cross)
}
}

func TestMerchantLocationForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/merchants/", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

got, resp, err := client.MerchantLocation(context.Background(), "949404bd-d32e-4f1e-9759-4d6caee3137c", "949404bd-d32e-4f1e-9759-4d6caee3137c")
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if got != nil {
t.Error("should not return a merchant location")
}
}
4 changes: 4 additions & 0 deletions payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ func (c *Client) CreateScheduledPayment(ctx context.Context, p ScheduledPayment)
}

resp, err := c.Do(ctx, req, nil)
if err != nil {
return "", resp, err
}

loc := resp.Header.Get("Location")
uid := path.Base(loc)
return uid, resp, err
Expand Down
86 changes: 86 additions & 0 deletions payments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,32 @@ func testLocalPayment(t *testing.T, name string, payment LocalPayment, mock stri
resp, err := client.MakeLocalPayment(context.Background(), payment)
checkNoError(t, err)
checkStatus(t, resp, http.StatusAccepted)
}

func TestLocalPaymentForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/payments/local", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodPost)
w.WriteHeader(http.StatusForbidden)
})

payment := LocalPayment{
Reference: "sample payment",
DestinationAccountUID: "99970be2-2bc7-49d3-8d23-ebef9f746ecf",
Payment: PaymentAmount{
Currency: "GBP",
Amount: 10.24,
},
}

resp, err := client.MakeLocalPayment(context.Background(), payment)
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}
}

var paymentsCasesScheduled = []struct {
Expand Down Expand Up @@ -171,6 +196,27 @@ func testScheduledPayment(t *testing.T, name string, mock string) {
}
}

func TestScheduledPaymentForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/payments/scheduled/", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

payments, resp, err := client.ScheduledPayments(context.Background())
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if payments != nil {
t.Error("should not return scheduled payments")
}
}

var paymentsCasesCreateScheduled = []struct {
name string
payment ScheduledPayment
Expand Down Expand Up @@ -260,3 +306,43 @@ func testCreateScheduledPayment(t *testing.T, name string, payment ScheduledPaym
t.Error("should return the correct UID", cross, id)
}
}

func TestCreateScheduledPaymentForbidden(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

mux.HandleFunc("/api/v1/payments/scheduled/", func(w http.ResponseWriter, r *http.Request) {
checkMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusForbidden)
})

payment := ScheduledPayment{
LocalPayment: LocalPayment{
Reference: "sample payment",
DestinationAccountUID: "99970be2-2bc7-49d3-8d23-ebef9f746ecf",
Payment: PaymentAmount{
Currency: "GBP",
Amount: 10.24,
},
},
Schedule: RecurrenceRule{
StartDate: "",
UntilDate: "",
Frequency: "",
Count: 2,
Interval: 2,
WeekStart: "MONDAY",
},
}

id, resp, err := client.CreateScheduledPayment(context.Background(), payment)
checkHasError(t, err)

if resp.StatusCode != http.StatusForbidden {
t.Error("should return HTTP 403 status")
}

if id != "" {
t.Error("should not return a payment ID")
}
}
Loading

0 comments on commit 8bf27dc

Please sign in to comment.