/* This file is part of TALER (C) 2014-2020 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ /** * @file backend/taler-merchant-httpd_private-get-transfers.c * @brief implement API for obtaining a list of wire transfers * @author Marcello Stanisci * @author Christian Grothoff */ #include "platform.h" #include #include #include "taler-merchant-httpd_private-get-transfers.h" /** * Function called with information about a wire transfer. * Generate a response (array entry) based on the given arguments. * * @param cls closure with a `json_t *` array to build up the response * @param credit_amount how much was wired to the merchant (minus fees) * @param wtid wire transfer identifier * @param payto_uri target account that received the wire transfer * @param exchange_url base URL of the exchange that made the wire transfer * @param transfer_serial_id serial number identifying the transfer in the backend * @param execution_time when did the exchange make the transfer, #GNUNET_TIME_UNIT_FOREVER_ABS * if it did not yet happen * @param verified YES if we checked the exchange's answer and liked it, * NO if we checked the exchange's answer and it is problematic, * ALL if we did not yet check */ static void transfer_cb (void *cls, const struct TALER_Amount *credit_amount, const struct TALER_WireTransferIdentifierRawP *wtid, const char *payto_uri, const char *exchange_url, uint64_t transfer_serial_id, struct GNUNET_TIME_Absolute execution_time, bool verified, bool confirmed) { json_t *ja = cls; json_t *r; r = json_pack ("{s:o, s:o, s:s, s:s, s:I}", "credit_amount", TALER_JSON_from_amount (credit_amount), "wtid", GNUNET_JSON_from_data_auto (wtid), "payto_uri", payto_uri, "exchange_url", exchange_url, "transfer_serial_id", (json_int_t) transfer_serial_id); GNUNET_assert (NULL != r); if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != execution_time.abs_value_us) GNUNET_assert (0 == json_object_set_new ( r, "execution_time", GNUNET_JSON_from_time_abs (execution_time))); GNUNET_assert (0 == json_object_set_new ( r, "verified", json_boolean (verified ? 1 : 0))); GNUNET_assert (0 == json_object_set_new ( r, "confirmed", json_boolean (confirmed ? 1 : 0))); GNUNET_assert (0 == json_array_append_new (ja, r)); } /** * Manages a GET /private/transfers call. * * @param rh context of the handler * @param connection the MHD connection to handle * @param[in,out] hc context with further information about the request * @return MHD result code */ MHD_RESULT TMH_private_get_transfers (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { const char *payto_uri; struct GNUNET_TIME_Absolute before = GNUNET_TIME_UNIT_FOREVER_ABS; struct GNUNET_TIME_Absolute after = GNUNET_TIME_UNIT_ZERO_ABS; int64_t limit = -20; uint64_t offset; enum TALER_EXCHANGE_YesNoAll verified; payto_uri = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "payto_uri"); { const char *before_s; before_s = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "before"); if ( (NULL != before_s) && (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (before_s, &before)) ) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_PARAMETER_MALFORMED, "before"); } { const char *after_s; after_s = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "after"); if ( (NULL != after_s) && (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (after_s, &after)) ) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_PARAMETER_MALFORMED, "after"); } { const char *limit_s; limit_s = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "limit"); if (NULL != limit_s) { char dummy[2]; long long l; if (1 != sscanf (limit_s, "%lld%1s", &l, dummy)) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_PARAMETER_MALFORMED, "limit"); limit = (int64_t) l; } } { const char *offset_s; offset_s = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "offset"); if (NULL != offset_s) { char dummy[2]; unsigned long long o; if (1 != sscanf (offset_s, "%llu%1s", &o, dummy)) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_PARAMETER_MALFORMED, "offset"); offset = (uint64_t) o; } else { if (limit < 0) offset = INT64_MAX; else offset = 0; } } if (! (TALER_arg_to_yna (connection, "verified", TALER_EXCHANGE_YNA_ALL, &verified)) ) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_PARAMETER_MALFORMED, "verified"); TMH_db->preflight (TMH_db->cls); { json_t *ja; enum GNUNET_DB_QueryStatus qs; ja = json_array (); GNUNET_assert (NULL != ja); qs = TMH_db->lookup_transfers (TMH_db->cls, hc->instance->settings.id, payto_uri, before, after, limit, offset, verified, &transfer_cb, ja); if (0 > qs) { /* Simple select queries should not cause serialization issues */ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); /* Always report on hard error as well to enable diagnostics */ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GET_TRANSFERS_DB_FETCH_ERROR, NULL); } return TALER_MHD_reply_json_pack (connection, MHD_HTTP_OK, "{s:o}", "transfers", ja); } } /* end of taler-merchant-httpd_track-transfer.c */