Skip to content
This repository has been archived by the owner on Sep 12, 2019. It is now read-only.

Commit

Permalink
Auth response errors
Browse files Browse the repository at this point in the history
  • Loading branch information
bartekn committed Nov 7, 2017
1 parent d3f973b commit 22ccd32
Show file tree
Hide file tree
Showing 422 changed files with 54,242 additions and 382 deletions.
12 changes: 9 additions & 3 deletions readme_compliance.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,14 @@ The customer information that is exchanged between FIs is flexible but the typic
Respond with one of the following status codes:
* `200 OK` when sender/receiver is allowed and the payment should be processed,
* `202 Accepted` when your callback needs some time for processing,
* `400 Bad Request` when sender info is invalid.
* `403 Forbidden` when sender/receiver is denied.

Any other status code will be considered an error.

When `202 Accepted` is returned the response body should contain JSON object with a `pending` field which represents the estimated number of seconds needed for processing. For example, the following response means to try the payment again in an hour.
When `202 Accepted` is returned the response body should contain JSON object with `pending` field which represents the estimated number of seconds needed for processing. For example, the following response means to try the payment again in an hour.

When `400 Bad Request` is returned the response body should contain JSON object with `error` field with error string.

```json
{"pending": 3600}
Expand Down Expand Up @@ -212,11 +215,14 @@ The customer information (`sender`) that is exchanged between FIs is flexible bu
Respond with one of the following status codes:
* `200 OK` when your customer has allowed sharing his/her compliance information with the requesting FI.
* `202 Accepted` when your callback needs some time for processing, ie to ask the customer.
* `400 Bad Request` when request data is invalid.
* `403 Forbidden` when your customer has denied sharing his/her compliance information with the requesting FI.

Any other status code will be considered an error.

When `202 Accepted` is returned the response body should contain JSON object with `pending` field which represents estimated number of seconds needed for processing. For example, the following response means to try the payment again in an hour:
When `202 Accepted` is returned the response body should contain JSON object with `pending` field which represents estimated number of seconds needed for processing. For example, the following response means to try the payment again in an hour.

When `400 Bad Request` is returned the response body should contain JSON object with `error` field with error string.

```json
{"pending": 3600}
Expand Down Expand Up @@ -244,7 +250,7 @@ This callback should return `200 OK` status code and JSON object with the custom
}
```
### `callbacks.tx_status`
This callback should return the status of a transaction as explained in [`SEP-0001`](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md).
This callback should return the status of a transaction as explained in [`SEP-0004`](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0004.md).

#### Request

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,26 @@ func (rh *RequestHandler) HandlerAuth(c web.C, w http.ResponseWriter, r *http.Re
case http.StatusAccepted: // AuthStatusPending
response.TxStatus = compliance.AuthStatusPending

pendingResponse := struct {
Pending int `json:"pending"`
}{}
err := json.Unmarshal(body, &pendingResponse)
callbackResponse := callback.CallbackResponse{}
err := json.Unmarshal(body, &callbackResponse)
if err != nil {
// Set default value
response.Pending = 600
} else {
response.Pending = pendingResponse.Pending
response.Pending = callbackResponse.Pending
}
case http.StatusBadRequest: // AuthStatusError
response.TxStatus = compliance.AuthStatusError

callbackResponse := callback.CallbackResponse{}
err := json.Unmarshal(body, &callbackResponse)
if err != nil {
log.WithFields(log.Fields{
"status": resp.StatusCode,
"body": string(body),
}).Error("Error response from sanctions server")
} else {
response.Error = callbackResponse.Error
}
case http.StatusForbidden: // AuthStatusDenied
response.TxStatus = compliance.AuthStatusDenied
Expand Down Expand Up @@ -296,15 +307,26 @@ func (rh *RequestHandler) HandlerAuth(c web.C, w http.ResponseWriter, r *http.Re
case http.StatusAccepted: // AuthStatusPending
response.InfoStatus = compliance.AuthStatusPending

pendingResponse := struct {
Pending int `json:"pending"`
}{}
err := json.Unmarshal(body, &pendingResponse)
callbackResponse := callback.CallbackResponse{}
err := json.Unmarshal(body, &callbackResponse)
if err != nil {
// Set default value
response.Pending = 600
} else {
response.Pending = pendingResponse.Pending
response.Pending = callbackResponse.Pending
}
case http.StatusBadRequest: // AuthStatusError
response.InfoStatus = compliance.AuthStatusError

callbackResponse := callback.CallbackResponse{}
err := json.Unmarshal(body, &callbackResponse)
if err != nil {
log.WithFields(log.Fields{
"status": resp.StatusCode,
"body": string(body),
}).Error("Error response from sanctions server")
} else {
response.Error = callbackResponse.Error
}
case http.StatusForbidden: // AuthStatusDenied
response.InfoStatus = compliance.AuthStatusDenied
Expand Down Expand Up @@ -362,6 +384,7 @@ func (rh *RequestHandler) HandlerAuth(c web.C, w http.ResponseWriter, r *http.Re
}

if response.TxStatus == compliance.AuthStatusOk && response.InfoStatus == compliance.AuthStatusOk {
w.WriteHeader(http.StatusOK)
authorizedTransaction := &entities.AuthorizedTransaction{
TransactionID: hex.EncodeToString(transactionHash[:]),
Memo: base64.StdEncoding.EncodeToString(memoBytes[:]),
Expand All @@ -375,6 +398,12 @@ func (rh *RequestHandler) HandlerAuth(c web.C, w http.ResponseWriter, r *http.Re
server.Write(w, protocols.InternalServerError)
return
}
} else if response.TxStatus == compliance.AuthStatusDenied || response.InfoStatus == compliance.AuthStatusDenied {
w.WriteHeader(http.StatusForbidden)
} else if response.TxStatus == compliance.AuthStatusError || response.InfoStatus == compliance.AuthStatusError {
w.WriteHeader(http.StatusBadRequest)
} else if response.TxStatus == compliance.AuthStatusPending || response.InfoStatus == compliance.AuthStatusPending {
w.WriteHeader(http.StatusAccepted)
}

responseBody, err := response.Marshal()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,14 +387,35 @@ func TestRequestHandlerAuth(t *testing.T) {

statusCode, response := net.GetResponse(testServer, params)
responseString := strings.TrimSpace(string(response))
assert.Equal(t, 200, statusCode)
assert.Equal(t, 403, statusCode)
expected := test.StringToJSONMap(`{
"info_status": "ok",
"tx_status": "denied"
}`)
assert.Equal(t, expected, test.StringToJSONMap(responseString))
})

Convey("when sanctions server returns bad request it returns tx_status `error`", func() {
mockHTTPClient.On(
"PostForm",
"http://sanctions",
url.Values{"sender": {string(senderInfoJSON)}},
).Return(
net.BuildHTTPResponse(400, "{\"error\": \"Invalid name\"}"),
nil,
).Once()

statusCode, response := net.GetResponse(testServer, params)
responseString := strings.TrimSpace(string(response))
assert.Equal(t, 400, statusCode)
expected := test.StringToJSONMap(`{
"info_status": "ok",
"tx_status": "error",
"error": "Invalid name"
}`)
assert.Equal(t, expected, test.StringToJSONMap(responseString))
})

Convey("when sanctions server returns accepted it returns tx_status `pending`", func() {
mockHTTPClient.On(
"PostForm",
Expand All @@ -407,7 +428,7 @@ func TestRequestHandlerAuth(t *testing.T) {

statusCode, response := net.GetResponse(testServer, params)
responseString := strings.TrimSpace(string(response))
assert.Equal(t, 200, statusCode)
assert.Equal(t, 202, statusCode)
expected := test.StringToJSONMap(`{
"info_status": "ok",
"tx_status": "pending",
Expand Down Expand Up @@ -516,14 +537,41 @@ func TestRequestHandlerAuth(t *testing.T) {

statusCode, response := net.GetResponse(testServer, params)
responseString := strings.TrimSpace(string(response))
assert.Equal(t, 200, statusCode)
assert.Equal(t, 403, statusCode)
expected := test.StringToJSONMap(`{
"info_status": "denied",
"tx_status": "ok"
}`)
assert.Equal(t, expected, test.StringToJSONMap(responseString))
})

Convey("when ask_user server returns bad request it returns info_status `error`", func() {
mockHTTPClient.On(
"PostForm",
"http://ask_user",
url.Values{
"sender": {string(senderInfoJSON)},
"note": {attachment.Transaction.Note},
"amount": {"20.0000000"},
"asset_code": {"USD"},
"asset_issuer": {"GAMVF7G4GJC4A7JMFJWLUAEIBFQD5RT3DCB5DC5TJDEKQBBACQ4JZVEE"},
},
).Return(
net.BuildHTTPResponse(400, "{\"error\": \"Invalid name\"}"),
nil,
).Once()

statusCode, response := net.GetResponse(testServer, params)
responseString := strings.TrimSpace(string(response))
assert.Equal(t, 400, statusCode)
expected := test.StringToJSONMap(`{
"info_status": "error",
"tx_status": "ok",
"error": "Invalid name"
}`)
assert.Equal(t, expected, test.StringToJSONMap(responseString))
})

Convey("when ask_user server returns pending it returns info_status `pending`", func() {
mockHTTPClient.On(
"PostForm",
Expand All @@ -542,7 +590,7 @@ func TestRequestHandlerAuth(t *testing.T) {

statusCode, response := net.GetResponse(testServer, params)
responseString := strings.TrimSpace(string(response))
assert.Equal(t, 200, statusCode)
assert.Equal(t, 202, statusCode)
expected := test.StringToJSONMap(`{
"info_status": "pending",
"tx_status": "ok",
Expand All @@ -569,7 +617,7 @@ func TestRequestHandlerAuth(t *testing.T) {

statusCode, response := net.GetResponse(testServer, params)
responseString := strings.TrimSpace(string(response))
assert.Equal(t, 200, statusCode)
assert.Equal(t, 202, statusCode)
expected := test.StringToJSONMap(`{
"info_status": "pending",
"tx_status": "ok",
Expand Down Expand Up @@ -761,7 +809,7 @@ func TestRequestHandlerAuth(t *testing.T) {

statusCode, response := net.GetResponse(testServer, params)
responseString := strings.TrimSpace(string(response))
assert.Equal(t, 200, statusCode)
assert.Equal(t, 403, statusCode)
expected := test.StringToJSONMap(`{
"info_status": "denied",
"tx_status": "ok"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package compliance

// PendingResponse is a response from Sanctions and AskUser callbacks when they return 202 Accepted status
type PendingResponse struct {
// CallbackResponse is a response from Sanctions and AskUser callbacks when they return 202 Accepted or 400 Bad Requests statuses
type CallbackResponse struct {
// Estimated number of seconds till the sender can check back for a change in status.
Pending int `json:"pending"`
Pending int `json:"pending"`
Error string `json:"error"`
}
8 changes: 4 additions & 4 deletions vendor/manifest
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
{
"importpath": "github.com/Sirupsen/logrus",
"repository": "https://github.com/Sirupsen/logrus",
"revision": "61e43dc76f7ee59a82bdf3d71033dc12bea4c77d",
"revision": "68cec9f21fbf3ea8d8f98c044bc6ce05f17b267a",
"branch": "master"
},
{
"importpath": "github.com/Sirupsen/logrus/hooks/test",
"repository": "https://github.com/Sirupsen/logrus",
"revision": "61e43dc76f7ee59a82bdf3d71033dc12bea4c77d",
"revision": "68cec9f21fbf3ea8d8f98c044bc6ce05f17b267a",
"branch": "master",
"path": "/hooks/test"
},
Expand Down Expand Up @@ -476,13 +476,13 @@
{
"importpath": "github.com/stellar/go",
"repository": "https://github.com/stellar/go",
"revision": "d73c794a1a2352e7020ad728697aaa5664bc62fa",
"revision": "78d294bf7c2afe35e0cfef5c1e6e61aa38b1c04c",
"branch": "master"
},
{
"importpath": "github.com/stellar/go/protocols/compliance",
"repository": "https://github.com/stellar/go",
"revision": "a2a363c0c6943b1f477f33db3a32e7a28bfc403e",
"revision": "78d294bf7c2afe35e0cfef5c1e6e61aa38b1c04c",
"branch": "master",
"path": "/protocols/compliance"
},
Expand Down
28 changes: 28 additions & 0 deletions vendor/src/github.com/Sirupsen/logrus/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
# 0.11.5

* feature: add writer and writerlevel to entry (#372)

# 0.11.4

* bug: fix undefined variable on solaris (#493)

# 0.11.3

* formatter: configure quoting of empty values (#484)
* formatter: configure quoting character (default is `"`) (#484)
* bug: fix not importing io correctly in non-linux environments (#481)

# 0.11.2

* bug: fix windows terminal detection (#476)

# 0.11.1

* bug: fix tty detection with custom out (#471)

# 0.11.0

* performance: Use bufferpool to allocate (#370)
* terminal: terminal detection for app-engine (#343)
* feature: exit handler (#375)

# 0.10.0

* feature: Add a test hook (#180)
Expand Down
Loading

0 comments on commit 22ccd32

Please sign in to comment.