diff options
author | priscilla <priscilla.huang@efrei.net> | 2023-01-23 08:25:49 -0500 |
---|---|---|
committer | priscilla <priscilla.huang@efrei.net> | 2023-01-23 08:25:49 -0500 |
commit | 4ba9ffaaeef83a05964bee764c419d9006a6767d (patch) | |
tree | 3f8c3e4936d7391bbdfd99b909bcb9983d1e50f3 | |
parent | 03ce25438c251820ff556c66f11b22659f7a896f (diff) |
backend pending webhook
16 files changed, 205 insertions, 702 deletions
diff --git a/src/backend/#taler-merchant-httpd_private-post-webhooks.h# b/src/backend/#taler-merchant-httpd_private-post-webhooks.h# deleted file mode 100644 index fd73c9e7..00000000 --- a/src/backend/#taler-merchant-httpd_private-post-webhooks.h# +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of TALER - (C) 2022 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 Foundation; either version 3, - or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, - see <http://www.gnu.org/licenses/> -*/ - -/** - * @file taler-merchant-httpd_private-post-webhooks.h - * @brief implementing POST /webhooks request handling - * @author Priscilla HUANG - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_WEBHOOKS_H -#define TALER_MERCHANT_HTTPD_PRIVATE_POST_WEBHOOKS_H -#include "taler-merchant-httpd.h" - - -/** - * Generate a webhook entry. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_post_webhooks (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -#endif diff --git a/src/backend/taler-merchant-httpd_helper.c b/src/backend/taler-merchant-httpd_helper.c index 86ff37c3..4f117154 100644 --- a/src/backend/taler-merchant-httpd_helper.c +++ b/src/backend/taler-merchant-httpd_helper.c @@ -23,6 +23,8 @@ #include <taler/taler_util.h> #include <taler/taler_json_lib.h> #include "taler-merchant-httpd_helper.h" +#include "../exchange/src/include/taler_templating_lib.h" + /** * check @a payto_uris for well-formedness @@ -496,3 +498,125 @@ TMH_uuid_from_string (const char *uuids, &hc, sizeof (*uuid)); } + + +/** + * Closure for #trigger_webhook_cb. + * + * @param instance which is the instance we work with + * @param root JSON data to fill into the template + * @param rv, query of the TALER_TEMPLATEING_fill + */ +struct Trigger +{ + const char *instance; + + const json_t *root; + + enum GNUNET_DB_QueryStatus rv; + +}; + +/** + * Typically called by `TMH_trigger_webhook`. + * + * @param[in,out] cls a `struct Trigger` with information about the webhook + * @param webhook_serial reference to the configured webhook template. + * @param event_type is the event/action of the webhook + * @param url to make request to + * @param http_method use for the webhook + * @param header_template of the webhook + * @param body_template of the webhook + */ +static void +trigger_webhook_cb (void *cls, + uint64_t webhook_serial, + const char *event_type, + const char *url, + const char *http_method, + const char *header_template, + const char *body_template) +{ + struct Trigger *t = cls; + void *header = NULL; + void *body = NULL; + size_t header_size; + size_t body_size; + + if (NULL != header_template) + { + int ret; + + ret = TALER_TEMPLATING_fill (header_template, + t->root, + &header, + &header_size); + if (0 != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to expand webhook header template for webhook %llu (%d)\n", + (unsigned long long) webhook_serial, + ret); + t->rv = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + GNUNET_assert ('\0' == ((const char *) header)[header_size-1]); + } + if (NULL != body_template) + { + int ret; + ret = TALER_TEMPLATING_fill (body_template, + t->root, + &body, + &body_size); + if (0 != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to expand webhook header template for webhook %llu (%d)\n", + (unsigned long long) webhook_serial, + ret); + t->rv = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + GNUNET_assert ('\0' == ((const char *) body)[body_size-1]); + } + t->rv = TMH_db->insert_pending_webhook (TMH_db->cls, + t->instance, + webhook_serial, + url, + http_method, + header, + body); + free (header); + free (body); +} + + +/** + * TMH_trigger_webhook is a function that need to be use when someone + * pay. Merchant need to have a notification. + * + * @param instance that we need to send the webhook as a notification + * @param event of the webhook + * @param args argument of the function + */ +enum GNUNET_DB_QueryStatus +TMH_trigger_webhook (const char *instance, + const char *event, + const json_t *args) +{ + struct Trigger t = { + .instance = instance, + .root = args + }; + enum GNUNET_DB_QueryStatus qs; + + qs = TMH_db->lookup_webhook_by_event (TMH_db->cls, + instance, + event, + &trigger_webhook_cb, + &t); + if (qs < 0) + return qs; + return t.rv; +} diff --git a/src/backend/taler-merchant-httpd_helper.h b/src/backend/taler-merchant-httpd_helper.h index dae9caaf..5cee97cc 100644 --- a/src/backend/taler-merchant-httpd_helper.h +++ b/src/backend/taler-merchant-httpd_helper.h @@ -111,6 +111,7 @@ TMH_setup_wire_account (const char *payto_uri); /** * FIXME: document */ + enum GNUNET_GenericReturnValue TMH_check_auth_config (struct MHD_Connection *connection, const json_t *jauth, @@ -142,4 +143,21 @@ TMH_uuid_from_string (const char *uuids, GNUNET_JSON_pack_allow_null ( \ GNUNET_JSON_pack_object_incref ("exchange_reply", (json_t *) (hr)->reply)) + + +/** + * TMH_trigger_webhook is a function that need to be use when someone + * pay. Merchant need to have a notification. + * + * @param instance that we need to send the webhook as a notification + * @param event of the webhook + * @param args argument of the function + */ +enum GNUNET_DB_QueryStatus +TMH_trigger_webhook (const char *instance, + const char *action, + const json_t *args); + + + #endif diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c index ee748470..162ee97a 100644 --- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c +++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c @@ -251,6 +251,11 @@ struct PayContext struct MHD_Response *response; /** + * Our contract (or NULL if not available). + */ + json_t *contract_terms; + + /** * Placeholder for #TALER_MHD_parse_post_json() to keep its internal state. */ void *json_parse_context; @@ -678,6 +683,11 @@ pay_context_cleanup (void *cls) GNUNET_SCHEDULER_cancel (pc->timeout_task); pc->timeout_task = NULL; } + if (NULL != pc->contract_terms) + { + json_decref (pc->contract_terms); + pc->contract_terms = NULL; + } abort_active_deposits (pc); for (unsigned int i = 0; i<pc->coins_cnt; i++) { @@ -1035,7 +1045,7 @@ handle_batch_deposit_ok (struct ExchangeGroup *eg, { resume_pay_with_error (pc, MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_SOFT_FAILURE, + TALER_EC_GENERIC_DB_SOFT_FAILURE, "insert_deposit"); return; } @@ -1871,7 +1881,7 @@ check_payment_sufficient (struct PayContext *pc) * * @param pc context to trigger notification for */ -static void +static enum GNUNET_DB_QueryStatus trigger_payment_notification (struct PayContext *pc) { { @@ -1916,6 +1926,9 @@ trigger_payment_notification (struct PayContext *pc) NULL, 0); } + return TMH_trigger_webhook (pc->hc->instance->settings.id, + "pay", + pc->contract_terms); } @@ -2101,7 +2114,26 @@ execute_pay_transaction (struct PayContext *pc) TMH_OSF_CLAIMED | TMH_OSF_PAID, pc->timestamp, pc->order_serial); - + { + enum GNUNET_DB_QueryStatus qs; + + qs = trigger_payment_notification (pc); + if (qs < 0) + { + TMH_db->rollback (TMH_db->cls); + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + { + execute_pay_transaction (pc); + return; + } + GNUNET_break (0); + resume_pay_with_error (pc, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "failed to trigger webhooks"); + return; + } + } { enum GNUNET_DB_QueryStatus qs; @@ -2123,7 +2155,6 @@ execute_pay_transaction (struct PayContext *pc) NULL); return; } - trigger_payment_notification (pc); } generate_success_response (pc); } @@ -2509,13 +2540,17 @@ check_contract (struct PayContext *pc) { /* obtain contract terms */ enum GNUNET_DB_QueryStatus qs; - json_t *contract_terms = NULL; bool paid = false; + if (NULL != pc->contract_terms) + { + json_decref (pc->contract_terms); + pc->contract_terms = NULL; + } qs = TMH_db->lookup_contract_terms (TMH_db->cls, pc->hc->instance->settings.id, pc->order_id, - &contract_terms, + &pc->contract_terms, &pc->order_serial, &paid, NULL); @@ -2546,11 +2581,10 @@ check_contract (struct PayContext *pc) } /* hash contract (needed later) */ if (GNUNET_OK != - TALER_JSON_contract_hash (contract_terms, + TALER_JSON_contract_hash (pc->contract_terms, &pc->h_contract_terms)) { GNUNET_break (0); - json_decref (contract_terms); return (MHD_YES == TALER_MHD_reply_with_error (pc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, @@ -2572,12 +2606,11 @@ check_contract (struct PayContext *pc) GNUNET_h2s (&pc->h_contract_terms.hash)); /* basic sanity check on the contract */ - if (NULL == json_object_get (contract_terms, + if (NULL == json_object_get (pc->contract_terms, "merchant")) { /* invalid contract */ GNUNET_break (0); - json_decref (contract_terms); return (MHD_YES == TALER_MHD_reply_with_error (pc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, @@ -2626,11 +2659,10 @@ check_contract (struct PayContext *pc) pc->minimum_age = 0; res = TALER_MHD_parse_internal_json_data (pc->connection, - contract_terms, + pc->contract_terms, espec); if (NULL != fulfillment_url) pc->fulfillment_url = GNUNET_strdup (fulfillment_url); - json_decref (contract_terms); if (GNUNET_YES != res) { GNUNET_break (0); diff --git a/src/backend/taler-merchant-httpd_private-delete-pending-webhooks-ID.h b/src/backend/taler-merchant-httpd_private-delete-pending-webhooks-ID.h deleted file mode 100644 index f558ce4d..00000000 --- a/src/backend/taler-merchant-httpd_private-delete-pending-webhooks-ID.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of TALER - (C) 2023 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 - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-delete-pending-webhooks-ID.h - * @brief implement DELETE /pending webhooks/$ID/ - * @author Priscilla HUANG - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_PENDING_WEBHOOKS_ID_H -#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_PENDING_WEBHOOKS_ID_H - -#include "taler-merchant-httpd.h" - - -/** - * Handle a DELETE "/pending webhooks/$ID" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_delete_pending_webhooks_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -/* end of taler-merchant-httpd_private-delete-pending-webhooks-ID.h */ -#endif diff --git a/src/backend/taler-merchant-httpd_private-get-pending-webhooks-ID.c b/src/backend/taler-merchant-httpd_private-get-pending-webhooks-ID.c deleted file mode 100644 index 7536b2f2..00000000 --- a/src/backend/taler-merchant-httpd_private-get-pending-webhooks-ID.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - This file is part of TALER - (C) 2023 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 - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-get-pending-webhooks-ID.c - * @brief implement GET /pending webhooks/$ID - * @author Priscilla HUANG - */ -#include "platform.h" -#include "taler-merchant-httpd_private-get-pending-webhooks-ID.h" -#include <taler/taler_json_lib.h> - - -/** - * Handle a GET "/pending webhooks/$ID" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_get_pending_webhooks_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct TMH_MerchantInstance *mi = hc->instance; - struct TALER_MERCHANTDB_PendingWebhookDetails pwb = { 0 }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_assert (NULL != mi); - qs = TMH_db->lookup_pending_webhook (TMH_db->cls, - mi->settings.id, - hc->infix, - &pwb); - if (0 > qs) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - "lookup_pending_webhook"); - } - if (0 == qs) - { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_MERCHANT_GENERIC_PENDING_WEBHOOK_UNKNOWN, - hc->infix); - } - { - MHD_RESULT ret; - - ret = TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_absolute ("next_attempt", - pwb.next_attempt), - GNUNET_JSON_pack_uint32 ("retries", - pwb.retries), - GNUNET_JSON_pack_string ("url", - pwb.url), - GNUNET_JSON_pack_string ("http_method", - pwb.http_method), - GNUNET_JSON_pack_string ("header", - pwb.header), - GNUNET_JSON_pack_string ("body" - pwb.body)); - GNUNET_free (pwb.url); - GNUNET_free (pwb.http_method); - GNUNET_free (pwb.header_template); - GNUNET_free (pwb.body_template); - - return ret; - } -} - - -/* end of taler-merchant-httpd_private-get-webhooks-ID.c */ diff --git a/src/backend/taler-merchant-httpd_private-get-pending-webhooks-ID.h b/src/backend/taler-merchant-httpd_private-get-pending-webhooks-ID.h deleted file mode 100644 index 6edd709e..00000000 --- a/src/backend/taler-merchant-httpd_private-get-pending-webhooks-ID.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of TALER - (C) 2023 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 - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-merchant-httpd_private-get-pending-webhooks-ID.h - * @brief implement GET /pending webhooks/$ID/ - * @author Priscilla HUANG - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_PENDING_WEBHOOKS_ID_H -#define TALER_MERCHANT_HTTPD_PRIVATE_GET_PENDING_WEBHOOKS_ID_H - -#include "taler-merchant-httpd.h" - - -/** - * Handle a GET "/pending webhooks/$ID" request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_get_pending_webhooks_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -/* end of taler-merchant-httpd_private-get-pending-webhooks-ID.h */ -#endif diff --git a/src/backend/taler-merchant-httpd_private-patch-pending-webhooks-ID.c b/src/backend/taler-merchant-httpd_private-patch-pending-webhooks-ID.c deleted file mode 100644 index 1a09c259..00000000 --- a/src/backend/taler-merchant-httpd_private-patch-pending-webhooks-ID.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - This file is part of TALER - (C) 2023 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 Foundation; either version 3, - or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, - see <http://www.gnu.org/licenses/> -*/ - -/** - * @file taler-merchant-httpd_private-patch-pending-webhooks-ID.c - * @brief implementing PATCH /pending webhooks/$ID request handling - * @author Priscilla HUANG - */ -#include "platform.h" -#include "taler-merchant-httpd_private-patch-pending-webhooks-ID.h" -#include "taler-merchant-httpd_helper.h" -#include <taler/taler_json_lib.h> - -/** - * How often do we retry the simple INSERT database transaction? - */ -#define MAX_RETRIES 3 - - -/** - * Determine the cause of the PATCH failure in more detail and report. - * - * @param connection connection to report on - * @param instance_id instance we are processing - * @param webhook_serial ID of the pending webhook to patch - * @param pwb webhook details we failed to set - */ -static MHD_RESULT -determine_cause (struct MHD_Connection *connection, - const char *instance_id, - uint64_t *webhook_serial, - const struct TALER_MERCHANTDB_PendingWebhookDetails *pwb) -{ - struct TALER_MERCHANTDB_PendingWebhookDetails wpx; - enum GNUNET_DB_QueryStatus qs; - - qs = TMH_db->lookup_pending_webhook (TMH_db->cls, - instance_id, - webhook_serial, - &wpx); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - NULL); - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, - "unexpected serialization problem"); - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_MERCHANT_GENERIC_PENDING_WEBHOOK_UNKNOWN, - webhook_id); - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - break; /* do below */ - } - - { - enum TALER_ErrorCode ec; - - ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - TALER_MERCHANTDB_pending_webhook_details_free (&wpx); - GNUNET_break (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE != ec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - ec, - NULL); - } -} - -/** - * PATCH configuration of an existing instance, given its configuration. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_patch_pending_webhooks_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct TMH_MerchantInstance *mi = hc->instance; - uint64_t *webhook_serial = hc->infix; - struct TALER_MERCHANTDB_PendingWebhookDetails pwb = {0}; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_absolute ("next_attempt", - (&pwb.next_attempt), - GNUNET_JSON_spec_end () - }; - - GNUNET_assert (NULL != mi); - GNUNET_assert (NULL != webhook_serial); - { - enum GNUNET_GenericReturnValue res; - - res = TALER_MHD_parse_json_data (connection, - hc->request_body, - spec); - if (GNUNET_OK != res) - return (GNUNET_NO == res) - ? MHD_YES - : MHD_NO; - } - - - qs = TMH_db->update_pending_webhook (TMH_db->cls, - mi->settings.id, - webhook_serial, - &pwb); - { - MHD_RESULT ret = MHD_NO; - - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - NULL); - break; - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_break (0); - ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, - "unexpected serialization problem"); - break; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - ret = determine_cause (connection, - mi->settings.id, - webhook_serial, - &pwb); - break; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - ret = TALER_MHD_reply_static (connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0); - break; - } - GNUNET_JSON_parse_free (spec); - return ret; - } -} - - - /* end of taler-merchant-httpd_private-patch-pending-webhooks-ID.c */ diff --git a/src/backend/taler-merchant-httpd_private-patch-pending-webhooks-ID.h b/src/backend/taler-merchant-httpd_private-patch-pending-webhooks-ID.h deleted file mode 100644 index 409fec9b..00000000 --- a/src/backend/taler-merchant-httpd_private-patch-pending-webhooks-ID.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of TALER - (C) 2023 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 Foundation; either version 3, - or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, - see <http://www.gnu.org/licenses/> -*/ - -/** - * @file taler-merchant-httpd_private-patch-pending-webhooks-ID.h - * @brief implementing PATCH /pending webhooks request handling - * @author Priscilla HUANG - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_PENDING_WEBHOOKS_ID_H -#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_PENDING_WEBHOOKS_ID_H -#include "taler-merchant-httpd.h" - - -/** - * PATCH configuration of an existing instance, given its configuration. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_patch_pending_webhooks_ID (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -#endif diff --git a/src/backend/taler-merchant-httpd_private-post-pending-webhooks.c b/src/backend/taler-merchant-httpd_private-post-pending-webhooks.c deleted file mode 100644 index 6115124f..00000000 --- a/src/backend/taler-merchant-httpd_private-post-pending-webhooks.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - This file is part of TALER - (C) 2023 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 Foundation; either version 3, - or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, - see <http://www.gnu.org/licenses/> -*/ - -/** - * @file taler-merchant-httpd_private-post-pending-webhooks.c - * @brief implementing POST /pending webhooks request handling - * @author Priscilla HUANG - */ -#include "platform.h" -#include "taler-merchant-httpd_private-post-webhooks.h" -#include "taler-merchant-httpd_helper.h" -#include <taler/taler_json_lib.h> - -/** - * How often do we retry the simple INSERT database transaction? - */ -#define MAX_RETRIES 3 - - -/** - * Check if the two pending webhooks are identical. - * - * @param pw1 pending webhook to compare - * @param pw2 other pending webhook to compare - * @return true if they are 'equal', false if not or of payto_uris is not an array - */ -static bool -pending_webhooks_equal (const struct TALER_MERCHANTDB_PendingWebhookDetails *pw1, - const struct TALER_MERCHANTDB_PendingWebhookDetails *pw2) -{ - return ( (GNUNET_TIME_absolute_cmp (pw1->next_attempt, - ==, - pw2->next_attempt)) && - (pw1->retries == pw2->retries) && - (0 == strcmp (pw1->url, - pw2->url)) && - (0 == strcmp (pw1->http_method, - pw2->http_method)) && - (0 == strcmp (pw1->header, - pw2->heade)) && - (0 == strcmp (pw1->body, - pw2->body))); -} - - -MHD_RESULT -TMH_private_post_pending_webhooks (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - struct TMH_MerchantInstance *mi = hc->instance; - struct TALER_MERCHANTDB_PendingWebhookDetails pwb = { 0 }; - uint64_t *webhook_serial; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_uint64 ("webhook_serial", - &webhook_serial), - GNUNET_JSON_spec_absolute ("next_attempt", - &pwb.next_attempt), - GNUNET_JSON_spec_uint64 ("retries", - &pwb.retries), - GNUNET_JSON_spec_string ("url", - (const char **) &wb.url), - GNUNET_JSON_spec_string ("http_method", - (const char **) &wb.http_method), - GNUNET_JSON_spec_string ("header", - (const char **) &wb.header), - GNUNET_JSON_spec_string ("body", - (const char **) &wb.body), - GNUNET_JSON_spec_end () - }; - - GNUNET_assert (NULL != mi); - { - enum GNUNET_GenericReturnValue res; - - res = TALER_MHD_parse_json_data (connection, - hc->request_body, - spec); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - return (GNUNET_NO == res) - ? MHD_YES - : MHD_NO; - } - } - - - - /* finally, interact with DB until no serialization error */ - for (unsigned int i = 0; i<MAX_RETRIES; i++) - { - /* Test if a pending webhook of this id is known */ - struct TALER_MERCHANTDB_PendingWebhooksDetails epwb; - - if (GNUNET_OK != - TMH_db->start (TMH_db->cls, - "/post pending webhooks")) - { - GNUNET_break (0); - GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_START_FAILED, - NULL); - } - qs = TMH_db->lookup_pending_webhook (TMH_db->cls, - mi->settings.id, - webhook_serial, - &ewb); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - /* Clean up and fail hard */ - GNUNET_break (0); - TMH_db->rollback (TMH_db->cls); - GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - NULL); - case GNUNET_DB_STATUS_SOFT_ERROR: - /* restart transaction */ - goto retry; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* Good, we can proceed! */ - break; - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - /* idempotency check: is ewb == wb? */ - { - bool eq; - - eq = pending_webhooks_equal (&pwb, - &epwb); - TALER_MERCHANTDB_pending_webhook_details_free(&epwb); - TMH_db->rollback (TMH_db->cls); - GNUNET_JSON_parse_free (spec); - return eq - ? TALER_MHD_reply_static (connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0) - : TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_PRIVATE_POST_PENDING_WEBHOOKS_CONFLICT_PENDING_WEBHOOKS_EXISTS, - webhook_serial - } - } /* end switch (qs) */ - - qs = TMH_db->insert_pending_webhook (TMH_db->cls, - mi->settings.id, - webhook_serial, - &pwb); - if (GNUNET_DB_STATUS_HARD_ERROR == qs) - { - TMH_db->rollback (TMH_db->cls); - break; - } - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - qs = TMH_db->commit (TMH_db->cls); - if (GNUNET_DB_STATUS_SOFT_ERROR != qs) - break; - } -retry: - GNUNET_assert (GNUNET_DB_STATUS_SOFT_ERROR == qs); - TMH_db->rollback (TMH_db->cls); - } /* for RETRIES loop */ - GNUNET_JSON_parse_free (spec); - if (qs < 0) - { - GNUNET_break (0); - return TALER_MHD_reply_with_error ( - connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - (GNUNET_DB_STATUS_SOFT_ERROR == qs) - ? TALER_EC_GENERIC_DB_SOFT_FAILURE - : TALER_EC_GENERIC_DB_COMMIT_FAILED, - NULL); - } - return TALER_MHD_reply_static (connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0); -} - - - /* end of taler-merchant-httpd_private-post-pending-webhooks.c */ diff --git a/src/backend/taler-merchant-httpd_private-post-pending-webhooks.h b/src/backend/taler-merchant-httpd_private-post-pending-webhooks.h deleted file mode 100644 index 0bf317b7..00000000 --- a/src/backend/taler-merchant-httpd_private-post-pending-webhooks.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of TALER - (C) 2023 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 Foundation; either version 3, - or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, - see <http://www.gnu.org/licenses/> -*/ - -/** - * @file taler-merchant-httpd_private-post-pending-webhooks.h - * @brief implementing POST /pending webhooks request handling - * @author Priscilla HUANG - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_PENDING_WEBHOOKS_H -#define TALER_MERCHANT_HTTPD_PRIVATE_POST_PENDING_WEBHOOKS_H -#include "taler-merchant-httpd.h" - - -/** - * Generate a pending webhook entry. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] hc context with further information about the request - * @return MHD result code - */ -MHD_RESULT -TMH_private_post_pending_webhooks (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -#endif diff --git a/src/backend/taler-merchant-httpd_private-post-templates.c b/src/backend/taler-merchant-httpd_private-post-templates.c index 8377b034..1dd324e4 100644 --- a/src/backend/taler-merchant-httpd_private-post-templates.c +++ b/src/backend/taler-merchant-httpd_private-post-templates.c @@ -194,8 +194,8 @@ TMH_private_post_templates (const struct TMH_RequestHandler *rh, if (GNUNET_DB_STATUS_SOFT_ERROR != qs) break; } -retry: - GNUNET_assert (GNUNET_DB_STATUS_SOFT_ERROR == qs); +retry: + GNUNET_assert (GNUNET_DB_STATUS_SOFT_ERROR == qs); TMH_db->rollback (TMH_db->cls); } /* for RETRIES loop */ GNUNET_JSON_parse_free (spec); diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 230417e7..e87021ea 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -7773,7 +7773,7 @@ postgres_lookup_all_webhooks (void *cls, struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (instance_id), GNUNET_PQ_query_param_uint64 (&min_row), - GNUNET_PQ_query_param_uint64 (&max_results64), + GNUNET_PQ_query_param_uint64 (&max_results64), GNUNET_PQ_query_param_end }; @@ -7800,16 +7800,24 @@ postgres_lookup_all_webhooks (void *cls, * @param next_attempt when we should make the next request to the webhook * @return database result code */ +<<<<<<< HEAD static enum GNUNET_DB_QueryStatus postgres_update_pending_webhook (void *cls, uint64_t webhook_serial, struct GNUNET_TIME_Absolute next_attempt) // maybe add: http status of failure? +======= + static enum GNUNET_DB_QueryStatus + postgres_update_pending_webhook(void *cls, + uint64_t webhook_serial, + const struct TALER_MERCHANTDB_PendingWebhookDetails *pwb) + // maybe add: http status of failure? +>>>>>>> ee56051c (backend for pending webhook) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&webhook_serial), - GNUNET_PQ_query_param_absolute_time (&next_attempt), + GNUNET_PQ_query_param_absolute_time (&pwb->next_attempt), GNUNET_PQ_query_param_end }; diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c index 69a376aa..cbf4e4b6 100644 --- a/src/backenddb/test_merchantdb.c +++ b/src/backenddb/test_merchantdb.c @@ -7909,7 +7909,7 @@ test_update_pending_webhook (const struct InstanceData *instance, TEST_COND_RET_ON_FAIL (expected_result == plugin->update_pending_webhook (plugin->cls, pwebhook->webhook_serial, - pwebhook->pwebhook.next_attempt), + &pwebhook->pwebhook), "Update pending webhook failed\n"); return 0; } diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index 707cf2d9..54432e52 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -2828,8 +2828,13 @@ struct TALER_MERCHANTDB_Plugin enum GNUNET_DB_QueryStatus (*update_pending_webhook)(void *cls, uint64_t webhook_serial, +<<<<<<< HEAD struct GNUNET_TIME_Absolute next_attempt); // maybe add: http status of failure? +======= + const struct TALER_MERCHANTDB_PendingWebhookDetails *pwb); + // maybe add: http status of failure? +>>>>>>> ee56051c (backend for pending webhook) /** diff --git a/src/testing/testing_api_cmd_post_using_templates.c b/src/testing/testing_api_cmd_post_using_templates.c index 137c7df1..956a421a 100644 --- a/src/testing/testing_api_cmd_post_using_templates.c +++ b/src/testing/testing_api_cmd_post_using_templates.c @@ -209,8 +209,7 @@ TALER_TESTING_cmd_merchant_post_using_templates ( const char *template_ref, const char *merchant_url, const char *summary, - const char *amount, - unsigned int http_status) + const char *amount, unsigned int http_status) { struct PostUsingTemplatesState *tis; |