/*
This file is part of TALER
(C) 2018, 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-reserves-ID.c
* @brief implement GET /reserves/$RESERVE_PUB endpoint
* @author Christian Grothoff
*/
#include "platform.h"
#include
#include
#include
#include "taler-merchant-httpd.h"
#include "taler-merchant-httpd_mhd.h"
#include "taler-merchant-httpd_exchanges.h"
#include "taler-merchant-httpd_private-get-reserves-ID.h"
/**
* Closure for handle_reserve_details().
*/
struct GetReserveContext
{
/**
* Connection we are handling.
*/
struct MHD_Connection *connection;
/**
* Value to return from the callback.
*/
MHD_RESULT res;
/**
* Should we return details about tips?
*/
bool tips;
};
/**
* Callback with reserve details.
*
* @param cls closure with a `struct GetReserveContext`
* @param creation_time time when the reserve was setup
* @param expiration_time time when the reserve will be closed by the exchange
* @param merchant_initial_amount initial amount that the merchant claims to have filled the
* reserve with
* @param exchange_initial_amount initial amount that the exchange claims to have received
* @param picked_up_amount total of tips that were picked up from this reserve
* @param committed_amount total of tips that the merchant committed to, but that were not
* picked up yet
* @param tips_length length of the @a tips array
* @param tips information about the tips created by this reserve
*/
static void
handle_reserve_details (void *cls,
struct GNUNET_TIME_Absolute creation_time,
struct GNUNET_TIME_Absolute expiration_time,
const struct TALER_Amount *merchant_initial_amount,
const struct TALER_Amount *exchange_initial_amount,
const struct TALER_Amount *picked_up_amount,
const struct TALER_Amount *committed_amount,
unsigned int tips_length,
const struct TALER_MERCHANTDB_TipDetails *tips)
{
struct GetReserveContext *ctx = cls;
json_t *tips_json;
struct GNUNET_TIME_Absolute creation_time_round = creation_time;
struct GNUNET_TIME_Absolute expiration_time_round = expiration_time;
GNUNET_TIME_round_abs (&creation_time_round);
GNUNET_TIME_round_abs (&expiration_time_round);
if (NULL != tips)
{
tips_json = json_array ();
GNUNET_assert (NULL != tips_json);
for (unsigned int i = 0; ires = TALER_MHD_reply_json_pack (
ctx->connection,
MHD_HTTP_OK,
"{s:o, s:o, s:o, s:o, s:o, s:o, s:o?}",
"creation_time", GNUNET_JSON_from_time_abs (creation_time_round),
"expiration_time", GNUNET_JSON_from_time_abs (expiration_time_round),
"merchant_initial_amount", TALER_JSON_from_amount (merchant_initial_amount),
"exchange_initial_amount", TALER_JSON_from_amount (exchange_initial_amount),
"pickup_amount", TALER_JSON_from_amount (picked_up_amount),
"committed_amount", TALER_JSON_from_amount (committed_amount),
"tips", tips_json);
}
/**
* Manages a GET /reserves/$RESERVE_PUB 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_reserves_ID (const struct TMH_RequestHandler *rh,
struct MHD_Connection *connection,
struct TMH_HandlerContext *hc)
{
struct TALER_ReservePublicKeyP reserve_pub;
bool tips;
if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (hc->infix,
strlen (hc->infix),
&reserve_pub,
sizeof (reserve_pub)))
{
/* tip_id has wrong encoding */
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_PARAMETER_MALFORMED,
"reserve_pub malformed");
}
{
const char *tstr;
tstr = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND,
"tips");
tips = (NULL != tstr)
? 0 == strcasecmp (tstr, "yes")
: false;
}
{
struct GetReserveContext ctx = {
.connection = connection,
.tips = tips
};
enum GNUNET_DB_QueryStatus qs;
TMH_db->preflight (TMH_db->cls);
qs = TMH_db->lookup_reserve (TMH_db->cls,
hc->instance->settings.id,
&reserve_pub,
tips,
&handle_reserve_details,
&ctx);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
{
unsigned int response_code;
enum TALER_ErrorCode ec;
switch (qs)
{
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
ec = TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN;
response_code = MHD_HTTP_NOT_FOUND;
break;
case GNUNET_DB_STATUS_SOFT_ERROR:
ec = TALER_EC_TIP_PICKUP_DB_ERROR_SOFT;
response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
break;
case GNUNET_DB_STATUS_HARD_ERROR:
ec = TALER_EC_TIP_PICKUP_DB_ERROR_HARD;
response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
break;
default:
GNUNET_break (0);
ec = TALER_EC_INTERNAL_LOGIC_ERROR;
response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
break;
}
return TALER_MHD_reply_with_error (connection,
response_code,
ec,
"Could not determine exchange URL for the given tip id");
}
return ctx.res;
}
}
/* end of taler-merchant-httpd_private-get-reserves-ID.c */