commit beac1c1695d8a74864eac9461b9d5d9b0e0e3ae2
parent 3a52aa07dbef186b9f44268487c5c1d75e7aff7d
Author: Christian Grothoff <christian@grothoff.org>
Date: Fri, 26 Sep 2025 19:09:02 +0200
cleanups related to #10454
Diffstat:
7 files changed, 86 insertions(+), 53 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c
@@ -1183,7 +1183,6 @@ phase_redirect_to_paid_order (struct GetOrderData *god)
GNUNET_free (already_paid_order_id);
return ret;
}
- GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
GNUNET_free (already_paid_order_id);
}
god->phase++;
diff --git a/src/backend/taler-merchant-httpd_private-get-donau-instances.c b/src/backend/taler-merchant-httpd_private-get-donau-instances.c
@@ -40,7 +40,7 @@
* @param charity_max_per_year the maximum donation amount per year
* @param charity_receipts_to_date the total donations received so far this year
* @param current_year the current year being tracked for donations
- * @param donau_keys_json JSON object with key information specific to the Donau instance
+ * @param donau_keys_json JSON object with key information specific to the Donau instance, NULL if not (yet) available.
*/
static void
add_donau_instance (void *cls,
@@ -76,8 +76,9 @@ add_donau_instance (void *cls,
charity_receipts_to_date),
GNUNET_JSON_pack_int64 ("current_year",
current_year),
- GNUNET_JSON_pack_object_incref ("donau_keys_json",
- (json_t *) donau_keys_json)
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_object_incref ("donau_keys_json",
+ (json_t *) donau_keys_json))
)));
}
@@ -118,4 +119,4 @@ TMH_private_get_donau_instances (const struct TMH_RequestHandler *rh,
GNUNET_JSON_pack_array_steal (
"donau_instances",
json_donau_instances));
-}
-\ No newline at end of file
+}
diff --git a/src/backenddb/pg_insert_donau_instance.c b/src/backenddb/pg_insert_donau_instance.c
@@ -69,20 +69,20 @@ TMH_PG_insert_donau_instance (
" FROM merchant_instances mi"
" WHERE mi.merchant_pub = $3),"
" $4, $5, $6, $7);");
-
PREPARE (pg,
"update_donau_instance",
"UPDATE merchant_donau_instances SET"
" charity_name = $2,"
- " merchant_instance_serial = (SELECT merchant_serial"
- " FROM merchant_instances mi"
- " WHERE mi.merchant_pub = $3),"
" charity_max_per_year = $5,"
" charity_receipts_to_date = $6,"
" current_year = $7"
" WHERE"
- " charity_id = $4"
- " AND donau_url = $1;");
+ " charity_id=$4"
+ " AND merchant_instance_serial"
+ " = (SELECT merchant_serial"
+ " FROM merchant_instances mi"
+ " WHERE mi.merchant_pub = $3)"
+ " AND donau_url=$1;");
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
"update_donau_instance",
diff --git a/src/backenddb/pg_select_donau_instances.c b/src/backenddb/pg_select_donau_instances.c
@@ -74,8 +74,7 @@ select_donau_instance_cb (void *cls,
struct TALER_Amount charity_max_per_year;
struct TALER_Amount charity_receipts_to_date;
int64_t current_year;
- json_t *donau_keys_json;
-
+ json_t *donau_keys_json = NULL;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint64 ("donau_instances_serial",
&donau_instance_serial),
@@ -93,8 +92,10 @@ select_donau_instance_cb (void *cls,
&charity_receipts_to_date),
GNUNET_PQ_result_spec_int64 ("current_year",
¤t_year),
- TALER_PQ_result_spec_json ("keys_json",
- &donau_keys_json),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("keys_json",
+ &donau_keys_json),
+ NULL),
GNUNET_PQ_result_spec_end
};
@@ -155,7 +156,7 @@ TMH_PG_select_donau_instances (void *cls,
",di.current_year"
",dk.keys_json"
" FROM merchant_donau_instances di"
- " JOIN merchant_donau_keys dk"
+ " LEFT JOIN merchant_donau_keys dk"
" ON di.donau_url = dk.donau_url"
" JOIN merchant_instances mi"
" ON di.merchant_instance_serial = mi.merchant_serial"
diff --git a/src/include/taler_merchant_donau.h b/src/include/taler_merchant_donau.h
@@ -142,7 +142,7 @@ struct TALER_MERCHANTDB_DonauInstance
* @param charity_max_per_year Maximum allowed donations to the charity for the current year.
* @param charity_receipts_to_date Total donations received by the charity so far in the current year.
* @param current_year The year for which the donation data is being tracked.
- * @param donau_keys_json JSON object containing additional key-related information for the Donau instance.
+ * @param donau_keys_json JSON object containing additional key-related information for the Donau instance, NULL if not (yet) available.
*/
typedef void
(*TALER_MERCHANTDB_DonauInstanceCallback)(
@@ -228,7 +228,7 @@ struct TALER_MERCHANT_DonauInstanceEntry
/**
* Additional key information related to the Donau instance.
*/
- struct DONAU_Keys donau_keys;
+ const struct DONAU_Keys *donau_keys;
};
/**
diff --git a/src/lib/merchant_api_get_donau_instance.c b/src/lib/merchant_api_get_donau_instance.c
@@ -83,6 +83,7 @@ parse_donau_instances (const json_t *ia,
instances[GNUNET_NZL (instances_len)];
size_t index;
json_t *value;
+ struct DONAU_Keys *donau_keys_ptr = NULL;
if ((json_array_size (ia) != (size_t) instances_len))
{
@@ -95,9 +96,7 @@ parse_donau_instances (const json_t *ia,
value)
{
struct TALER_MERCHANT_DonauInstanceEntry *instance = &instances[index];
- const json_t *donau_keys_json;
- struct DONAU_Keys *donau_keys_ptr;
-
+ const json_t *donau_keys_json = NULL;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_uint64 ("donau_instance_serial",
&instance->donau_instance_serial),
@@ -115,42 +114,47 @@ parse_donau_instances (const json_t *ia,
&instance->charity_receipts_to_date),
GNUNET_JSON_spec_int64 ("current_year",
&instance->current_year),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_object_const ("donau_keys_json",
+ &donau_keys_json),
+ NULL),
GNUNET_JSON_spec_end ()
};
- if (GNUNET_OK != GNUNET_JSON_parse (value,
- spec,
- NULL,
- NULL))
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (value,
+ spec,
+ NULL,
+ NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
/* Parse the Donau keys */
- donau_keys_json = json_object_get (value,
- "donau_keys_json");
- if (NULL == donau_keys_json)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse donau keys JSON\n");
- return GNUNET_SYSERR;
- }
- donau_keys_ptr = DONAU_keys_from_json (donau_keys_json);
- if (NULL == donau_keys_ptr)
+ if (NULL != donau_keys_json)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to convert donau keys from JSON\n");
- return GNUNET_SYSERR;
+ donau_keys_ptr = DONAU_keys_from_json (donau_keys_json);
+ if (NULL == donau_keys_ptr)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to convert donau keys from JSON\n");
+ return GNUNET_SYSERR;
+ }
+ instance->donau_keys = donau_keys_ptr;
}
-
- instance->donau_keys = *donau_keys_ptr;
}
igr->details.ok.donau_instances_length = instances_len;
igr->details.ok.donau_instances = instances;
- dgh->cb (dgh->cb_cls, igr);
+ dgh->cb (dgh->cb_cls,
+ igr);
dgh->cb = NULL;
+ if (NULL != donau_keys_ptr)
+ {
+ DONAU_keys_decref (donau_keys_ptr);
+ donau_keys_ptr= NULL;
+ }
return GNUNET_OK;
}
@@ -186,18 +190,26 @@ handle_get_donau_instances_finished (void *cls,
{
const json_t *donau_instances;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_array_const ("donau_instances", &donau_instances),
+ GNUNET_JSON_spec_array_const ("donau_instances",
+ &donau_instances),
GNUNET_JSON_spec_end ()
};
- if (GNUNET_OK != GNUNET_JSON_parse (json, spec, NULL, NULL))
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json,
+ spec,
+ NULL,
+ NULL))
{
igr.hr.http_status = 0;
igr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
- if (GNUNET_OK == parse_donau_instances (donau_instances, &igr, dgh))
+ if (GNUNET_OK ==
+ parse_donau_instances (donau_instances,
+ &igr,
+ dgh))
{
TALER_MERCHANT_donau_instances_get_cancel (dgh);
return;
@@ -248,8 +260,9 @@ TALER_MERCHANT_donau_instances_get (struct GNUNET_CURL_Context *ctx,
dgh->ctx = ctx;
dgh->cb = cb;
dgh->cb_cls = cb_cls;
-
- dgh->url = TALER_url_join (backend_url, "private/donau", NULL);
+ dgh->url = TALER_url_join (backend_url,
+ "private/donau",
+ NULL);
if (NULL == dgh->url)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -257,12 +270,13 @@ TALER_MERCHANT_donau_instances_get (struct GNUNET_CURL_Context *ctx,
GNUNET_free (dgh);
return NULL;
}
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Requesting URL '%s'\n", dgh->url);
-
+ "Requesting URL '%s'\n",
+ dgh->url);
eh = TALER_MERCHANT_curl_easy_get_ (dgh->url);
- dgh->job = GNUNET_CURL_job_add (ctx, eh, &handle_get_donau_instances_finished,
+ dgh->job = GNUNET_CURL_job_add (ctx,
+ eh,
+ &handle_get_donau_instances_finished,
dgh);
return dgh;
@@ -280,7 +294,6 @@ TALER_MERCHANT_donau_instances_get_cancel (
{
if (NULL != dgh->job)
GNUNET_CURL_job_cancel (dgh->job);
-
GNUNET_free (dgh->url);
GNUNET_free (dgh);
}
diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c
@@ -1880,11 +1880,31 @@ run (void *cls,
"create-another-order-with-input-and-output",
// reusing the merchant_reference for merchant_pub
MHD_HTTP_CREATED),
+ TALER_TESTING_cmd_charity_post_merchant ("post-charity-conflict",
+ "example",
+ "example.com",
+ "EUR:50", // max_per_year
+ "EUR:0", // receipts_to_date
+ 2025, // current year
+ &bearer,
+ "create-another-order-with-input-and-output",
+ // reusing the merchant_reference for merchant_pub
+ MHD_HTTP_CONFLICT),
TALER_TESTING_cmd_merchant_post_donau_instance (
"post-donau-instance",
merchant_url,
- "create-another-order-with-input-and-output", // reusing the merchant_reference
+ "create-another-order-with-input-and-output",
+ MHD_HTTP_NO_CONTENT),
+ TALER_TESTING_cmd_merchant_post_donau_instance (
+ "post-donau-instance-idempotent",
+ merchant_url,
+ "create-another-order-with-input-and-output",
MHD_HTTP_NO_CONTENT),
+ TALER_TESTING_cmd_merchant_get_donau_instances (
+ "get-donau-instances-after-insert",
+ merchant_url,
+ 1,
+ MHD_HTTP_OK),
TALER_TESTING_cmd_sleep (
"In this time donaukeyupdate must fetch the keys from the donau",
1),