From 4d4ac495a4cca70d7ac14d01d0a0088f86e82ba1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 16 Apr 2017 02:39:11 +0200 Subject: test case of /payback done twice, handle 403-case in /payback handler, thereby also testing coin-with-payback history case in test logic (fixes #3887) --- src/exchange-lib/exchange_api_payback.c | 35 +++++++++++++++++++++++++++++++++ src/exchange-lib/test_exchange_api.c | 5 +++++ src/exchange/taler-exchange-httpd_db.c | 1 - src/include/taler_exchange_service.h | 3 ++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/exchange-lib/exchange_api_payback.c b/src/exchange-lib/exchange_api_payback.c index eff459693..30cd55cba 100644 --- a/src/exchange-lib/exchange_api_payback.c +++ b/src/exchange-lib/exchange_api_payback.c @@ -53,6 +53,11 @@ struct TALER_EXCHANGE_PaybackHandle */ char *json_enc; + /** + * Denomination key of the coin. + */ + const struct TALER_EXCHANGE_DenomPublicKey *pk; + /** * Handle for the request. */ @@ -181,6 +186,35 @@ handle_payback_finished (void *cls, /* This should never happen, either us or the exchange is buggy (or API version conflict); just pass JSON reply to the application */ break; + case MHD_HTTP_FORBIDDEN: + { + /* Insufficient funds, proof attached */ + json_t *history; + struct TALER_Amount total; + const struct TALER_EXCHANGE_DenomPublicKey *dki; + + dki = ph->pk; + history = json_object_get (json, + "history"); + if (GNUNET_OK != + TALER_EXCHANGE_verify_coin_history (dki->fee_deposit.currency, + &ph->coin_pub, + history, + &total)) + { + GNUNET_break_op (0); + response_code = 0; + } + ph->cb (ph->cb_cls, + response_code, + TALER_JSON_get_error_code (json), + &total, + GNUNET_TIME_UNIT_FOREVER_ABS, + NULL, + json); + TALER_EXCHANGE_payback_cancel (ph); + return; + } case MHD_HTTP_UNAUTHORIZED: /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we @@ -277,6 +311,7 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange, ph = GNUNET_new (struct TALER_EXCHANGE_PaybackHandle); ph->coin_pub = pr.coin_pub; ph->exchange = exchange; + ph->pk = pk; ph->cb = payback_cb; ph->cb_cls = payback_cb_cls; ph->url = MAH_path_to_url (exchange, "/payback"); diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c index 5b64e79bd..fb0c93eb1 100644 --- a/src/exchange-lib/test_exchange_api.c +++ b/src/exchange-lib/test_exchange_api.c @@ -3501,6 +3501,11 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.payback.ref = "payback-withdraw-coin-2a", .details.payback.amount = "EUR:0.5" }, + { .oc = OC_PAYBACK, + .label = "payback-2b", + .expected_response_code = MHD_HTTP_FORBIDDEN, + .details.payback.ref = "payback-withdraw-coin-2a", + .details.payback.amount = "EUR:0.5" }, { .oc = OC_DEPOSIT, .label = "payback-deposit-revoked", .expected_response_code = MHD_HTTP_NOT_FOUND, diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 57be19708..d7f91c892 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -2396,7 +2396,6 @@ TEH_DB_execute_payback (struct MHD_Connection *connection, if ( (0 == amount.fraction) && (0 == amount.value) ) { - GNUNET_break_op (0); TEH_plugin->rollback (TEH_plugin->cls, session); ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection, diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index bd8e281d3..c097dff1a 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -1403,7 +1403,8 @@ struct TALER_EXCHANGE_PaybackHandle; * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * 0 if the exchange's reply is bogus (fails to follow the protocol) * @param ec taler-specific error code, #TALER_EC_NONE on success - * @param amount amount the exchange will wire back for this coin + * @param amount amount the exchange will wire back for this coin, + * on error the total balance remaining, or NULL * @param timestamp what time did the exchange receive the /payback request * @param reserve_pub public key of the reserve receiving the payback * @param full_response full response from the exchange (for logging, in case of errors) -- cgit v1.2.3