diff options
author | priscilla <priscilla.huang@efrei.net> | 2023-01-31 09:06:20 -0500 |
---|---|---|
committer | priscilla <priscilla.huang@efrei.net> | 2023-01-31 09:06:41 -0500 |
commit | 3645e148dd673d0f5b72226a9d9a6310cbe21be0 (patch) | |
tree | 7287a1c15ff22d559852e596e52eb3943564c990 /src | |
parent | bf872f712e7af196341a0aacde1c0fd70b046e72 (diff) | |
download | merchant-3645e148dd673d0f5b72226a9d9a6310cbe21be0.tar.gz merchant-3645e148dd673d0f5b72226a9d9a6310cbe21be0.tar.bz2 merchant-3645e148dd673d0f5b72226a9d9a6310cbe21be0.zip |
backend pending webhook
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/taler-merchant-httpd_helper.c | 16 | ||||
-rw-r--r-- | src/backend/taler-merchant-webhook.c | 107 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 6 | ||||
-rw-r--r-- | src/backenddb/test.conf | 172 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 13 |
5 files changed, 280 insertions, 34 deletions
diff --git a/src/backend/taler-merchant-httpd_helper.c b/src/backend/taler-merchant-httpd_helper.c index 2cffa20c..b875f6f3 100644 --- a/src/backend/taler-merchant-httpd_helper.c +++ b/src/backend/taler-merchant-httpd_helper.c @@ -20,11 +20,12 @@ */ #include "platform.h" #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_db_lib.h> #include <taler/taler_util.h> #include <taler/taler_json_lib.h> #include "taler-merchant-httpd_helper.h" #include <taler/taler_templating_lib.h> - +#include <taler/taler_dbevents.h> /** * check @a payto_uris for well-formedness @@ -587,6 +588,19 @@ trigger_webhook_cb (void *cls, http_method, header, body); + if (t->rv > 0) + { + struct GNUNET_DB_EventHeaderP es = { + .size = htons (sizeof(es)), + .type = htons (TALER_DBEVENT_MERCHANT_WEBHOOK_PENDING) + }; + const void *extra = NULL; + size_t extra_size = 0; + TMH_db->event_notify (TMH_db->cls, + &es, + &extra, + extra_size); + } free (header); free (body); } diff --git a/src/backend/taler-merchant-webhook.c b/src/backend/taler-merchant-webhook.c index a1a31558..1d258a18 100644 --- a/src/backend/taler-merchant-webhook.c +++ b/src/backend/taler-merchant-webhook.c @@ -16,7 +16,7 @@ /** * @file taler-merchant-webhook.c * @brief Process that runs webhooks triggered by the merchant backend - * @author Christian Grothoff + * @author Priscilla HUANG */ #include "platform.h" #include <gnunet/gnunet_util_lib.h> @@ -24,6 +24,7 @@ #include <pthread.h> #include "taler_merchantdb_lib.h" #include "taler_merchantdb_plugin.h" +#include <taler/taler_dbevents.h> struct WorkResponse @@ -31,7 +32,7 @@ struct WorkResponse struct WorkResponse *next; struct WorkResponse *prev; struct GNUNET_CURL_Job *job; - uint64_t webhook_serial; + uint64_t webhook_pending_serial; char *body; struct curl_slist *job_headers; }; @@ -41,6 +42,8 @@ static struct WorkResponse *w_head; static struct WorkResponse *w_tail; +static struct GNUNET_DB_EventHandler *eh; + /** * The exchange's configuration. */ @@ -90,6 +93,11 @@ shutdown_task (void *cls) (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running shutdown\n"); + if (NULL != eh) + { + db_plugin->event_listen_cancel (eh); + eh = NULL; + } if (NULL != task) { GNUNET_SCHEDULER_cancel (task); @@ -153,18 +161,30 @@ handle_webhook_response (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Webhook %llu returned with status %ld\n", - (unsigned long long) w->webhook_serial, + (unsigned long long) w->webhook_pending_serial, response_code); if (2 == response_code / 100) /* any 2xx http status code is OK! */ { - db_plugin->delete_pending_webhook (db_plugin->cls, - w->webhook_serial); + enum GNUNET_DB_QueryStatus qs; + + qs = db_plugin->delete_pending_webhook (db_plugin->cls, + w->webhook_pending_serial); + + if ((GNUNET_DB_STATUS_HARD_ERROR == qs) ||(GNUNET_DB_STATUS_SOFT_ERROR==qs)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Delete returned: %d\n", + qs); + global_ret = EXIT_FAILURE; + GNUNET_SCHEDULER_shutdown (); + } } else { struct GNUNET_TIME_Relative next_attempt; enum GNUNET_DB_QueryStatus qs; - switch (response_code) { case MHD_HTTP_BAD_REQUEST: @@ -181,12 +201,19 @@ handle_webhook_response (void *cls, break; } qs = db_plugin->update_pending_webhook (db_plugin->cls, - w->webhook_serial, + w->webhook_pending_serial, GNUNET_TIME_relative_to_absolute (next_attempt)); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Next in %s Rval: %d\n", - GNUNET_TIME_relative2s (next_attempt, true), - qs); + if ((GNUNET_DB_STATUS_HARD_ERROR == qs) ||(GNUNET_DB_STATUS_SOFT_ERROR==qs)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Next in %s Rval: %d\n", + GNUNET_TIME_relative2s (next_attempt, true), + qs); + global_ret = EXIT_FAILURE; + GNUNET_SCHEDULER_shutdown (); + } } GNUNET_CONTAINER_DLL_remove (w_head, w_tail, @@ -204,7 +231,7 @@ handle_webhook_response (void *cls, * Typically called by `select_work`. * * @param cls a `json_t *` JSON array to build - * @param webhook_serial reference to the configured webhook template. + * @param webhook_pending_serial reference to the configured webhook template. * @param next_attempt is the time we should make the next request to the webhook. * @param retries how often have we tried this request to the webhook. * @param url to make request to @@ -214,7 +241,7 @@ handle_webhook_response (void *cls, */ static void pending_webhooks_cb (void *cls, - uint64_t webhook_serial, + uint64_t webhook_pending_serial, struct GNUNET_TIME_Absolute next_attempt, uint32_t retries, const char *url, @@ -232,7 +259,7 @@ pending_webhooks_cb (void *cls, GNUNET_CONTAINER_DLL_insert (w_head, w_tail, w); - w->webhook_serial = webhook_serial; + w->webhook_pending_serial = webhook_pending_serial; eh = curl_easy_init (); GNUNET_assert (NULL != eh); GNUNET_assert (CURLE_OK == @@ -246,7 +273,7 @@ pending_webhooks_cb (void *cls, GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_VERBOSE, - 1L)); + 0L)); /* conversion body data */ if (NULL != body) @@ -263,8 +290,8 @@ pending_webhooks_cb (void *cls, char *header_copy = GNUNET_strdup (header); for (const char *tok = strtok (header_copy, "\n"); - tok = strtok (NULL, "\n"); - NULL != tok) + NULL != tok; + tok = strtok (NULL, "\n")) { // extract all Key: value from 'header_copy'! job_headers = curl_slist_append (job_headers, @@ -294,8 +321,8 @@ pending_webhooks_cb (void *cls, if (NULL == w->job) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to start the curl job for webhook #%llu\n", - (unsigned long long) webhook_serial); + "Failed to start the curl job for pending webhook #%llu\n", + (unsigned long long) webhook_pending_serial); curl_slist_free_all (w->job_headers); GNUNET_free (w->body); GNUNET_CONTAINER_DLL_remove (w_head, @@ -308,13 +335,34 @@ pending_webhooks_cb (void *cls, } +/** + * Function called on events received from Postgres. + * + * @param cls closure, NULL + * @param extra additional event data provided + * @param extra_size number of bytes in @a extra + */ +static void +db_notify (void *cls, + const void *extra, + size_t extra_size) +{ + (void) cls; + (void) extra; + (void) extra_size; + + GNUNET_assert (NULL != task); + GNUNET_SCHEDULER_cancel (task); + task = GNUNET_SCHEDULER_add_now (&select_work, + NULL); +} /** * Typically called by `select_work`. * * @param cls a `json_t *` JSON array to build - * @param webhook_serial reference to the configured webhook template. + * @param webhook_pending_serial reference to the configured webhook template. * @param next_attempt is the time we should make the next request to the webhook. * @param retries how often have we tried this request to the webhook. * @param url to make request to @@ -324,7 +372,7 @@ pending_webhooks_cb (void *cls, */ static void future_webhook_cb (void *cls, - uint64_t webhook_serial, + uint64_t webhook_pending_serial, struct GNUNET_TIME_Absolute next_attempt, uint32_t retries, const char *url, @@ -332,7 +380,7 @@ future_webhook_cb (void *cls, const char *header, const char *body) { - (void) webhook_serial; + (void) webhook_pending_serial; (void) retries; (void) url; (void) http_method; @@ -345,6 +393,8 @@ future_webhook_cb (void *cls, } + + static void select_work (void *cls) { @@ -388,6 +438,19 @@ select_work (void *cls) case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: /* wait 5 min */ rel = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5); + if (NULL == eh) + { + struct GNUNET_DB_EventHeaderP es = { + .size = htons (sizeof (es)), + .type = htons (TALER_DBEVENT_MERCHANT_WEBHOOK_PENDING) + }; + + eh = db_plugin->event_listen (db_plugin->cls, + &es, + GNUNET_TIME_UNIT_FOREVER_REL, + &db_notify, + NULL); + } task = GNUNET_SCHEDULER_add_delayed (rel, &select_work, NULL); diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 798cc48d..373ffa97 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -7503,7 +7503,7 @@ postgres_lookup_webhook_by_event (void *cls, static enum GNUNET_DB_QueryStatus postgres_insert_pending_webhook (void *cls, const char *instance_id, - uint64_t webhook_pending_serial, + uint64_t webhook_serial, const char *url, const char *http_method, const char *header, @@ -7512,7 +7512,7 @@ postgres_insert_pending_webhook (void *cls, struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_uint64 (&webhook_pending_serial), + GNUNET_PQ_query_param_uint64 (&webhook_serial), GNUNET_PQ_query_param_string (url), GNUNET_PQ_query_param_string (http_method), NULL == header @@ -10447,7 +10447,7 @@ postgres_connect (void *cls) GNUNET_PQ_make_prepare ("insert_pending_webhook", "INSERT INTO merchant_pending_webhooks" "(merchant_serial" - ",webhook_pending_serial" + ",webhook_serial" ",url" ",http_method" ",header" diff --git a/src/backenddb/test.conf b/src/backenddb/test.conf new file mode 100644 index 00000000..502d807a --- /dev/null +++ b/src/backenddb/test.conf @@ -0,0 +1,172 @@ +# This file is in the public domain. +# +[PATHS] +# Persistent data storage for the testcase +TALER_TEST_HOME = test_merchant_api_home/ +TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/ + +# Persistent data storage +TALER_DATA_HOME = $TALER_HOME/.local/share/taler/ + +# Configuration files +TALER_CONFIG_HOME = $TALER_HOME/.config/taler/ + +# Cached data, no big deal if lost +TALER_CACHE_HOME = $TALER_HOME/.cache/taler/ + +[taler] +# What currency do we use? +CURRENCY = EUR +CURRENCY_ROUND_UNIT = EUR:0.01 + +[taler-helper-crypto-rsa] +# Reduce from 1 year to speed up test +LOOKAHEAD_SIGN = 24 days + +[taler-helper-crypto-eddsa] +# Reduce from 1 year to speed up test +LOOKAHEAD_SIGN = 24 days +# Reduce from 12 weeks to ensure we have multiple +DURATION = 14 days + +[bank] +HTTP_PORT = 8082 + +########################################## +# Configuration for the merchant backend # +########################################## + +[merchant] + +# Which port do we run the backend on? (HTTP server) +PORT = 8080 + +# Which plugin (backend) do we use for the DB. +DB = postgres + +# This specifies which database the postgres backend uses. +[merchantdb-postgres] +CONFIG = postgres:///talercheck + +# Sections starting with "merchant-exchange-" specify trusted exchanges +# (by the merchant) +[merchant-exchange-test] +MASTER_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG +EXCHANGE_BASE_URL = http://localhost:8081/ +CURRENCY = EUR + + +####################################################### +# Configuration for the auditor for the testcase +####################################################### +[auditor] +BASE_URL = http://the.auditor/ + + +####################################################### +# Configuration for ??? Is this used? +####################################################### + +# Auditors must be in sections "auditor-", the rest of the section +# name could be anything. +[auditor-ezb] +# Informal name of the auditor. Just for the user. +NAME = European Central Bank + +# URL of the auditor (especially for in the future, when the +# auditor offers an automated issue reporting system). +# Not really used today. +URL = http://taler.ezb.eu/ + +# This is the important bit: the signing key of the auditor. +PUBLIC_KEY = 9QXF7XY7E9VPV47B5Z806NDFSX2VJ79SVHHD29QEQ3BG31ANHZ60 + +# Which currency is this auditor trusted for? +CURRENCY = EUR + + +################################################### +# Configuration for the exchange for the testcase # +################################################### + +[exchange] +# How to access our database +DB = postgres + +# HTTP port the exchange listens to +PORT = 8081 + +# Our public key +MASTER_PUBLIC_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG + +# Base URL of the exchange. +BASE_URL = "http://localhost:8081/" + + +[exchangedb-postgres] +CONFIG = "postgres:///talercheck" + + +[auditordb-postgres] +CONFIG = postgres:///talercheck + + +# Account of the EXCHANGE +[exchange-account-exchange] +# What is the exchange's bank account (with the "Taler Bank" demo system)? +PAYTO_URI = "payto://x-taler-bank/localhost/2?receiver-name=2" +ENABLE_DEBIT = YES +ENABLE_CREDIT = YES + +[exchange-accountcredentials-exchange] +WIRE_GATEWAY_URL = "http://localhost:8082/2/" +WIRE_GATEWAY_AUTH_METHOD = NONE + + +[coin_eur_ct_1] +value = EUR:0.01 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.00 +fee_deposit = EUR:0.00 +fee_refresh = EUR:0.01 +fee_refund = EUR:0.01 +rsa_keysize = 1024 +CIPHER = CS + +[coin_eur_ct_10] +value = EUR:0.10 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +rsa_keysize = 1024 +CIPHER = CS + +[coin_eur_1] +value = EUR:1 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +rsa_keysize = 1024 +CIPHER = CS + +[coin_eur_5] +value = EUR:5 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +rsa_keysize = 1024 +CIPHER = CS diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index d9fe0d24..fe974ba4 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -409,7 +409,7 @@ typedef void * Typically called by `lookup_pending_webhooks`. * * @param cls a `json_t *` JSON array to build - * @param webhook_serial reference to the configured webhook template. + * @param webhook_pending_serial reference to the configured webhook template. * @param next_attempt is the time we should make the next request to the webhook. * @param retries how often have we tried this request to the webhook. * @param url to make request to @@ -419,9 +419,8 @@ typedef void */ typedef void (*TALER_MERCHANTDB_PendingWebhooksCallback)(void *cls, - uint64_t webhook_serial, - struct GNUNET_TIME_Absolute - next_attempt, + uint64_t webhook_pending_serial, + struct GNUNET_TIME_Absolute next_attempt, uint32_t retries, const char *url, const char *http_method, @@ -455,13 +454,11 @@ struct TALER_MERCHANTDB_PendingWebhookDetails */ char *http_method; - /** * Header of the webhook. */ char *header; - /** * Body of the webhook. */ @@ -2827,7 +2824,7 @@ struct TALER_MERCHANTDB_Plugin */ enum GNUNET_DB_QueryStatus (*update_pending_webhook)(void *cls, - uint64_t webhook_serial, + uint64_t webhook_pending_serial, struct GNUNET_TIME_Absolute next_attempt); // maybe add: http status of failure? @@ -2842,7 +2839,7 @@ struct TALER_MERCHANTDB_Plugin */ enum GNUNET_DB_QueryStatus (*delete_pending_webhook)(void *cls, - uint64_t webhook_serial); + uint64_t webhook_pending_serial); }; |