/*
This file is part of TALER
(C) 2014-2023 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 taler-merchant-httpd_get-rewards-ID.c
* @brief implementation of GET /rewards/$ID
* @author Marcello Stanisci
* @author Christian Grothoff
*/
#include "platform.h"
#include
#include
#include
#include
#include "taler-merchant-httpd_get-rewards-ID.h"
#include "taler-merchant-httpd_helper.h"
#include "taler-merchant-httpd_mhd.h"
#include "taler-merchant-httpd_qr.h"
char *
TMH_make_taler_reward_uri (struct MHD_Connection *con,
const struct TALER_RewardIdentifierP *reward_id,
const char *instance_id)
{
struct GNUNET_Buffer buf = { 0 };
GNUNET_assert (NULL != instance_id);
GNUNET_assert (NULL != reward_id);
if (GNUNET_OK !=
TMH_taler_uri_by_connection (con,
"reward",
instance_id,
&buf))
{
GNUNET_break (0);
return NULL;
}
/* Ensure previous part is slash-terminated */
GNUNET_buffer_write_path (&buf,
"");
GNUNET_buffer_write_data_encoded (&buf,
reward_id,
sizeof (*reward_id));
return GNUNET_buffer_reap_str (&buf);
}
char *
TMH_make_reward_status_url (struct MHD_Connection *con,
const struct TALER_RewardIdentifierP *reward_id,
const char *instance_id)
{
struct GNUNET_Buffer buf;
GNUNET_assert (NULL != instance_id);
GNUNET_assert (NULL != reward_id);
if (GNUNET_OK !=
TMH_base_url_by_connection (con,
instance_id,
&buf))
{
GNUNET_break (0);
return NULL;
}
GNUNET_buffer_write_path (&buf,
"rewards/");
GNUNET_buffer_write_data_encoded (&buf,
reward_id,
sizeof (*reward_id));
return GNUNET_buffer_reap_str (&buf);
}
MHD_RESULT
TMH_get_rewards_ID (const struct TMH_RequestHandler *rh,
struct MHD_Connection *connection,
struct TMH_HandlerContext *hc)
{
struct TALER_RewardIdentifierP reward_id;
enum GNUNET_DB_QueryStatus qs;
struct TALER_Amount total_authorized;
struct TALER_Amount total_picked_up;
struct GNUNET_TIME_Timestamp expiration;
char *exchange_url;
char *next_url;
struct TALER_ReservePrivateKeyP reserve_priv;
(void) rh;
if (GNUNET_OK !=
GNUNET_CRYPTO_hash_from_string (hc->infix,
&reward_id.hash))
{
/* reward_id has wrong encoding */
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
hc->infix);
}
TMH_db->preflight (TMH_db->cls);
qs = TMH_db->lookup_reward (TMH_db->cls,
hc->instance->settings.id,
&reward_id,
&total_authorized,
&total_picked_up,
&expiration,
&exchange_url,
&next_url,
&reserve_priv);
if (0 > qs)
{
/* single, read-only SQL statements should never cause
serialization problems */
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_GENERIC_DB_FETCH_FAILED,
NULL);
}
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Unknown reward id given: `%s'\n",
hc->infix);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_MERCHANT_GENERIC_REWARD_ID_UNKNOWN,
hc->infix);
}
/* Build response */
{
struct TALER_Amount remaining;
MHD_RESULT ret;
GNUNET_break (0 <=
TALER_amount_subtract (&remaining,
&total_authorized,
&total_picked_up));
if (TMH_MHD_test_html_desired (connection))
{
char *qr;
char *uri;
char *reward_status_url;
uri = TMH_make_taler_reward_uri (connection,
&reward_id,
hc->instance->settings.id);
reward_status_url = TMH_make_reward_status_url (connection,
&reward_id,
hc->instance->settings.id);
qr = TMH_create_qrcode (uri);
if (NULL == qr)
{
GNUNET_break (0);
GNUNET_free (uri);
ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_ALLOCATION_FAILURE,
"during QR code generation");
}
else
{
json_t *context;
context = GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("remaining_reward",
&remaining),
GNUNET_JSON_pack_string ("taler_reward_uri",
uri),
GNUNET_JSON_pack_string ("next_url",
next_url),
GNUNET_JSON_pack_string ("taler_reward_qrcode_svg",
qr));
ret = TALER_TEMPLATING_reply (connection,
( (0 == remaining.value) &&
(0 == remaining.fraction) )
? MHD_HTTP_GONE
: MHD_HTTP_OK,
( (0 == remaining.value) &&
(0 == remaining.fraction) )
? "depleted_reward"
: "offer_reward",
hc->instance->settings.id,
uri,
context);
json_decref (context);
}
GNUNET_free (reward_status_url);
GNUNET_free (uri);
GNUNET_free (qr);
}
else
{
ret = TALER_MHD_REPLY_JSON_PACK (
connection,
TALER_amount_is_zero (&remaining)
? MHD_HTTP_GONE
: MHD_HTTP_OK,
GNUNET_JSON_pack_string ("exchange_url",
exchange_url),
GNUNET_JSON_pack_string ("next_url",
next_url),
TALER_JSON_pack_amount ("reward_amount",
&remaining),
GNUNET_JSON_pack_timestamp ("expiration",
expiration));
}
GNUNET_free (exchange_url);
GNUNET_free (next_url);
return ret;
}
}
/* end of taler-merchant-httpd_get-rewards-ID.c */