From 385fb34f50768c76e32f8009c9270559e187bbb2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 2 Apr 2021 15:54:43 +0200 Subject: fix #6812: allow purging of deleted instances --- src/backend/taler-merchant-httpd.c | 44 ++++++++++------------ src/backend/taler-merchant-httpd.h | 11 ++++++ ...er-merchant-httpd_private-delete-instances-ID.c | 5 ++- ...taler-merchant-httpd_private-get-instances-ID.c | 3 +- .../taler-merchant-httpd_private-get-instances.c | 6 ++- ...ler-merchant-httpd_private-patch-instances-ID.c | 7 ++++ .../taler-merchant-httpd_private-post-instances.c | 8 ++++ 7 files changed, 55 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index a6bce84d..1f59eec2 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -829,14 +829,8 @@ run_daemon (void *cls) } -/** - * Kick MHD to run now, to be called after MHD_resume_connection(). - * Basically, we need to explicitly resume MHD's event loop whenever - * we made progress serving a request. This function re-schedules - * the task processing MHD's activities to run immediately. - */ void -TMH_trigger_daemon () +TMH_trigger_daemon (void) { if (NULL != mhd_task) { @@ -852,8 +846,10 @@ TMH_trigger_daemon () /** - * Function that queries MHD's select sets and - * starts the task waiting for them. + * Function that queries MHD's select sets and starts the task waiting for + * them. + * + * @return task handle for the MHD task. */ static struct GNUNET_SCHEDULER_Task * prepare_daemon (void) @@ -902,12 +898,6 @@ prepare_daemon (void) } -/** - * Lookup a merchant instance by its instance ID. - * - * @param instance_id identifier of the instance to resolve - * @return NULL if that instance is unknown to us - */ struct TMH_MerchantInstance * TMH_lookup_instance (const char *instance_id) { @@ -1199,6 +1189,7 @@ url_handler (void *cls, { .url_prefix = "/", .method = MHD_HTTP_METHOD_DELETE, + .allow_deleted_instance = true, .handler = &TMH_private_delete_instances_ID }, /* PATCH /instances/$ID/: */ @@ -1206,6 +1197,7 @@ url_handler (void *cls, .url_prefix = "/", .method = MHD_HTTP_METHOD_PATCH, .handler = &TMH_private_patch_instances_ID, + .allow_deleted_instance = true, /* allow instance data of up to 8 MB, that should be plenty; note that exceeding #GNUNET_MAX_MALLOC_CHECKED (40 MB) would require further changes to the allocation logic @@ -1641,11 +1633,6 @@ url_handler (void *cls, slash - istart); hc->instance = TMH_lookup_instance (instance_id); GNUNET_free (instance_id); - if (NULL == hc->instance) - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_GENERIC_ENDPOINT_UNKNOWN, - url); if (NULL == slash) url = ""; else @@ -1889,12 +1876,17 @@ url_handler (void *cls, } /* if (use_private) */ - if ( (NULL == hc->instance) && - (! hc->rh->skip_instance) ) + if ( ( (NULL == hc->instance) && + (! hc->rh->skip_instance) ) || + ( (! hc->rh->skip_instance) && + (hc->instance->deleted) && + (! hc->rh->allow_deleted_instance) ) ) return TALER_MHD_reply_with_error (connection, MHD_HTTP_NOT_FOUND, TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN, url); + + hc->has_body = ( (0 == strcasecmp (method, MHD_HTTP_METHOD_POST)) || (0 == strcasecmp (method, @@ -1964,7 +1956,6 @@ add_instance_cb (void *cls, struct TMH_MerchantInstance *mi; (void) cls; - GNUNET_assert (NULL != merchant_priv); mi = GNUNET_new (struct TMH_MerchantInstance); mi->settings = *is; mi->auth = *ias; @@ -1972,7 +1963,10 @@ add_instance_cb (void *cls, mi->settings.name = GNUNET_strdup (mi->settings.name); mi->settings.address = json_incref (mi->settings.address); mi->settings.jurisdiction = json_incref (mi->settings.jurisdiction); - mi->merchant_priv = *merchant_priv; + if (NULL != merchant_priv) + mi->merchant_priv = *merchant_priv; + else + mi->deleted = true; mi->merchant_pub = *merchant_pub; for (unsigned int i = 0; ilookup_instances (TMH_db->cls, - true, + false, &add_instance_cb, NULL); if (0 > qs) diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h index eb6d67c6..7f42e107 100644 --- a/src/backend/taler-merchant-httpd.h +++ b/src/backend/taler-merchant-httpd.h @@ -142,6 +142,11 @@ struct TMH_MerchantInstance * counter hits zero. */ unsigned int rc; + + /** + * True if this instance was deleted (but not yet purged). + */ + bool deleted; }; @@ -197,6 +202,11 @@ struct TMH_RequestHandler */ bool skip_instance; + /** + * Does this request handler work with a deleted instance? + */ + bool allow_deleted_instance; + /** * URL suffix the handler is for, excludes the '/', * so "pay" or "claim", not "/pay". @@ -499,6 +509,7 @@ TMH_instance_decref (struct TMH_MerchantInstance *mi); int TMH_add_instance (struct TMH_MerchantInstance *mi); + /** * Lookup a merchant instance by its instance ID. * diff --git a/src/backend/taler-merchant-httpd_private-delete-instances-ID.c b/src/backend/taler-merchant-httpd_private-delete-instances-ID.c index baa082a2..919c21c9 100644 --- a/src/backend/taler-merchant-httpd_private-delete-instances-ID.c +++ b/src/backend/taler-merchant-httpd_private-delete-instances-ID.c @@ -72,7 +72,10 @@ delete_instances_ID (struct TMH_MerchantInstance *mi, ? "Instance unknown" : "Private key unknown"); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - TMH_instance_decref (mi); + if (NULL != purge) + TMH_instance_decref (mi); + else + mi->deleted = true; return TALER_MHD_reply_static (connection, MHD_HTTP_NO_CONTENT, NULL, diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID.c b/src/backend/taler-merchant-httpd_private-get-instances-ID.c index 6c3730a2..2e63995f 100644 --- a/src/backend/taler-merchant-httpd_private-get-instances-ID.c +++ b/src/backend/taler-merchant-httpd_private-get-instances-ID.c @@ -121,7 +121,8 @@ TMH_private_get_instances_default_ID (const struct TMH_RequestHandler *rh, struct TMH_MerchantInstance *mi; mi = TMH_lookup_instance (hc->infix); - if (NULL == mi) + if ( (NULL == mi) || + (mi->deleted) ) { return TALER_MHD_reply_with_error (connection, MHD_HTTP_NOT_FOUND, diff --git a/src/backend/taler-merchant-httpd_private-get-instances.c b/src/backend/taler-merchant-httpd_private-get-instances.c index 2f2ac591..542d0b44 100644 --- a/src/backend/taler-merchant-httpd_private-get-instances.c +++ b/src/backend/taler-merchant-httpd_private-get-instances.c @@ -72,7 +72,7 @@ add_instance (void *cls, json_array_append_new ( ja, json_pack ( - "{s:s, s:s, s:o, s:o}", + "{s:s, s:s, s:o, s:o, s:b}", "name", mi->settings.name, "id", @@ -80,7 +80,9 @@ add_instance (void *cls, "merchant_pub", GNUNET_JSON_from_data_auto (&mi->merchant_pub), "payment_targets", - pta))); + pta, + "deleted", + mi->deleted))); return GNUNET_OK; } diff --git a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c index 8f21c76d..0a839a3a 100644 --- a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c +++ b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c @@ -448,6 +448,13 @@ TMH_private_patch_instances_default_ID (const struct TMH_RequestHandler *rh, TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN, hc->infix); } + if (mi->deleted) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_PATCH_INSTANCES_PURGE_REQUIRED, + hc->infix); + } return patch_instances_ID (mi, connection, hc); diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c index fbfb13c5..5b38f5b9 100644 --- a/src/backend/taler-merchant-httpd_private-post-instances.c +++ b/src/backend/taler-merchant-httpd_private-post-instances.c @@ -248,6 +248,14 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh, mi = TMH_lookup_instance (is.id); if (NULL != mi) { + if (mi->deleted) + { + GNUNET_JSON_parse_free (spec); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_PURGE_REQUIRED, + is.id); + } /* Check for idempotency */ if ( (0 == strcmp (mi->settings.id, is.id)) && -- cgit v1.2.3