summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2024-03-18 23:09:15 +0100
committerChristian Grothoff <christian@grothoff.org>2024-03-18 23:09:15 +0100
commit42490d300851bf16e94d9ba19ed230fc41867e38 (patch)
tree7e2a3ad19af7c13e49408554447d43942f0cfafb /src
parent63c171f49aa4b3d6d412bf50d07a0fae4beab211 (diff)
downloadmerchant-42490d300851bf16e94d9ba19ed230fc41867e38.tar.gz
merchant-42490d300851bf16e94d9ba19ed230fc41867e38.tar.bz2
merchant-42490d300851bf16e94d9ba19ed230fc41867e38.zip
implement protocol v12, fixes #7948
Diffstat (limited to 'src')
-rw-r--r--src/backend/taler-merchant-httpd_config.c2
-rw-r--r--src/backend/taler-merchant-httpd_private-get-orders.c107
-rw-r--r--src/backend/taler-merchant-httpd_private-get-products.c20
-rw-r--r--src/backend/taler-merchant-httpd_private-get-transfers.c63
-rw-r--r--src/backenddb/pg_lookup_products.c44
-rw-r--r--src/backenddb/pg_lookup_products.h5
-rw-r--r--src/backenddb/test_merchantdb.c6
-rw-r--r--src/include/taler_merchant_service.h4
-rw-r--r--src/include/taler_merchantdb_plugin.h7
-rw-r--r--src/lib/merchant_api_get_config.c4
-rw-r--r--src/lib/merchant_api_get_products.c4
11 files changed, 127 insertions, 139 deletions
diff --git a/src/backend/taler-merchant-httpd_config.c b/src/backend/taler-merchant-httpd_config.c
index d020985b..969cf1ca 100644
--- a/src/backend/taler-merchant-httpd_config.c
+++ b/src/backend/taler-merchant-httpd_config.c
@@ -42,7 +42,7 @@
* #MERCHANT_PROTOCOL_CURRENT and #MERCHANT_PROTOCOL_AGE in
* merchant_api_config.c!
*/
-#define MERCHANT_PROTOCOL_VERSION "11:0:7"
+#define MERCHANT_PROTOCOL_VERSION "12:0:8"
/**
diff --git a/src/backend/taler-merchant-httpd_private-get-orders.c b/src/backend/taler-merchant-httpd_private-get-orders.c
index 92a1f389..5fc91188 100644
--- a/src/backend/taler-merchant-httpd_private-get-orders.c
+++ b/src/backend/taler-merchant-httpd_private-get-orders.c
@@ -687,44 +687,23 @@ TMH_private_get_orders (const struct TMH_RequestHandler *rh,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"wired");
+ po->of.delta = -20;
+ /* deprecated in protocol v12 */
+ TALER_MHD_parse_request_snumber (connection,
+ "delta",
+ &po->of.delta);
+ /* since protocol v12 */
+ TALER_MHD_parse_request_snumber (connection,
+ "limit",
+ &po->of.delta);
+ if ( (-MAX_DELTA > po->of.delta) ||
+ (po->of.delta > MAX_DELTA) )
{
- const char *delta_str;
-
- delta_str = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "delta");
- if (NULL == delta_str)
- {
- po->of.delta = -20;
- }
- else
- {
- char dummy;
- long long ll;
-
- if (1 !=
- sscanf (delta_str,
- "%lld%c",
- &ll,
- &dummy))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "delta");
- }
- po->of.delta = (int64_t) ll;
- if ( (-MAX_DELTA > po->of.delta) ||
- (po->of.delta > MAX_DELTA) )
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "delta");
- }
- }
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "delta");
}
{
const char *date_s_str;
@@ -769,43 +748,25 @@ TMH_private_get_orders (const struct TMH_RequestHandler *rh,
}
}
}
+ if (po->of.delta > 0)
+ po->of.start_row = 0;
+ else
+ po->of.start_row = INT64_MAX;
+ /* deprecated in protocol v12 */
+ TALER_MHD_parse_request_number (connection,
+ "start",
+ &po->of.start_row);
+ /* since protocol v12 */
+ TALER_MHD_parse_request_number (connection,
+ "offset",
+ &po->of.start_row);
+ if (INT64_MAX < po->of.start_row)
{
- const char *start_row_str;
-
- start_row_str = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "start");
- if (NULL == start_row_str)
- {
- if (po->of.delta > 0)
- po->of.start_row = 0;
- else
- po->of.start_row = INT64_MAX;
- }
- else
- {
- char dummy;
- unsigned long long ull;
-
- if (1 !=
- sscanf (start_row_str,
- "%llu%c",
- &ull,
- &dummy))
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "start");
- po->of.start_row = (uint64_t) ull;
- if (INT64_MAX < po->of.start_row)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "start");
- }
- }
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "start");
}
po->of.session_id
= MHD_lookup_connection_value (connection,
diff --git a/src/backend/taler-merchant-httpd_private-get-products.c b/src/backend/taler-merchant-httpd_private-get-products.c
index bc90c94d..d9fa4e49 100644
--- a/src/backend/taler-merchant-httpd_private-get-products.c
+++ b/src/backend/taler-merchant-httpd_private-get-products.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2019, 2020, 2021 Taler Systems SA
+ (C) 2019, 2020, 2021, 2024 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
@@ -30,6 +30,7 @@
*/
static void
add_product (void *cls,
+ uint64_t product_serial,
const char *product_id)
{
json_t *pa = cls;
@@ -38,6 +39,8 @@ add_product (void *cls,
json_array_append_new (
pa,
GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_uint64 ("product_serial",
+ product_serial),
GNUNET_JSON_pack_string ("product_id",
product_id))));
}
@@ -50,11 +53,26 @@ TMH_private_get_products (const struct TMH_RequestHandler *rh,
{
json_t *pa;
enum GNUNET_DB_QueryStatus qs;
+ int64_t limit;
+ uint64_t offset;
+ limit = 20; /* default */
+ TALER_MHD_parse_request_snumber (connection,
+ "limit",
+ &limit);
+ if (limit < 0)
+ offset = INT64_MAX;
+ else
+ offset = 0;
+ TALER_MHD_parse_request_number (connection,
+ "offset",
+ &offset);
pa = json_array ();
GNUNET_assert (NULL != pa);
qs = TMH_db->lookup_products (TMH_db->cls,
hc->instance->settings.id,
+ offset,
+ limit,
&add_product,
pa);
if (0 > qs)
diff --git a/src/backend/taler-merchant-httpd_private-get-transfers.c b/src/backend/taler-merchant-httpd_private-get-transfers.c
index c43781dd..3e540297 100644
--- a/src/backend/taler-merchant-httpd_private-get-transfers.c
+++ b/src/backend/taler-merchant-httpd_private-get-transfers.c
@@ -137,59 +137,16 @@ TMH_private_get_transfers (const struct TMH_RequestHandler *rh,
TALER_EC_GENERIC_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_GENERIC_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_GENERIC_PARAMETER_MALFORMED,
- "offset");
- offset = (uint64_t) o;
- }
- else
- {
- if (limit < 0)
- offset = INT64_MAX;
- else
- offset = 0;
- }
- }
+ TALER_MHD_parse_request_snumber (connection,
+ "limit",
+ &limit);
+ if (limit < 0)
+ offset = INT64_MAX;
+ else
+ offset = 0;
+ TALER_MHD_parse_request_number (connection,
+ "offset",
+ &offset);
if (! (TALER_arg_to_yna (connection,
"verified",
TALER_EXCHANGE_YNA_ALL,
diff --git a/src/backenddb/pg_lookup_products.c b/src/backenddb/pg_lookup_products.c
index d16aeb8d..fa2887a8 100644
--- a/src/backenddb/pg_lookup_products.c
+++ b/src/backenddb/pg_lookup_products.c
@@ -65,9 +65,12 @@ lookup_products_cb (void *cls,
for (unsigned int i = 0; i < num_results; i++)
{
char *product_id;
+ uint64_t product_serial;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_string ("product_id",
&product_id),
+ GNUNET_PQ_result_spec_uint64 ("product_serial",
+ &product_serial),
GNUNET_PQ_result_spec_end
};
@@ -81,6 +84,7 @@ lookup_products_cb (void *cls,
return;
}
plc->cb (plc->cb_cls,
+ product_serial,
product_id);
GNUNET_PQ_cleanup_result (rs);
}
@@ -90,10 +94,13 @@ lookup_products_cb (void *cls,
enum GNUNET_DB_QueryStatus
TMH_PG_lookup_products (void *cls,
const char *instance_id,
+ uint64_t offset,
+ int64_t limit,
TALER_MERCHANTDB_ProductsCallback cb,
void *cb_cls)
{
struct PostgresClosure *pg = cls;
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
struct LookupProductsContext plc = {
.cb = cb,
.cb_cls = cb_cls,
@@ -102,24 +109,45 @@ TMH_PG_lookup_products (void *cls,
};
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
check_connection (pg);
PREPARE (pg,
- "lookup_products",
+ "lookup_products_asc",
"SELECT"
- " product_id"
+ " product_id"
+ " ,product_serial"
" FROM merchant_inventory"
" JOIN merchant_instances"
" USING (merchant_serial)"
- " WHERE merchant_instances.merchant_id=$1");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "lookup_products",
- params,
- &lookup_products_cb,
- &plc);
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND product_serial > $2"
+ " ORDER BY product_serial ASC"
+ " LIMIT $3");
+ PREPARE (pg,
+ "lookup_products_desc",
+ "SELECT"
+ " product_id"
+ " ,product_serial"
+ " FROM merchant_inventory"
+ " JOIN merchant_instances"
+ " USING (merchant_serial)"
+ " WHERE merchant_instances.merchant_id=$1"
+ " AND product_serial < $2"
+ " ORDER BY product_serial DESC"
+ " LIMIT $3");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ (limit > 0)
+ ? "lookup_products_asc"
+ : "lookup_products_desc",
+ params,
+ &lookup_products_cb,
+ &plc);
/* If there was an error inside lookup_products_cb, return a hard error. */
if (plc.extract_failed)
return GNUNET_DB_STATUS_HARD_ERROR;
diff --git a/src/backenddb/pg_lookup_products.h b/src/backenddb/pg_lookup_products.h
index 398b5eac..d96328c8 100644
--- a/src/backenddb/pg_lookup_products.h
+++ b/src/backenddb/pg_lookup_products.h
@@ -30,6 +30,9 @@
*
* @param cls closure
* @param instance_id instance to lookup products for
+ * @param offset transfer_serial number of the transfer we want to offset from
+ * @param limit number of entries to return, negative for descending,
+ * positive for ascending
* @param cb function to call on all products found
* @param cb_cls closure for @a cb
* @return database result code
@@ -37,6 +40,8 @@
enum GNUNET_DB_QueryStatus
TMH_PG_lookup_products (void *cls,
const char *instance_id,
+ uint64_t offset,
+ int64_t limit,
TALER_MERCHANTDB_ProductsCallback cb,
void *cb_cls);
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index 53902b3d..60a0b08b 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -906,13 +906,17 @@ struct TestLookupProducts_Closure
* Function called after calling @e test_lookup_products
*
* @param cls a pointer to the lookup closure.
+ * @param product_serial DB row ID
* @param product_id the identifier of the product found.
*/
static void
lookup_products_cb (void *cls,
+ uint64_t product_serial,
const char *product_id)
{
struct TestLookupProducts_Closure *cmp = cls;
+
+ GNUNET_assert (product_serial > 0);
if (NULL == cmp)
return;
cmp->results_length += 1;
@@ -948,6 +952,8 @@ test_lookup_products (const struct InstanceData *instance,
memset (results_matching, 0, sizeof (unsigned int) * products_length);
if (0 > plugin->lookup_products (plugin->cls,
instance->instance.id,
+ 0,
+ 20,
&lookup_products_cb,
&cls))
{
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index 2ed51a29..6ddf3ee4 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -1386,6 +1386,10 @@ struct TALER_MERCHANT_InventoryEntry
*/
const char *product_id;
+ /**
+ * Serial ID of the product.
+ */
+ uint64_t product_serial;
};
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index 316b8678..404d0eb9 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -249,10 +249,12 @@ typedef void
* Typically called by `lookup_products`.
*
* @param cls a `json_t *` JSON array to build
+ * @param product_serial row ID of the product
* @param product_id ID of the product
*/
typedef void
(*TALER_MERCHANTDB_ProductsCallback)(void *cls,
+ uint64_t product_serial,
const char *product_id);
@@ -1584,6 +1586,9 @@ struct TALER_MERCHANTDB_Plugin
*
* @param cls closure
* @param instance_id instance to lookup products for
+ * @param offset transfer_serial number of the transfer we want to offset from
+ * @param limit number of entries to return, negative for descending,
+ * positive for ascending
* @param cb function to call on all products found
* @param cb_cls closure for @a cb
* @return database result code
@@ -1591,6 +1596,8 @@ struct TALER_MERCHANTDB_Plugin
enum GNUNET_DB_QueryStatus
(*lookup_products)(void *cls,
const char *instance_id,
+ uint64_t offset,
+ int64_t limit,
TALER_MERCHANTDB_ProductsCallback cb,
void *cb_cls);
diff --git a/src/lib/merchant_api_get_config.c b/src/lib/merchant_api_get_config.c
index 3f1471e3..3382c9f2 100644
--- a/src/lib/merchant_api_get_config.c
+++ b/src/lib/merchant_api_get_config.c
@@ -34,12 +34,12 @@
* Which version of the Taler protocol is implemented
* by this library? Used to determine compatibility.
*/
-#define MERCHANT_PROTOCOL_CURRENT 11
+#define MERCHANT_PROTOCOL_CURRENT 12
/**
* How many configs are we backwards-compatible with?
*/
-#define MERCHANT_PROTOCOL_AGE 6
+#define MERCHANT_PROTOCOL_AGE 0
/**
diff --git a/src/lib/merchant_api_get_products.c b/src/lib/merchant_api_get_products.c
index 01115094..21657cbd 100644
--- a/src/lib/merchant_api_get_products.c
+++ b/src/lib/merchant_api_get_products.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2023 Taler Systems SA
+ Copyright (C) 2014-2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -89,6 +89,8 @@ parse_products (const json_t *json,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("product_id",
&ie->product_id),
+ GNUNET_JSON_spec_uint64 ("product_serial",
+ &ie->product_serial),
GNUNET_JSON_spec_end ()
};