diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-03-18 23:09:15 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-03-18 23:09:15 +0100 |
commit | 42490d300851bf16e94d9ba19ed230fc41867e38 (patch) | |
tree | 7e2a3ad19af7c13e49408554447d43942f0cfafb /src | |
parent | 63c171f49aa4b3d6d412bf50d07a0fae4beab211 (diff) | |
download | merchant-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.c | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-orders.c | 107 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-products.c | 20 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-transfers.c | 63 | ||||
-rw-r--r-- | src/backenddb/pg_lookup_products.c | 44 | ||||
-rw-r--r-- | src/backenddb/pg_lookup_products.h | 5 | ||||
-rw-r--r-- | src/backenddb/test_merchantdb.c | 6 | ||||
-rw-r--r-- | src/include/taler_merchant_service.h | 4 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 7 | ||||
-rw-r--r-- | src/lib/merchant_api_get_config.c | 4 | ||||
-rw-r--r-- | src/lib/merchant_api_get_products.c | 4 |
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 () }; |