merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit 4ce9fb07e98f445c9c97460e780d8c15ca3e1060
parent 80c83d164699ae05f2837275b3a99cb963f00e7a
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun,  5 Jul 2026 23:30:05 +0200

fix upper-case ID issues in merchant instance creation logic

Diffstat:
Msrc/backend/taler-merchant-httpd_post-management-instances.c | 66++++++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 40 insertions(+), 26 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_post-management-instances.c b/src/backend/taler-merchant-httpd_post-management-instances.c @@ -70,13 +70,14 @@ post_instances (const struct TMH_RequestHandler *rh, struct TMH_WireMethod *wm_tail = NULL; const json_t *jauth; const char *iphone = NULL; + char *id_lower; bool no_pay_delay; bool no_refund_delay; bool no_transfer_delay; bool no_rounding_interval; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("id", - (const char **) &is.id), + TALER_JSON_spec_slug ("id", + (const char **) &is.id), GNUNET_JSON_spec_string ("name", (const char **) &is.name), GNUNET_JSON_spec_mark_optional ( @@ -289,17 +290,21 @@ post_instances (const struct TMH_RequestHandler *rh, "logo"); } + id_lower = GNUNET_STRINGS_utf8_tolower (is.id); { /* Test if an instance of this id is known */ struct TMH_MerchantInstance *mi; - mi = TMH_lookup_instance (is.id); + mi = TMH_lookup_instance (id_lower); if (NULL != mi) { + enum MHD_Result ret; + if (mi->deleted) { GNUNET_JSON_parse_free (spec); GNUNET_free (is.phone); + GNUNET_free (id_lower); return TALER_MHD_reply_with_error ( connection, MHD_HTTP_CONFLICT, @@ -308,7 +313,7 @@ post_instances (const struct TMH_RequestHandler *rh, } /* Check for idempotency */ if ( (0 == strcmp (mi->settings.id, - is.id)) && + id_lower)) && (0 == strcmp (mi->settings.name, is.name)) && ((mi->settings.email == is.email) || @@ -348,6 +353,7 @@ post_instances (const struct TMH_RequestHandler *rh, { GNUNET_JSON_parse_free (spec); GNUNET_free (is.phone); + GNUNET_free (id_lower); return TALER_MHD_reply_static (connection, MHD_HTTP_NO_CONTENT, NULL, @@ -356,10 +362,12 @@ post_instances (const struct TMH_RequestHandler *rh, } GNUNET_JSON_parse_free (spec); GNUNET_free (is.phone); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS, - is.id); + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS, + id_lower); + GNUNET_free (id_lower); + return ret; } } @@ -374,6 +382,7 @@ post_instances (const struct TMH_RequestHandler *rh, GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); GNUNET_free (is.phone); /* does nothing... */ + GNUNET_free (id_lower); return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PARAMETER_MISSING, @@ -386,6 +395,7 @@ post_instances (const struct TMH_RequestHandler *rh, GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); GNUNET_free (is.phone); + GNUNET_free (id_lower); return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PARAMETER_MISSING, @@ -400,7 +410,7 @@ post_instances (const struct TMH_RequestHandler *rh, case TMH_TCS_SMS: is.phone_validated = true; ret = TMH_mfa_challenges_do (hc, - is.id, + id_lower, TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION, true, TALER_MERCHANT_MFA_CHANNEL_SMS, @@ -410,7 +420,7 @@ post_instances (const struct TMH_RequestHandler *rh, case TMH_TCS_EMAIL: is.email_validated = true; ret = TMH_mfa_challenges_do (hc, - is.id, + id_lower, TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION, true, TALER_MERCHANT_MFA_CHANNEL_EMAIL, @@ -421,7 +431,7 @@ post_instances (const struct TMH_RequestHandler *rh, is.phone_validated = true; is.email_validated = true; ret = TMH_mfa_challenges_do (hc, - is.id, + id_lower, TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION, true, TALER_MERCHANT_MFA_CHANNEL_EMAIL, @@ -435,6 +445,7 @@ post_instances (const struct TMH_RequestHandler *rh, { GNUNET_JSON_parse_free (spec); GNUNET_free (is.phone); + GNUNET_free (id_lower); return (GNUNET_NO == ret) ? MHD_YES : MHD_NO; @@ -470,7 +481,7 @@ post_instances (const struct TMH_RequestHandler *rh, mi->settings = is; mi->settings.address = json_incref (mi->settings.address); mi->settings.jurisdiction = json_incref (mi->settings.jurisdiction); - mi->settings.id = GNUNET_STRINGS_utf8_tolower (is.id); + mi->settings.id = id_lower; mi->settings.name = GNUNET_strdup (is.name); if (NULL != is.email) mi->settings.email = GNUNET_strdup (is.email); @@ -495,10 +506,11 @@ post_instances (const struct TMH_RequestHandler *rh, mi->rc = 1; TMH_instance_decref (mi); GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_START_FAILED, - NULL); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_START_FAILED, + NULL); } qs = TALER_MERCHANTDB_insert_instance (TMH_db, &mi->merchant_pub, @@ -513,10 +525,11 @@ post_instances (const struct TMH_RequestHandler *rh, TALER_MERCHANTDB_rollback (TMH_db); GNUNET_break (0); - ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - is.id); + ret = TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "insert_instance"); mi->rc = 1; TMH_instance_decref (mi); GNUNET_JSON_parse_free (spec); @@ -530,10 +543,11 @@ post_instances (const struct TMH_RequestHandler *rh, TALER_MERCHANTDB_rollback (TMH_db); GNUNET_break (0); - ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS, - is.id); + ret = TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS, + id_lower); mi->rc = 1; TMH_instance_decref (mi); GNUNET_JSON_parse_free (spec); @@ -581,7 +595,7 @@ retry: enum GNUNET_DB_QueryStatus qs; qs = TALER_MERCHANTDB_set_instance (TMH_db, - is.id); + id_lower); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: @@ -621,7 +635,7 @@ retry: expiration_time = GNUNET_TIME_relative_to_timestamp (login_token_expiration); qs = TALER_MERCHANTDB_insert_login_token (TMH_db, - is.id, + id_lower, &btoken, GNUNET_TIME_timestamp_get (), expiration_time,