From 62220c02979c1a7e81d8ac261d2f624680bdedc1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 28 May 2023 00:06:08 +0200 Subject: towards a CRUD API for merchant instance account editing --- src/backend/Makefile.am | 28 ++-- src/backend/taler-merchant-httpd.c | 47 ++++-- src/backend/taler-merchant-httpd.h | 9 + ...aler-merchant-httpd_private-delete-account-ID.c | 94 +++++++++++ ...aler-merchant-httpd_private-delete-account-ID.h | 42 +++++ .../taler-merchant-httpd_private-post-account.c | 184 +++++++++++++++++++++ .../taler-merchant-httpd_private-post-account.h | 44 +++++ 7 files changed, 424 insertions(+), 24 deletions(-) create mode 100644 src/backend/taler-merchant-httpd_private-delete-account-ID.c create mode 100644 src/backend/taler-merchant-httpd_private-delete-account-ID.h create mode 100644 src/backend/taler-merchant-httpd_private-post-account.c create mode 100644 src/backend/taler-merchant-httpd_private-post-account.h diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 4edca6ac..e62124a9 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -36,10 +36,8 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_private-get-tips-ID.c \ taler-merchant-httpd_private-get-tips-ID.h \ taler-merchant-httpd_mhd.c taler-merchant-httpd_mhd.h \ - taler-merchant-httpd_private-delete-templates-ID.c \ - taler-merchant-httpd_private-delete-templates-ID.h \ - taler-merchant-httpd_private-delete-webhooks-ID.c \ - taler-merchant-httpd_private-delete-webhooks-ID.h \ + taler-merchant-httpd_private-delete-account-ID.c \ + taler-merchant-httpd_private-delete-account-ID.h \ taler-merchant-httpd_private-delete-instances-ID.c \ taler-merchant-httpd_private-delete-instances-ID.h \ taler-merchant-httpd_private-delete-products-ID.c \ @@ -48,8 +46,12 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_private-delete-orders-ID.h \ taler-merchant-httpd_private-delete-reserves-ID.c \ taler-merchant-httpd_private-delete-reserves-ID.h \ + taler-merchant-httpd_private-delete-templates-ID.c \ + taler-merchant-httpd_private-delete-templates-ID.h \ taler-merchant-httpd_private-delete-transfers-ID.c \ taler-merchant-httpd_private-delete-transfers-ID.h \ + taler-merchant-httpd_private-delete-webhooks-ID.c \ + taler-merchant-httpd_private-delete-webhooks-ID.h \ taler-merchant-httpd_private-get-instances.c \ taler-merchant-httpd_private-get-instances.h \ taler-merchant-httpd_private-get-instances-ID.c \ @@ -88,14 +90,16 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_private-patch-orders-ID-forget.h \ taler-merchant-httpd_private-patch-products-ID.c \ taler-merchant-httpd_private-patch-products-ID.h \ - taler-merchant-httpd_private-post-templates.c \ - taler-merchant-httpd_private-post-templates.h \ - taler-merchant-httpd_private-post-webhooks.c \ - taler-merchant-httpd_private-post-webhooks.h \ + taler-merchant-httpd_private-post-account.c \ + taler-merchant-httpd_private-post-account.h \ taler-merchant-httpd_private-post-instances.c \ taler-merchant-httpd_private-post-instances.h \ taler-merchant-httpd_private-post-instances-ID-auth.c \ taler-merchant-httpd_private-post-instances-ID-auth.h \ + taler-merchant-httpd_private-post-orders-ID-refund.c \ + taler-merchant-httpd_private-post-orders-ID-refund.h \ + taler-merchant-httpd_private-post-orders.c \ + taler-merchant-httpd_private-post-orders.h \ taler-merchant-httpd_private-post-products.c \ taler-merchant-httpd_private-post-products.h \ taler-merchant-httpd_private-post-products-ID-lock.c \ @@ -104,12 +108,12 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_private-post-reserves.h \ taler-merchant-httpd_private-post-reserves-ID-authorize-tip.c \ taler-merchant-httpd_private-post-reserves-ID-authorize-tip.h \ - taler-merchant-httpd_private-post-orders-ID-refund.c \ - taler-merchant-httpd_private-post-orders-ID-refund.h \ - taler-merchant-httpd_private-post-orders.c \ - taler-merchant-httpd_private-post-orders.h \ + taler-merchant-httpd_private-post-templates.c \ + taler-merchant-httpd_private-post-templates.h \ taler-merchant-httpd_private-post-transfers.c \ taler-merchant-httpd_private-post-transfers.h \ + taler-merchant-httpd_private-post-webhooks.c \ + taler-merchant-httpd_private-post-webhooks.h \ taler-merchant-httpd_post-orders-ID-abort.c \ taler-merchant-httpd_post-orders-ID-abort.h \ taler-merchant-httpd_post-orders-ID-claim.c \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index d7ac2b74..00e4689c 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -33,13 +33,14 @@ #include "taler-merchant-httpd_get-orders-ID.h" #include "taler-merchant-httpd_get-tips-ID.h" #include "taler-merchant-httpd_mhd.h" -#include "taler-merchant-httpd_private-delete-webhooks-ID.h" -#include "taler-merchant-httpd_private-delete-templates-ID.h" +#include "taler-merchant-httpd_private-delete-account-ID.h" #include "taler-merchant-httpd_private-delete-instances-ID.h" #include "taler-merchant-httpd_private-delete-products-ID.h" #include "taler-merchant-httpd_private-delete-orders-ID.h" #include "taler-merchant-httpd_private-delete-reserves-ID.h" +#include "taler-merchant-httpd_private-delete-templates-ID.h" #include "taler-merchant-httpd_private-delete-transfers-ID.h" +#include "taler-merchant-httpd_private-delete-webhooks-ID.h" #include "taler-merchant-httpd_private-get-webhooks.h" #include "taler-merchant-httpd_private-get-webhooks-ID.h" #include "taler-merchant-httpd_private-get-templates.h" @@ -61,8 +62,7 @@ #include "taler-merchant-httpd_private-patch-instances-ID.h" #include "taler-merchant-httpd_private-patch-orders-ID-forget.h" #include "taler-merchant-httpd_private-patch-products-ID.h" -#include "taler-merchant-httpd_private-post-webhooks.h" -#include "taler-merchant-httpd_private-post-templates.h" +#include "taler-merchant-httpd_private-post-account.h" #include "taler-merchant-httpd_private-post-instances.h" #include "taler-merchant-httpd_private-post-instances-ID-auth.h" #include "taler-merchant-httpd_private-post-orders.h" @@ -71,7 +71,9 @@ #include "taler-merchant-httpd_private-post-products-ID-lock.h" #include "taler-merchant-httpd_private-post-reserves.h" #include "taler-merchant-httpd_private-post-reserves-ID-authorize-tip.h" +#include "taler-merchant-httpd_private-post-templates.h" #include "taler-merchant-httpd_private-post-transfers.h" +#include "taler-merchant-httpd_private-post-webhooks.h" #include "taler-merchant-httpd_post-orders-ID-abort.h" #include "taler-merchant-httpd_post-orders-ID-claim.h" #include "taler-merchant-httpd_post-orders-ID-paid.h" @@ -223,6 +225,17 @@ TMH_compute_auth (const char *token, } +void +TMH_wire_method_free (struct TMH_WireMethod *wm) +{ + GNUNET_free (wm->payto_uri); + GNUNET_free (wm->wire_method); + GNUNET_free (wm->credit_facade_url); + json_decref (wm->credit_facade_credentials); + GNUNET_free (wm); +} + + void TMH_instance_decref (struct TMH_MerchantInstance *mi) { @@ -237,11 +250,7 @@ TMH_instance_decref (struct TMH_MerchantInstance *mi) GNUNET_CONTAINER_DLL_remove (mi->wm_head, mi->wm_tail, wm); - GNUNET_free (wm->payto_uri); - GNUNET_free (wm->wire_method); - GNUNET_free (wm->credit_facade_url); - json_decref (wm->credit_facade_credentials); - GNUNET_free (wm); + TMH_wire_method_free (wm); } GNUNET_free (mi->settings.id); @@ -1067,6 +1076,21 @@ url_handler (void *cls, in the code... */ .max_upload = 1024 * 1024 * 8 }, + /* POST /account: */ + { + .url_prefix = "/account", + .method = MHD_HTTP_METHOD_POST, + .handler = &TMH_private_post_account, + /* allow account details of up to 8 kb, that should be plenty */ + .max_upload = 1024 * 8 + }, + /* DELETE /account/$PAYTO: */ + { + .url_prefix = "/account", + .method = MHD_HTTP_METHOD_DELETE, + .handler = &TMH_private_delete_account_ID, + .have_id_segment = true + }, { .url_prefix = NULL } @@ -1816,9 +1840,8 @@ load_instances (void *cls, /** - * A transaction modified an instance setting - * (or created/deleted/purged one). Notify all - * backends about the change. + * A transaction modified an instance setting (or created/deleted/purged + * one). Notify all backends about the change. * * @param id ID of the instance that changed */ diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h index 6f637934..46bbcb5b 100644 --- a/src/backend/taler-merchant-httpd.h +++ b/src/backend/taler-merchant-httpd.h @@ -695,6 +695,15 @@ void TMH_instance_decref (struct TMH_MerchantInstance *mi); +/** + * Free memory allocated by @a wm. + * + * @param[in] wm wire method to free + */ +void +TMH_wire_method_free (struct TMH_WireMethod *wm); + + /** * Lookup a merchant instance by its instance ID. * diff --git a/src/backend/taler-merchant-httpd_private-delete-account-ID.c b/src/backend/taler-merchant-httpd_private-delete-account-ID.c new file mode 100644 index 00000000..7b7aa6e0 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-delete-account-ID.c @@ -0,0 +1,94 @@ +/* + 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 +*/ +/** + * @file taler-merchant-httpd_private-delete-account-ID.c + * @brief implement DELETE /account/$H_WIRE + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-delete-account-ID.h" +#include +#include + + +MHD_RESULT +TMH_private_delete_account_ID (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + struct TMH_MerchantInstance *mi = hc->instance; + struct TALER_MerchantWireHashP h_wire; + enum GNUNET_DB_QueryStatus qs; + + (void) rh; + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (hc->infix, + strlen (hc->infix), + &h_wire, + sizeof (h_wire))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "h_wire"); + } + GNUNET_assert (NULL != mi); + qs = TMH_db->inactivate_account (TMH_db->cls, + mi->settings.id, + &h_wire); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "inactivate_account"); + 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, + NULL); + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_PRIVATE_ACCOUNT_DELETE_UNKNOWN_ACCOUNT, + "account unknown"); + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + } + { + struct GNUNET_DB_EventHeaderP es = { + .size = htons (sizeof (es)), + .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED) + }; + + TMH_db->event_notify (TMH_db->cls, + &es, + NULL, + 0); + } + TMH_reload_instances (mi->settings.id); + return TALER_MHD_reply_static (connection, + MHD_HTTP_NO_CONTENT, + NULL, + NULL, + 0); +} + + +/* end of taler-merchant-httpd_private-delete-account-ID.c */ diff --git a/src/backend/taler-merchant-httpd_private-delete-account-ID.h b/src/backend/taler-merchant-httpd_private-delete-account-ID.h new file mode 100644 index 00000000..b9004b9f --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-delete-account-ID.h @@ -0,0 +1,42 @@ +/* + 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 +*/ +/** + * @file taler-merchant-httpd_private-delete-account-ID.h + * @brief implement DELETE /account/$PAYTO + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_ACCOUNT_ID_H +#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_ACCOUNT_ID_H + +#include "taler-merchant-httpd.h" + + +/** + * Handle a DELETE "/private/account/$H_WIRE" 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_account_ID (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + + +/* end of taler-merchant-httpd_private-delete-account-ID.h */ +#endif diff --git a/src/backend/taler-merchant-httpd_private-post-account.c b/src/backend/taler-merchant-httpd_private-post-account.c new file mode 100644 index 00000000..8e93203b --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-post-account.c @@ -0,0 +1,184 @@ +/* + This file is part of TALER + (C) 2020-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 +*/ + +/** + * @file taler-merchant-httpd_private-post-account.c + * @brief implementing POST /private/account request handling + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-post-account.h" +#include "taler-merchant-httpd_helper.h" +#include "taler_merchant_bank_lib.h" +#include +#include + + +MHD_RESULT +TMH_private_post_account (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + struct TMH_MerchantInstance *mi = hc->instance; + const char *credit_facade_url = NULL; + json_t *credit_facade_credentials = NULL; + const char *uri; + struct GNUNET_JSON_Specification ispec[] = { + GNUNET_JSON_spec_string ("payto_uri", + &uri), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("credit_facade_url", + &credit_facade_url), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_json ("credit_facade_credentials", + &credit_facade_credentials), + NULL), + GNUNET_JSON_spec_end () + }; + struct TMH_WireMethod *wm; + + { + enum GNUNET_GenericReturnValue res; + + res = TALER_MHD_parse_json_data (connection, + hc->request_body, + ispec); + if (GNUNET_OK != res) + return (GNUNET_NO == res) + ? MHD_YES + : MHD_NO; + } + + { + char *err; + + if (NULL != + (err = TALER_payto_validate (uri))) + { + MHD_RESULT mret; + + GNUNET_break_op (0); + mret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PAYTO_URI_MALFORMED, + err); + GNUNET_free (err); + return mret; + } + } + + if ( (NULL == credit_facade_url) != + (NULL == credit_facade_credentials) ) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MISSING, + (NULL == credit_facade_url) + ? "credit_facade_url" + : "credit_facade_credentials"); + } + if ( (NULL != credit_facade_url) || + (NULL != credit_facade_credentials) ) + { + struct TALER_MERCHANT_BANK_AuthenticationData auth; + + if (GNUNET_OK != + TALER_MERCHANT_BANK_auth_parse_json (credit_facade_credentials, + credit_facade_url, + &auth)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "credit_facade_credentials"); + } + TALER_MERCHANT_BANK_auth_free (&auth); + } + + /* convert provided payto URI into internal data structure with salts */ + wm = TMH_setup_wire_account (uri, + credit_facade_url, + credit_facade_credentials); + GNUNET_assert (NULL != wm); + { + struct TALER_MERCHANTDB_AccountDetails ad = { + .payto_uri = wm->payto_uri, + .salt = wm->wire_salt, + .h_wire = wm->h_wire, + .credit_facade_url = wm->credit_facade_url, + .credit_facade_credentials = wm->credit_facade_credentials, + .active = wm->active + }; + enum GNUNET_DB_QueryStatus qs; + + qs = TMH_db->insert_account (TMH_db->cls, + mi->settings.id, + &ad); + switch (qs) + { + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* conflict: account exists */ + TMH_wire_method_free (wm); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_ACCOUNT_EXISTS, + uri); + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TMH_wire_method_free (wm); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "insert_account"); + } + } + + { + struct GNUNET_DB_EventHeaderP es = { + .size = htons (sizeof (es)), + .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED) + }; + + TMH_db->event_notify (TMH_db->cls, + &es, + NULL, + 0); + } + /* Finally, also update our running process */ + GNUNET_CONTAINER_DLL_insert (mi->wm_head, + mi->wm_tail, + wm); + /* Note: we may not need to do this, as we notified + about the account change above. But also hardly hurts. */ + TMH_reload_instances (mi->settings.id); + return TALER_MHD_reply_static (connection, + MHD_HTTP_NO_CONTENT, + NULL, + NULL, + 0); +} + + +/* end of taler-merchant-httpd_private-post-account.c */ diff --git a/src/backend/taler-merchant-httpd_private-post-account.h b/src/backend/taler-merchant-httpd_private-post-account.h new file mode 100644 index 00000000..99f61090 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-post-account.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + (C) 2020-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 +*/ + +/** + * @file taler-merchant-httpd_private-post-account.h + * @brief implementing POST /private/account request handling + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_ACCOUNT_H +#define TALER_MERCHANT_HTTPD_PRIVATE_POST_ACCOUNT_H + +#include "taler-merchant-httpd.h" + + +/** + * Add bank account to an instance. + * + * @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_account (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif -- cgit v1.2.3