summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/#taler-merchant-httpd_private-patch-templates-ID.c#197
-rw-r--r--src/backend/Makefile.am24
-rw-r--r--src/backend/taler-merchant-httpd.c138
-rw-r--r--src/backend/taler-merchant-httpd_post-using-templates.c11
-rw-r--r--src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.c78
-rw-r--r--src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.h41
-rw-r--r--src/backend/taler-merchant-httpd_private-get-accounts-ID.c103
-rw-r--r--src/backend/taler-merchant-httpd_private-get-accounts-ID.h41
-rw-r--r--src/backend/taler-merchant-httpd_private-get-accounts.c78
-rw-r--r--src/backend/taler-merchant-httpd_private-get-accounts.h41
-rw-r--r--src/backend/taler-merchant-httpd_private-get-otp-devices-ID.c83
-rw-r--r--src/backend/taler-merchant-httpd_private-get-otp-devices-ID.h41
-rw-r--r--src/backend/taler-merchant-httpd_private-get-otp-devices.c80
-rw-r--r--src/backend/taler-merchant-httpd_private-get-otp-devices.h41
-rw-r--r--src/backend/taler-merchant-httpd_private-get-templates-ID.c9
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-accounts-ID.c132
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-accounts-ID.h43
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-instances-ID.c274
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-otp-devices-ID.c122
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-otp-devices-ID.h44
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-templates-ID.c16
-rw-r--r--src/backend/taler-merchant-httpd_private-post-account.c13
-rw-r--r--src/backend/taler-merchant-httpd_private-post-instances.c149
-rw-r--r--src/backend/taler-merchant-httpd_private-post-orders.c69
-rw-r--r--src/backend/taler-merchant-httpd_private-post-orders.h20
-rw-r--r--src/backend/taler-merchant-httpd_private-post-otp-devices.c201
-rw-r--r--src/backend/taler-merchant-httpd_private-post-otp-devices.h44
-rw-r--r--src/backend/taler-merchant-httpd_private-post-templates.c171
28 files changed, 1492 insertions, 812 deletions
diff --git a/src/backend/#taler-merchant-httpd_private-patch-templates-ID.c# b/src/backend/#taler-merchant-httpd_private-patch-templates-ID.c#
deleted file mode 100644
index 6739c7a9..00000000
--- a/src/backend/#taler-merchant-httpd_private-patch-templates-ID.c#
+++ /dev/null
@@ -1,197 +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-patch-templates-ID.c
- * @brief implementing PATCH /templates/$ID request handling
- * @author Priscilla HUANG
- */
-#include "platform.h"
-#include "taler-merchant-httpd_private-patch-templates-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 template_id ID of the product to patch
- * @param tp template details we failed to set
- */
-static MHD_RESULT
-determine_cause (struct MHD_Connection *connection,
- const char *instance_id,
- const char *template_id,
- const struct TALER_MERCHANTDB_TemplateDetails *tp)
-{
- struct TALER_MERCHANTDB_TemplateDetails tpx;
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TMH_db->lookup_template (TMH_db->cls,
- instance_id,
- template_id,
- &tpx);
- 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_TEMPLATE_UNKNOWN,
- template_id);
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break; /* do below */
- }
-
- {
- enum TALER_ErrorCode ec;
-
- ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
- TALER_MERCHANTDB_template_details_free (&tpx);
- 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_templates_ID (const struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- struct TMH_HandlerContext *hc)
-{
- struct TMH_MerchantInstance *mi = hc->instance;
- const char *template_id = hc->infix;
- struct TALER_MERCHANTDB_TemplateDetails tp = {0};
- enum GNUNET_DB_QueryStatus qs;
- uint32_t pos_algorithm;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("template_description",
- (const char **) &tp.template_description),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_uint32 ("pos_algorithm",
- &pos_algorithm),
- 0),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("pos_key",
- (const char **) &tp.pos_key),
- NULL),
- GNUNET_JSON_spec_json ("template_contract",
- &tp.template_contract),
- GNUNET_JSON_spec_end ()
- };
-
- GNUNET_assert (NULL != mi);
- GNUNET_assert (NULL != template_id);
- {
- 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;
- }
-
- tp.pos_algorithm = (enum TALER_MerchantConfirmationAlgorithm) pos_algorithm;
- if (! TMH_template_contract_valid (tp.template_contract))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "template_contract");
- }
-
- qs = TMH_db->update_template (TMH_db->cls,
- mi->settings.id,
- template_id,
- &tp);
- {
- 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,
- template_id,
- &tp);
- 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-templates-ID.c */
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index fed9c0a2..ef5b67bb 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -44,6 +44,8 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-delete-products-ID.h \
taler-merchant-httpd_private-delete-orders-ID.c \
taler-merchant-httpd_private-delete-orders-ID.h \
+ taler-merchant-httpd_private-delete-otp-devices-ID.c \
+ taler-merchant-httpd_private-delete-otp-devices-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 \
@@ -52,6 +54,10 @@ taler_merchant_httpd_SOURCES = \
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-accounts.c \
+ taler-merchant-httpd_private-get-accounts.h \
+ taler-merchant-httpd_private-get-accounts-ID.c \
+ taler-merchant-httpd_private-get-accounts-ID.h \
taler-merchant-httpd_private-get-instances.c \
taler-merchant-httpd_private-get-instances.h \
taler-merchant-httpd_private-get-instances-ID.c \
@@ -66,6 +72,10 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-get-orders.h \
taler-merchant-httpd_private-get-orders-ID.c \
taler-merchant-httpd_private-get-orders-ID.h \
+ taler-merchant-httpd_private-get-otp-devices.c \
+ taler-merchant-httpd_private-get-otp-devices.h \
+ taler-merchant-httpd_private-get-otp-devices-ID.c \
+ taler-merchant-httpd_private-get-otp-devices-ID.h \
taler-merchant-httpd_private-get-reserves.c \
taler-merchant-httpd_private-get-reserves.h \
taler-merchant-httpd_private-get-reserves-ID.c \
@@ -80,16 +90,20 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-get-webhooks.h \
taler-merchant-httpd_private-get-webhooks-ID.c \
taler-merchant-httpd_private-get-webhooks-ID.h \
- taler-merchant-httpd_private-patch-templates-ID.c \
- taler-merchant-httpd_private-patch-templates-ID.h \
- taler-merchant-httpd_private-patch-webhooks-ID.c \
- taler-merchant-httpd_private-patch-webhooks-ID.h \
+ taler-merchant-httpd_private-patch-accounts-ID.c \
+ taler-merchant-httpd_private-patch-accounts-ID.h \
taler-merchant-httpd_private-patch-instances-ID.c \
taler-merchant-httpd_private-patch-instances-ID.h \
taler-merchant-httpd_private-patch-orders-ID-forget.c \
taler-merchant-httpd_private-patch-orders-ID-forget.h \
+ taler-merchant-httpd_private-patch-otp-devices-ID.c \
+ taler-merchant-httpd_private-patch-otp-devices-ID.h \
taler-merchant-httpd_private-patch-products-ID.c \
taler-merchant-httpd_private-patch-products-ID.h \
+ taler-merchant-httpd_private-patch-templates-ID.c \
+ taler-merchant-httpd_private-patch-templates-ID.h \
+ taler-merchant-httpd_private-patch-webhooks-ID.c \
+ taler-merchant-httpd_private-patch-webhooks-ID.h \
taler-merchant-httpd_private-post-account.c \
taler-merchant-httpd_private-post-account.h \
taler-merchant-httpd_private-post-instances.c \
@@ -102,6 +116,8 @@ taler_merchant_httpd_SOURCES = \
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-otp-devices.c \
+ taler-merchant-httpd_private-post-otp-devices.h \
taler-merchant-httpd_private-post-products-ID-lock.c \
taler-merchant-httpd_private-post-products-ID-lock.h \
taler-merchant-httpd_private-post-reserves.c \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index d8be1edc..9c543958 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -37,14 +37,13 @@
#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-otp-devices-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"
-#include "taler-merchant-httpd_private-get-templates-ID.h"
+#include "taler-merchant-httpd_private-get-accounts.h"
+#include "taler-merchant-httpd_private-get-accounts-ID.h"
#include "taler-merchant-httpd_private-get-instances.h"
#include "taler-merchant-httpd_private-get-instances-ID.h"
#include "taler-merchant-httpd_private-get-instances-ID-kyc.h"
@@ -52,19 +51,28 @@
#include "taler-merchant-httpd_private-get-products-ID.h"
#include "taler-merchant-httpd_private-get-orders.h"
#include "taler-merchant-httpd_private-get-orders-ID.h"
+#include "taler-merchant-httpd_private-get-otp-devices.h"
+#include "taler-merchant-httpd_private-get-otp-devices-ID.h"
#include "taler-merchant-httpd_private-get-reserves.h"
#include "taler-merchant-httpd_private-get-reserves-ID.h"
#include "taler-merchant-httpd_private-get-rewards-ID.h"
#include "taler-merchant-httpd_private-get-rewards.h"
+#include "taler-merchant-httpd_private-get-templates.h"
+#include "taler-merchant-httpd_private-get-templates-ID.h"
#include "taler-merchant-httpd_private-get-transfers.h"
-#include "taler-merchant-httpd_private-patch-webhooks-ID.h"
-#include "taler-merchant-httpd_private-patch-templates-ID.h"
+#include "taler-merchant-httpd_private-get-webhooks.h"
+#include "taler-merchant-httpd_private-get-webhooks-ID.h"
+#include "taler-merchant-httpd_private-patch-accounts-ID.h"
#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-otp-devices-ID.h"
#include "taler-merchant-httpd_private-patch-products-ID.h"
+#include "taler-merchant-httpd_private-patch-templates-ID.h"
+#include "taler-merchant-httpd_private-patch-webhooks-ID.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-otp-devices.h"
#include "taler-merchant-httpd_private-post-orders.h"
#include "taler-merchant-httpd_private-post-orders-ID-refund.h"
#include "taler-merchant-httpd_private-post-products.h"
@@ -1041,6 +1049,39 @@ url_handler (void *cls,
.allow_deleted_instance = true,
.handler = &TMH_private_get_transfers
},
+ /* POST /otp-devices: */
+ {
+ .url_prefix = "/otp-devices",
+ .method = MHD_HTTP_METHOD_POST,
+ .handler = &TMH_private_post_otp_devices
+ },
+ /* GET /otp-devices: */
+ {
+ .url_prefix = "/otp-devices",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler = &TMH_private_get_otp_devices
+ },
+ /* GET /otp-devices/$ID/: */
+ {
+ .url_prefix = "/otp-devices/",
+ .method = MHD_HTTP_METHOD_GET,
+ .have_id_segment = true,
+ .handler = &TMH_private_get_otp_devices_ID
+ },
+ /* DELETE /otp-devices/$ID/: */
+ {
+ .url_prefix = "/otp-devices/",
+ .method = MHD_HTTP_METHOD_DELETE,
+ .have_id_segment = true,
+ .handler = &TMH_private_delete_otp_devices_ID
+ },
+ /* PATCH /otp-devices/$ID/: */
+ {
+ .url_prefix = "/otp-devices/",
+ .method = MHD_HTTP_METHOD_PATCH,
+ .have_id_segment = true,
+ .handler = &TMH_private_patch_otp_devices_ID
+ },
/* POST /templates: */
{
.url_prefix = "/templates",
@@ -1133,17 +1174,39 @@ url_handler (void *cls,
in the code... */
.max_upload = 1024 * 1024 * 8
},
- /* POST /account: */
+ /* POST /accounts: */
{
- .url_prefix = "/account",
+ .url_prefix = "/accounts",
.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: */
+ /* PATCH /accounts/$H_WIRE: */
{
- .url_prefix = "/account",
+ .url_prefix = "/accounts",
+ .method = MHD_HTTP_METHOD_PATCH,
+ .handler = &TMH_private_patch_accounts_ID,
+ .have_id_segment = true,
+ /* allow account details of up to 8 kb, that should be plenty */
+ .max_upload = 1024 * 8
+ },
+ /* GET /accounts: */
+ {
+ .url_prefix = "/accounts",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler = &TMH_private_get_accounts
+ },
+ /* GET /accounts/$H_WIRE: */
+ {
+ .url_prefix = "/accounts",
+ .method = MHD_HTTP_METHOD_GET,
+ .have_id_segment = true,
+ .handler = &TMH_private_get_accounts_ID
+ },
+ /* DELETE /accounts/$H_WIRE: */
+ {
+ .url_prefix = "/accounts",
.method = MHD_HTTP_METHOD_DELETE,
.handler = &TMH_private_delete_account_ID,
.have_id_segment = true
@@ -1779,6 +1842,31 @@ url_handler (void *cls,
/**
+ * Callback invoked with information about a bank account.
+ *
+ * @param cls closure with a `struct TMH_MerchantInstance *`
+ * @param ad details about the account
+ */
+static void
+add_account_cb (void *cls,
+ const struct TALER_MERCHANTDB_AccountDetails *acc)
+{
+ struct TMH_MerchantInstance *mi = cls;
+ struct TMH_WireMethod *wm;
+
+ wm = GNUNET_new (struct TMH_WireMethod);
+ wm->h_wire = acc->h_wire;
+ wm->payto_uri = GNUNET_strdup (acc->payto_uri);
+ wm->wire_salt = acc->salt;
+ wm->wire_method = TALER_payto_get_method (acc->payto_uri);
+ wm->active = acc->active;
+ GNUNET_CONTAINER_DLL_insert (mi->wm_head,
+ mi->wm_tail,
+ wm);
+}
+
+
+/**
* Function called during startup to add all known instances to our
* hash map in memory for faster lookups when we receive requests.
*
@@ -1787,20 +1875,17 @@ url_handler (void *cls,
* @param merchant_priv private key of the instance, NULL if not available
* @param is detailed configuration settings for the instance
* @param ias authentication settings for the instance
- * @param accounts_length length of the @a accounts array
- * @param accounts list of accounts of the merchant
*/
static void
add_instance_cb (void *cls,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_MerchantPrivateKeyP *merchant_priv,
const struct TALER_MERCHANTDB_InstanceSettings *is,
- const struct TALER_MERCHANTDB_InstanceAuthSettings *ias,
- unsigned int accounts_length,
- const struct TALER_MERCHANTDB_AccountDetails accounts[])
+ const struct TALER_MERCHANTDB_InstanceAuthSettings *ias)
{
struct TMH_MerchantInstance *mi;
-
+ enum GNUNET_DB_QueryStatus qs;
+
(void) cls;
mi = TMH_lookup_instance (is->id);
if (NULL != mi)
@@ -1829,20 +1914,15 @@ add_instance_cb (void *cls,
else
mi->deleted = true;
mi->merchant_pub = *merchant_pub;
- for (unsigned int i = 0; i<accounts_length; i++)
+ qs = TMH_db->select_accounts (TMH_db->cls,
+ mi->settings.id,
+ &add_account_cb,
+ mi);
+ if (0 > qs)
{
- const struct TALER_MERCHANTDB_AccountDetails *acc = &accounts[i];
- struct TMH_WireMethod *wm;
-
- wm = GNUNET_new (struct TMH_WireMethod);
- wm->h_wire = acc->h_wire;
- wm->payto_uri = GNUNET_strdup (acc->payto_uri);
- wm->wire_salt = acc->salt;
- wm->wire_method = TALER_payto_get_method (acc->payto_uri);
- wm->active = acc->active;
- GNUNET_CONTAINER_DLL_insert (mi->wm_head,
- mi->wm_tail,
- wm);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error loading accounts of `%s' from database\n",
+ mi->settings.id);
}
GNUNET_assert (GNUNET_OK ==
TMH_add_instance (mi));
diff --git a/src/backend/taler-merchant-httpd_post-using-templates.c b/src/backend/taler-merchant-httpd_post-using-templates.c
index 74eb0f44..67fc4b1e 100644
--- a/src/backend/taler-merchant-httpd_post-using-templates.c
+++ b/src/backend/taler-merchant-httpd_post-using-templates.c
@@ -73,7 +73,6 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
struct TMH_HandlerContext *hc)
{
struct TMH_MerchantInstance *mi = hc->instance;
- MHD_RESULT mret;
const char *template_id = hc->infix;
const char *summary = NULL;
const char *fulfillment_url = NULL;
@@ -252,6 +251,9 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
}
no_summary = (NULL == summary);
fake_body = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string ("otp_id",
+ uc->etp.otp_id)),
GNUNET_JSON_pack_object_steal (
"order",
GNUNET_JSON_PACK (
@@ -276,11 +278,8 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
}
uc->ihc.request_body = fake_body;
- mret = TMH_private_post_orders_with_pos_secrets (
+ return TMH_private_post_orders (
NULL, /* not even used */
connection,
- &uc->ihc,
- uc->etp.pos_key,
- uc->etp.pos_algorithm);
- return mret;
+ &uc->ihc);
}
diff --git a/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.c b/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.c
new file mode 100644
index 00000000..b147b84f
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.c
@@ -0,0 +1,78 @@
+/*
+ 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-delete-otp-devices-ID.c
+ * @brief implement DELETE /otp-devices/$ID
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-delete-otp-devices-ID.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * Handle a DELETE "/otp-devices/$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_otp_devices_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ enum GNUNET_DB_QueryStatus qs;
+
+ (void) rh;
+ GNUNET_assert (NULL != mi);
+ GNUNET_assert (NULL != hc->infix);
+ qs = TMH_db->delete_otp (TMH_db->cls,
+ mi->settings.id,
+ hc->infix);
+ 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,
+ "delete_otp");
+ 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,
+ "delete_otp (soft)");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN,
+ hc->infix);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return TALER_MHD_reply_static (connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
+ }
+ GNUNET_assert (0);
+ return MHD_NO;
+}
+
+
+/* end of taler-merchant-httpd_private-delete-otp-devices-ID.c */
diff --git a/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.h b/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.h
new file mode 100644
index 00000000..cd129d0d
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.h
@@ -0,0 +1,41 @@
+/*
+ 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-delete-otp-devices-ID.h
+ * @brief implement DELETE /otp-devices/$ID/
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_OTP_DEVICES_ID_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_OTP_DEVICES_ID_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a DELETE "/otp-devices/$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_otp_devices_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+/* end of taler-merchant-httpd_private-delete-otp-devices-ID.h */
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-get-accounts-ID.c b/src/backend/taler-merchant-httpd_private-get-accounts-ID.c
new file mode 100644
index 00000000..703beeca
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-accounts-ID.c
@@ -0,0 +1,103 @@
+/*
+ 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-accounts-ID.c
+ * @brief implement GET /accounts/$ID
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-get-accounts-ID.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * Handle a GET "/accounts/$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_accounts_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ const char *h_wire_s = hc->infix;
+ struct TALER_MerchantWireHashP h_wire;
+ struct TALER_MERCHANTDB_AccountDetails tp = { 0 };
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_assert (NULL != mi);
+ GNUNET_assert (NULL != h_wire_s);
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (h_wire_s,
+ strlen (h_wire_s),
+ &h_wire,
+ sizeof (h_wire)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_MERCHANT_GENERIC_H_WIRE_MALFORMED,
+ h_wire_s);
+ }
+ qs = TMH_db->select_account (TMH_db->cls,
+ mi->settings.id,
+ &h_wire,
+ &tp);
+ 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_account");
+ }
+ if (0 == qs)
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_ACCOUNT_UNKNOWN,
+ hc->infix);
+ }
+ {
+ MHD_RESULT ret;
+
+ ret = TALER_MHD_REPLY_JSON_PACK (
+ connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_string ("payto_uri",
+ tp.payto_uri),
+ GNUNET_JSON_pack_data_auto ("h_wire",
+ &tp.h_wire),
+ GNUNET_JSON_pack_data_auto ("salt",
+ &tp.salt),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string ("credit_facade_url",
+ tp.credit_facade_url)));
+ /* We do not return the credentials, as they may
+ be sensitive */
+ json_decref (tp.credit_facade_credentials);
+ GNUNET_free (tp.payto_uri);
+ GNUNET_free (tp.credit_facade_url);
+ return ret;
+ }
+}
+
+
+/* end of taler-merchant-httpd_private-get-accounts-ID.c */
diff --git a/src/backend/taler-merchant-httpd_private-get-accounts-ID.h b/src/backend/taler-merchant-httpd_private-get-accounts-ID.h
new file mode 100644
index 00000000..da5cb729
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-accounts-ID.h
@@ -0,0 +1,41 @@
+/*
+ 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-get-accounts-ID.h
+ * @brief implement GET /accounts/$ID/
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_ACCOUNTS_ID_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_GET_ACCOUNTS_ID_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a GET "/accounts/$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_accounts_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+/* end of taler-merchant-httpd_private-get-accounts-ID.h */
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-get-accounts.c b/src/backend/taler-merchant-httpd_private-get-accounts.c
new file mode 100644
index 00000000..92ebb368
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-accounts.c
@@ -0,0 +1,78 @@
+/*
+ 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-get-accounts.c
+ * @brief implement GET /accounts
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-get-accounts.h"
+
+
+/**
+ * Add account details to our JSON array.
+ *
+ * @param cls a `json_t *` JSON array to build
+ * @param ad details about the account
+ */
+static void
+add_account (void *cls,
+ const struct TALER_MERCHANTDB_AccountDetails *ad)
+{
+ json_t *pa = cls;
+
+ GNUNET_assert (0 ==
+ json_array_append_new (
+ pa,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("payto_uri",
+ ad->payto_uri),
+ GNUNET_JSON_pack_data_auto ("h_wire",
+ &ad->h_wire))));
+}
+
+
+MHD_RESULT
+TMH_private_get_accounts (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ json_t *pa;
+ enum GNUNET_DB_QueryStatus qs;
+
+ pa = json_array ();
+ GNUNET_assert (NULL != pa);
+ qs = TMH_db->select_accounts (TMH_db->cls,
+ hc->instance->settings.id,
+ &add_account,
+ pa);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ json_decref (pa);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
+ }
+ return TALER_MHD_REPLY_JSON_PACK (connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_array_steal ("accounts",
+ pa));
+}
+
+
+/* end of taler-merchant-httpd_private-get-accounts.c */
diff --git a/src/backend/taler-merchant-httpd_private-get-accounts.h b/src/backend/taler-merchant-httpd_private-get-accounts.h
new file mode 100644
index 00000000..0e9897cf
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-accounts.h
@@ -0,0 +1,41 @@
+/*
+ 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-get-accounts.h
+ * @brief implement GET /accounts
+ * @author Priscilla HUANG
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_ACCOUNTS_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_GET_ACCOUNTS_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a GET "/accounts" 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_accounts (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+/* end of taler-merchant-httpd_private-get-accounts.h */
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-get-otp-devices-ID.c b/src/backend/taler-merchant-httpd_private-get-otp-devices-ID.c
new file mode 100644
index 00000000..747e30cd
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-otp-devices-ID.c
@@ -0,0 +1,83 @@
+/*
+ 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-get-otp-devices-ID.c
+ * @brief implement GET /otp-devices/$ID
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-get-otp-devices-ID.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * Handle a GET "/otp-devices/$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_otp_devices_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ struct TALER_MERCHANTDB_OtpDeviceDetails tp = { 0 };
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_assert (NULL != mi);
+ qs = TMH_db->select_otp (TMH_db->cls,
+ mi->settings.id,
+ hc->infix,
+ &tp);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "select_otp");
+ }
+ if (0 == qs)
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN,
+ hc->infix);
+ }
+ {
+ MHD_RESULT ret;
+
+ /* Note: we deliberately (by design) do not return the otp_key */
+ ret = TALER_MHD_REPLY_JSON_PACK (
+ connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_string ("device_description",
+ tp.otp_description),
+ GNUNET_JSON_pack_uint64 ("otp_algorithm",
+ tp.otp_algorithm),
+ GNUNET_JSON_pack_uint64 ("otp_ctr",
+ tp.otp_ctr));
+ GNUNET_free (tp.otp_description);
+ GNUNET_free (tp.otp_key);
+ return ret;
+ }
+}
+
+
+/* end of taler-merchant-httpd_private-get-otp-devices-ID.c */
diff --git a/src/backend/taler-merchant-httpd_private-get-otp-devices-ID.h b/src/backend/taler-merchant-httpd_private-get-otp-devices-ID.h
new file mode 100644
index 00000000..78834f67
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-otp-devices-ID.h
@@ -0,0 +1,41 @@
+/*
+ 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-get-otp-devices-ID.h
+ * @brief implement GET /otp-devices/$ID/
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_OTP_DEVICES_ID_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_GET_OTP_DEVICES_ID_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a GET "/otp-devices/$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_otp_devices_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+/* end of taler-merchant-httpd_private-get-otp-devices-ID.h */
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-get-otp-devices.c b/src/backend/taler-merchant-httpd_private-get-otp-devices.c
new file mode 100644
index 00000000..df86842b
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-otp-devices.c
@@ -0,0 +1,80 @@
+/*
+ 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-get-otp-devices.c
+ * @brief implement GET /otp-devices
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-get-otp-devices.h"
+
+
+/**
+ * Add OTP device details to our JSON array.
+ *
+ * @param cls a `json_t *` JSON array to build
+ * @param template_id ID of the template
+ * @param template_description human-readable description for the template
+ */
+static void
+add_otp (void *cls,
+ const char *otp_id,
+ const char *otp_description)
+{
+ json_t *pa = cls;
+
+ GNUNET_assert (0 ==
+ json_array_append_new (
+ pa,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("otp_device_id",
+ otp_id),
+ GNUNET_JSON_pack_string ("device_description",
+ otp_description))));
+}
+
+
+MHD_RESULT
+TMH_private_get_otp_devices (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ json_t *pa;
+ enum GNUNET_DB_QueryStatus qs;
+
+ pa = json_array ();
+ GNUNET_assert (NULL != pa);
+ qs = TMH_db->lookup_otp_devices (TMH_db->cls,
+ hc->instance->settings.id,
+ &add_otp,
+ pa);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ json_decref (pa);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
+ }
+ return TALER_MHD_REPLY_JSON_PACK (connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_array_steal ("otp_devices",
+ pa));
+}
+
+
+/* end of taler-merchant-httpd_private-get-otp-devices.c */
diff --git a/src/backend/taler-merchant-httpd_private-get-otp-devices.h b/src/backend/taler-merchant-httpd_private-get-otp-devices.h
new file mode 100644
index 00000000..a97ca179
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-otp-devices.h
@@ -0,0 +1,41 @@
+/*
+ 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-get-otp-devices.h
+ * @brief implement GET /otp-devices
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_OTP_DEVICES_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_GET_OTP_DEVICES_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a GET "/otp-devices" 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_otp_devices (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+/* end of taler-merchant-httpd_private-get-otp-devices.h */
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-get-templates-ID.c b/src/backend/taler-merchant-httpd_private-get-templates-ID.c
index bdb1de9d..e9dfc00f 100644
--- a/src/backend/taler-merchant-httpd_private-get-templates-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-templates-ID.c
@@ -68,16 +68,13 @@ TMH_private_get_templates_ID (const struct TMH_RequestHandler *rh,
MHD_HTTP_OK,
GNUNET_JSON_pack_string ("template_description",
tp.template_description),
- GNUNET_JSON_pack_uint64 ("pos_algorithm",
- tp.pos_algorithm),
GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_string ("pos_key",
- tp.pos_key)),
+ GNUNET_JSON_pack_string ("otp_id",
+ tp.otp_id)),
GNUNET_JSON_pack_object_steal ("template_contract",
tp.template_contract));
GNUNET_free (tp.template_description);
- GNUNET_free (tp.pos_key);
-
+ GNUNET_free (tp.otp_id);
return ret;
}
}
diff --git a/src/backend/taler-merchant-httpd_private-patch-accounts-ID.c b/src/backend/taler-merchant-httpd_private-patch-accounts-ID.c
new file mode 100644
index 00000000..04fe4ce5
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-patch-accounts-ID.c
@@ -0,0 +1,132 @@
+/*
+ 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-accounts-ID.c
+ * @brief implementing PATCH /accounts/$ID request handling
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-patch-accounts-ID.h"
+#include "taler-merchant-httpd_helper.h"
+#include <taler/taler_json_lib.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_accounts_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ const char *h_wire_s = hc->infix;
+ enum GNUNET_DB_QueryStatus qs;
+ const json_t *cfc;
+ const char *cfu;
+ struct TALER_MerchantWireHashP h_wire;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("credit_facade_url",
+ (const char **) &cfu),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_object_const ("credit_facade_credentials",
+ &cfc),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+
+ GNUNET_assert (NULL != mi);
+ GNUNET_assert (NULL != h_wire_s);
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (h_wire_s,
+ strlen (h_wire_s),
+ &h_wire,
+ sizeof (h_wire)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_MERCHANT_GENERIC_H_WIRE_MALFORMED,
+ h_wire_s);
+ }
+ {
+ 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_account (TMH_db->cls,
+ mi->settings.id,
+ &h_wire,
+ cfu,
+ cfc);
+ {
+ 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,
+ "update_account");
+ 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:
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_ACCOUNT_UNKNOWN,
+ h_wire_s);
+ 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-accounts-ID.c */
diff --git a/src/backend/taler-merchant-httpd_private-patch-accounts-ID.h b/src/backend/taler-merchant-httpd_private-patch-accounts-ID.h
new file mode 100644
index 00000000..752fb958
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-patch-accounts-ID.h
@@ -0,0 +1,43 @@
+/*
+ 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-accounts-ID.h
+ * @brief implementing PATCH /accounts request handling
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_ACCOUNTS_ID_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_ACCOUNTS_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_accounts_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+#endif
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 bc6e3aae..027d5869 100644
--- a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
+++ b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
@@ -63,14 +63,11 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
struct TMH_HandlerContext *hc)
{
struct TALER_MERCHANTDB_InstanceSettings is;
- const json_t *accounts;
const char *name;
const char *uts = "business";
struct TMH_WireMethod *wm_head = NULL;
struct TMH_WireMethod *wm_tail = NULL;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_array_const ("accounts",
- &accounts),
GNUNET_JSON_spec_string ("name",
&name),
GNUNET_JSON_spec_mark_optional (
@@ -102,7 +99,6 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
GNUNET_JSON_spec_end ()
};
enum GNUNET_DB_QueryStatus qs;
- bool committed = false;
GNUNET_assert (NULL != mi);
memset (&is,
@@ -162,14 +158,6 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
"jurisdiction");
}
- if (! TMH_accounts_array_valid (accounts))
- {
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
- NULL);
- }
for (unsigned int retry = 0; retry<MAX_RETRIES; retry++)
{
/* Cleanup after earlier loops */
@@ -236,258 +224,13 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
goto giveup;
}
}
-
- /* Check for changes in accounts */
- {
- unsigned int len = json_array_size (accounts);
- struct TMH_WireMethod *matches[GNUNET_NZL (len)];
- bool updated[GNUNET_NZL (len)];
-
- memset (matches,
- 0,
- sizeof (matches));
- memset (updated,
- 0,
- sizeof (updated));
- for (struct TMH_WireMethod *wm = mi->wm_head;
- NULL != wm;
- wm = wm->next)
- {
- bool matched = false;
- for (unsigned int i = 0; i<len; i++)
- {
- json_t *account = json_array_get (accounts,
- i);
- enum GNUNET_GenericReturnValue ret;
-
- ret = TMH_cmp_wire_account (account,
- wm);
- switch (ret)
- {
- case GNUNET_SYSERR:
- continue;
- case GNUNET_NO:
- matched = true;
- /* our own existing payto URIs should be unique, that is no
- duplicates in the list, so we cannot match twice */
- GNUNET_assert (NULL == matches[i]);
- matches[i] = wm;
- updated[i] = true;
- break;
- case GNUNET_YES:
- matched = true;
- /* our own existing payto URIs should be unique, that is no
- duplicates in the list, so we cannot match twice */
- GNUNET_assert (NULL == matches[i]);
- matches[i] = wm;
- break;
- }
- }
-
- /* delete unmatched (= removed) accounts */
- if ( (! matched) &&
- (wm->active) )
- {
- /* Account was REMOVED */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Existing account `%s' not found, deactivating it.\n",
- wm->payto_uri);
- wm->deleting = true;
- qs = TMH_db->inactivate_account (TMH_db->cls,
- mi->settings.id,
- &wm->h_wire);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- {
- TMH_db->rollback (TMH_db->cls);
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- goto retry;
- else
- goto giveup;
- }
- }
- } /* for (wm) */
-
- /* handle updates */
- for (unsigned int i = 0; i<len; i++)
- {
- struct TMH_WireMethod *wm = matches[i];
-
- if (! updated[i])
- continue;
- GNUNET_assert (NULL != wm);
- {
- struct TALER_MERCHANTDB_AccountDetails ad = {
- .payto_uri = wm->payto_uri,
- .h_wire = wm->h_wire,
- .salt = wm->wire_salt,
- .credit_facade_url = wm->credit_facade_url,
- .credit_facade_credentials = wm->credit_facade_credentials,
- .active = true
- };
-
- qs = TMH_db->update_account (TMH_db->cls,
- mi->settings.id,
- &ad);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- {
- TMH_db->rollback (TMH_db->cls);
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- goto retry;
- else
- goto giveup;
- }
- } /* ad scope */
- } /* for possible updates */
-
- /* Find _new_ accounts or accounts to only enable */
- for (unsigned int i = 0; i<len; i++)
- {
- json_t *account = json_array_get (accounts,
- i);
- struct TMH_WireMethod *wm = matches[i];
-
- if (NULL != wm)
- {
- if (updated[i])
- continue; /* handled above */
- if (! wm->active)
- {
- qs = TMH_db->activate_account (TMH_db->cls,
- mi->settings.id,
- &wm->h_wire);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- {
- TMH_db->rollback (TMH_db->cls);
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- goto retry;
- else
- goto giveup;
- }
- }
- wm->enabling = true;
- continue;
- }
-
- {
- const char *credit_facade_url = NULL;
- const 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_object_const ("credit_facade_credentials",
- &credit_facade_credentials),
- NULL),
- GNUNET_JSON_spec_end ()
- };
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (connection,
- account,
- ispec);
- if (GNUNET_OK != res)
- return (GNUNET_NO == res)
- ? MHD_YES
- : MHD_NO;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Adding NEW account `%s'\n",
- uri);
- wm = TMH_setup_wire_account (uri,
- credit_facade_url,
- credit_facade_credentials);
- GNUNET_assert (NULL != wm); /* checked payto_uri validity earlier */
- GNUNET_CONTAINER_DLL_insert (wm_head,
- wm_tail,
- wm);
- } /* ispec scope */
-
- {
- struct TALER_MERCHANTDB_AccountDetails ad = {
- .payto_uri = wm->payto_uri,
- .h_wire = wm->h_wire,
- .salt = wm->wire_salt,
- .credit_facade_url = wm->credit_facade_url,
- .credit_facade_credentials = wm->credit_facade_credentials,
- .active = true
- };
-
- qs = TMH_db->insert_account (TMH_db->cls,
- mi->settings.id,
- &ad);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- {
- TMH_db->rollback (TMH_db->cls);
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- goto retry;
- else
- goto giveup;
- }
- } /* ad variable scope */
- } /* for (i) to find new accounts */
- } /* scope for checking for account changes */
-
- {
- 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);
- }
qs = TMH_db->commit (TMH_db->cls);
retry:
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
continue;
- if (qs >= 0)
- committed = true;
break;
} /* for(... MAX_RETRIES) */
giveup:
- /* Deactivate existing wire methods that were removed above */
- for (struct TMH_WireMethod *wm = mi->wm_head;
- NULL != wm;
- wm = wm->next)
- {
- /* We did not flip the 'active' bits earlier because the
- DB transaction could still fail. Now it is time to update our
- runtime state. */
- GNUNET_assert (! (wm->deleting & wm->enabling));
- if (committed)
- {
- if (wm->deleting)
- wm->active = false;
- if (wm->enabling)
- wm->active = true;
- }
- wm->deleting = false;
- wm->enabling = false;
- }
- if (! committed)
- {
- struct TMH_WireMethod *wm;
-
- while (NULL != (wm = wm_head))
- {
- GNUNET_CONTAINER_DLL_remove (wm_head,
- wm_tail,
- wm);
- free_wm (wm);
- }
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_COMMIT_FAILED,
- NULL);
- }
-
/* Update our 'settings' */
GNUNET_free (mi->settings.name);
GNUNET_free (mi->settings.email);
@@ -508,23 +251,6 @@ giveup:
if (NULL != is.logo)
mi->settings.logo = GNUNET_strdup (is.logo);
- /* Add 'new' wire methods to our list */
- {
- struct TMH_WireMethod *wm;
-
- /* Note: this _could_ be done more efficiently if
- someone wrote a GNUNET_CONTAINER_DLL_merge()... */
- while (NULL != (wm = wm_head))
- {
- GNUNET_CONTAINER_DLL_remove (wm_head,
- wm_tail,
- wm);
- GNUNET_CONTAINER_DLL_insert (mi->wm_head,
- mi->wm_tail,
- wm);
- }
- }
-
GNUNET_JSON_parse_free (spec);
TMH_reload_instances (mi->settings.id);
return TALER_MHD_reply_static (connection,
diff --git a/src/backend/taler-merchant-httpd_private-patch-otp-devices-ID.c b/src/backend/taler-merchant-httpd_private-patch-otp-devices-ID.c
new file mode 100644
index 00000000..f0fc8b0b
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-patch-otp-devices-ID.c
@@ -0,0 +1,122 @@
+/*
+ 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-patch-otp-devices-ID.c
+ * @brief implementing PATCH /otp-devices/$ID request handling
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-patch-otp-devices-ID.h"
+#include "taler-merchant-httpd_helper.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * PATCH OTP device of an existing 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_patch_otp_devices_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ const char *device_id = hc->infix;
+ struct TALER_MERCHANTDB_OtpDeviceDetails tp = {0};
+ enum GNUNET_DB_QueryStatus qs;
+ uint32_t otp_algorithm;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("otp_description",
+ (const char **) &tp.otp_description),
+ GNUNET_JSON_spec_uint32 ("otp_algorithm",
+ &otp_algorithm),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint64 ("otp_ctr",
+ &tp.otp_ctr),
+ NULL),
+ GNUNET_JSON_spec_string ("otp_key",
+ (const char **) &tp.otp_key),
+ GNUNET_JSON_spec_end ()
+ };
+
+ GNUNET_assert (NULL != mi);
+ GNUNET_assert (NULL != device_id);
+ {
+ 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;
+ }
+
+ tp.otp_algorithm = (enum TALER_MerchantConfirmationAlgorithm) otp_algorithm;
+
+ qs = TMH_db->update_otp (TMH_db->cls,
+ mi->settings.id,
+ device_id,
+ &tp);
+ {
+ 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,
+ "update_pos");
+ 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 = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN,
+ device_id);
+ 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-otp-devices-ID.c */
diff --git a/src/backend/taler-merchant-httpd_private-patch-otp-devices-ID.h b/src/backend/taler-merchant-httpd_private-patch-otp-devices-ID.h
new file mode 100644
index 00000000..eef1dd0a
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-patch-otp-devices-ID.h
@@ -0,0 +1,44 @@
+/*
+ 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-patch-otp-devices-ID.h
+ * @brief implementing PATCH /otp-devices/$ID request handling
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_OTP_DEVICES_ID_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_OTP_DEVICES_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_otp_devices_ID (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-patch-templates-ID.c b/src/backend/taler-merchant-httpd_private-patch-templates-ID.c
index b5938368..68e0a478 100644
--- a/src/backend/taler-merchant-httpd_private-patch-templates-ID.c
+++ b/src/backend/taler-merchant-httpd_private-patch-templates-ID.c
@@ -29,12 +29,6 @@
/**
- * 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
@@ -109,17 +103,12 @@ TMH_private_patch_templates_ID (const struct TMH_RequestHandler *rh,
const char *template_id = hc->infix;
struct TALER_MERCHANTDB_TemplateDetails tp = {0};
enum GNUNET_DB_QueryStatus qs;
- uint32_t pos_algorithm;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("template_description",
(const char **) &tp.template_description),
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_uint32 ("pos_algorithm",
- &pos_algorithm),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("pos_key",
- (const char **) &tp.pos_key),
+ GNUNET_JSON_spec_string ("otp_id",
+ (const char **) &tp.otp_id),
NULL),
GNUNET_JSON_spec_json ("template_contract",
&tp.template_contract),
@@ -140,7 +129,6 @@ TMH_private_patch_templates_ID (const struct TMH_RequestHandler *rh,
: MHD_NO;
}
- tp.pos_algorithm = (enum TALER_MerchantConfirmationAlgorithm) pos_algorithm;
if (! TMH_template_contract_valid (tp.template_contract))
{
GNUNET_break_op (0);
diff --git a/src/backend/taler-merchant-httpd_private-post-account.c b/src/backend/taler-merchant-httpd_private-post-account.c
index f9be253c..73abfe48 100644
--- a/src/backend/taler-merchant-httpd_private-post-account.c
+++ b/src/backend/taler-merchant-httpd_private-post-account.c
@@ -19,7 +19,7 @@
/**
* @file taler-merchant-httpd_private-post-account.c
- * @brief implementing POST /private/account request handling
+ * @brief implementing POST /private/accounts request handling
* @author Christian Grothoff
*/
#include "platform.h"
@@ -173,11 +173,12 @@ TMH_private_post_account (const struct TMH_RequestHandler *rh,
/* 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);
+ return TALER_MHD_REPLY_JSON_PACK (connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_data_auto ("salt",
+ &wm->wire_salt),
+ GNUNET_JSON_pack_data_auto ("h_wire",
+ &wm->h_wire));
}
diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c
index 6c9727e9..398a846d 100644
--- a/src/backend/taler-merchant-httpd_private-post-instances.c
+++ b/src/backend/taler-merchant-httpd_private-post-instances.c
@@ -37,56 +37,6 @@
/**
- * Check if the array of @a payto_uris contains exactly the same
- * URIs as those already in @a mi (possibly in a different order).
- *
- * @param mi a merchant instance with accounts
- * @param accounts a JSON array with accounts (presumably)
- * @return true if they are 'equal', false if not or of payto_uris is not an array
- */
-static bool
-accounts_equal (const struct TMH_MerchantInstance *mi,
- const json_t *accounts)
-{
- if (! json_is_array (accounts))
- return false;
- {
- unsigned int len = json_array_size (accounts);
- enum GNUNET_GenericReturnValue matches[GNUNET_NZL (len)];
-
- for (unsigned int i = 0; i<len; i++)
- matches[i] = GNUNET_SYSERR;
- for (struct TMH_WireMethod *wm = mi->wm_head;
- NULL != wm;
- wm = wm->next)
- {
- for (unsigned int i = 0; i<len; i++)
- {
- json_t *account = json_array_get (accounts,
- i);
- enum GNUNET_GenericReturnValue ret;
-
- ret = TMH_cmp_wire_account (account,
- wm);
- if (GNUNET_SYSERR == ret)
- continue;
- if (GNUNET_SYSERR != matches[i])
- {
- GNUNET_break (0);
- return false; /* duplicate entry!? */
- }
- matches[i] = ret;
- }
- }
- for (unsigned int i = 0; i<len; i++)
- if (GNUNET_YES != matches[i])
- return false;
- }
- return true;
-}
-
-
-/**
* Generate an instance, given its configuration.
*
* @param rh context of the handler
@@ -101,15 +51,12 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
{
struct TALER_MERCHANTDB_InstanceSettings is;
struct TALER_MERCHANTDB_InstanceAuthSettings ias;
- const json_t *accounts;
const char *auth_token = NULL;
const char *uts = "business";
struct TMH_WireMethod *wm_head = NULL;
struct TMH_WireMethod *wm_tail = NULL;
const json_t *jauth;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_array_const ("accounts",
- &accounts),
GNUNET_JSON_spec_string ("id",
(const char **) &is.id),
GNUNET_JSON_spec_string ("name",
@@ -179,16 +126,6 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
}
- /* check accounts for well-formedness */
- if (! TMH_accounts_array_valid (accounts))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
- NULL);
- }
-
/* check 'id' well-formed */
{
static bool once;
@@ -292,9 +229,7 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
is.default_wire_transfer_delay)) &&
(GNUNET_TIME_relative_cmp (mi->settings.default_pay_delay,
==,
- is.default_pay_delay)) &&
- (accounts_equal (mi,
- accounts)) )
+ is.default_pay_delay)) )
{
return TALER_MHD_reply_static (connection,
MHD_HTTP_NO_CONTENT,
@@ -312,50 +247,6 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
}
}
- /* convert provided payto URIs into internal data structure with salts */
- {
- unsigned int len = json_array_size (accounts);
-
- for (unsigned int i = 0; i<len; i++)
- {
- json_t *account = json_array_get (accounts,
- i);
- const char *credit_facade_url = NULL;
- const json_t *credit_facade_credentials = NULL;
- const char *uri;
- struct TMH_WireMethod *wm;
- 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_object_const ("credit_facade_credentials",
- &credit_facade_credentials),
- NULL),
- GNUNET_JSON_spec_end ()
- };
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (connection,
- account,
- ispec);
- if (GNUNET_OK != res)
- return (GNUNET_NO == res)
- ? MHD_YES
- : MHD_NO;
- wm = TMH_setup_wire_account (uri,
- credit_facade_url,
- credit_facade_credentials);
- GNUNET_assert (NULL != wm);
- GNUNET_CONTAINER_DLL_insert (wm_head,
- wm_tail,
- wm);
- }
- }
-
/* handle authentication token setup */
if (NULL == auth_token)
{
@@ -431,44 +322,6 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
TMH_instance_decref (mi);
return ret;
}
- for (struct TMH_WireMethod *wm = wm_head;
- NULL != wm;
- wm = wm->next)
- {
- 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
- };
-
- qs = TMH_db->insert_account (TMH_db->cls,
- mi->settings.id,
- &ad);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- break;
- }
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- TMH_db->rollback (TMH_db->cls);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- break;
- goto retry;
- }
- {
- 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);
- }
qs = TMH_db->commit (TMH_db->cls);
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c
index 1c888508..34fac6a0 100644
--- a/src/backend/taler-merchant-httpd_private-post-orders.c
+++ b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -1760,11 +1760,17 @@ merge_inventory (struct OrderContext *oc)
}
+/**
+ * Parse the basics of the client request.
+ *
+ * @param[in,out] oc order context to process
+ */
static void
parse_order_request (struct OrderContext *oc)
{
const json_t *ip = NULL;
const json_t *uuid = NULL;
+ const char *otp_id = NULL;
bool create_token = true; /* default */
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("order",
@@ -1789,6 +1795,10 @@ parse_order_request (struct OrderContext *oc)
GNUNET_JSON_spec_bool ("create_token",
&create_token),
NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("otp_id",
+ &otp_id),
+ NULL),
GNUNET_JSON_spec_end ()
};
enum GNUNET_GenericReturnValue ret;
@@ -1808,6 +1818,43 @@ parse_order_request (struct OrderContext *oc)
GNUNET_TIME_relative2s (oc->refund_delay,
false));
TMH_db->expire_locks (TMH_db->cls);
+ if (NULL != otp_id)
+ {
+ struct TALER_MERCHANTDB_OtpDeviceDetails td;
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = TMH_db->select_otp (TMH_db->cls,
+ oc->hc->instance->settings.id,
+ otp_id,
+ &td);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ reply_with_error (oc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "select_otp");
+ return;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ reply_with_error (oc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_SOFT_FAILURE,
+ "select_otp");
+ return;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ reply_with_error (oc,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN,
+ otp_id);
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
+ oc->pos_key = td.otp_key;
+ oc->pos_algorithm = td.otp_algorithm;
+ }
if (create_token)
{
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
@@ -1912,12 +1959,10 @@ parse_order_request (struct OrderContext *oc)
MHD_RESULT
-TMH_private_post_orders_with_pos_secrets (
+TMH_private_post_orders (
const struct TMH_RequestHandler *rh,
struct MHD_Connection *connection,
- struct TMH_HandlerContext *hc,
- const char *pos_key,
- enum TALER_MerchantConfirmationAlgorithm pos_algorithm)
+ struct TMH_HandlerContext *hc)
{
struct OrderContext *oc = hc->ctx;
@@ -1928,8 +1973,6 @@ TMH_private_post_orders_with_pos_secrets (
hc->cc = &clean_order;
oc->connection = connection;
oc->hc = hc;
- oc->pos_key = pos_key;
- oc->pos_algorithm = pos_algorithm;
}
while (1)
{
@@ -1976,18 +2019,4 @@ TMH_private_post_orders_with_pos_secrets (
}
-MHD_RESULT
-TMH_private_post_orders (
- const struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- struct TMH_HandlerContext *hc)
-{
- return TMH_private_post_orders_with_pos_secrets (rh,
- connection,
- hc,
- NULL,
- TALER_MCA_NONE);
-}
-
-
/* end of taler-merchant-httpd_private-post-orders.c */
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.h b/src/backend/taler-merchant-httpd_private-post-orders.h
index cbbb59c0..f1127bec 100644
--- a/src/backend/taler-merchant-httpd_private-post-orders.h
+++ b/src/backend/taler-merchant-httpd_private-post-orders.h
@@ -46,25 +46,5 @@ TMH_private_post_orders (const struct TMH_RequestHandler *rh,
struct MHD_Connection *connection,
struct TMH_HandlerContext *hc);
-/**
- * Generate an order. We add the fields 'exchanges', 'merchant_pub', and
- * 'H_wire' to the order gotten from the frontend, as well as possibly other
- * fields if the frontend did not provide them. Returns the order_id.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] hc context with further information about the request
- * @param pos_key key identifying the POS, can be NULL
- * @param pos_algorithm algorithm for computing the POS confirmation
- * @return MHD result code
- */
-MHD_RESULT
-TMH_private_post_orders_with_pos_secrets (
- const struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- struct TMH_HandlerContext *hc,
- const char *pos_key,
- enum TALER_MerchantConfirmationAlgorithm pos_algorithm);
-
#endif
diff --git a/src/backend/taler-merchant-httpd_private-post-otp-devices.c b/src/backend/taler-merchant-httpd_private-post-otp-devices.c
new file mode 100644
index 00000000..5521ce97
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-post-otp-devices.c
@@ -0,0 +1,201 @@
+/*
+ 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-otp-devices.c
+ * @brief implementing POST /otp-devices request handling
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-post-otp-devices.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 otp-devices are identical.
+ *
+ * @param t1 device to compare
+ * @param t2 other device to compare
+ * @return true if they are 'equal', false if not or of payto_uris is not an array
+ */
+static bool
+otp_devices_equal (const struct TALER_MERCHANTDB_OtpDeviceDetails *t1,
+ const struct TALER_MERCHANTDB_OtpDeviceDetails *t2)
+{
+ return ( (0 == strcmp (t1->otp_description,
+ t2->otp_description)) &&
+ (0 == strcmp (t1->otp_key,
+ t2->otp_key) ) &&
+ (t1->otp_ctr == t2->otp_ctr) &&
+ (t1->otp_algorithm == t2->otp_algorithm) );
+}
+
+
+MHD_RESULT
+TMH_private_post_otp_devices (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ struct TALER_MERCHANTDB_OtpDeviceDetails tp = { 0 };
+ const char *device_id;
+ enum GNUNET_DB_QueryStatus qs;
+ uint32_t otp_algorithm;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("otp_device_id",
+ &device_id),
+ GNUNET_JSON_spec_string ("otp_device_description",
+ (const char **) &tp.otp_description),
+ GNUNET_JSON_spec_uint32 ("otp_algorithm",
+ &otp_algorithm),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint64 ("otp_ctr",
+ &tp.otp_ctr),
+ NULL),
+ GNUNET_JSON_spec_string ("otp_key",
+ (const char **) &tp.otp_key),
+ 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;
+ }
+ }
+ tp.otp_algorithm = (enum TALER_MerchantConfirmationAlgorithm) otp_algorithm;
+
+ /* finally, interact with DB until no serialization error */
+ for (unsigned int i = 0; i<MAX_RETRIES; i++)
+ {
+ /* Test if a OTP device of this id is known */
+ struct TALER_MERCHANTDB_OtpDeviceDetails etp;
+
+ if (GNUNET_OK !=
+ TMH_db->start (TMH_db->cls,
+ "/post otp-devices"))
+ {
+ 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->select_otp (TMH_db->cls,
+ mi->settings.id,
+ device_id,
+ &etp);
+ 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 etp == tp? */
+ {
+ bool eq;
+
+ eq = otp_devices_equal (&tp,
+ &etp);
+ GNUNET_free (etp.otp_description);
+ GNUNET_free (etp.otp_key);
+ 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_OTP_DEVICES_CONFLICT_OTP_DEVICE_EXISTS,
+ device_id);
+ }
+ } /* end switch (qs) */
+
+ qs = TMH_db->insert_otp (TMH_db->cls,
+ mi->settings.id,
+ device_id,
+ &tp);
+ 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-otp-devices.c */
diff --git a/src/backend/taler-merchant-httpd_private-post-otp-devices.h b/src/backend/taler-merchant-httpd_private-post-otp-devices.h
new file mode 100644
index 00000000..96564d08
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-post-otp-devices.h
@@ -0,0 +1,44 @@
+/*
+ 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-otp-devices.h
+ * @brief implementing POST /otp-devices request handling
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_OTP_DEVICES_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_POST_OTP_DEVICES_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Generate an OTP device.
+ *
+ * @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_otp_devices (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 276e225f..4a5d8133 100644
--- a/src/backend/taler-merchant-httpd_private-post-templates.c
+++ b/src/backend/taler-merchant-httpd_private-post-templates.c
@@ -29,12 +29,6 @@
/**
- * How often do we retry the simple INSERT database transaction?
- */
-#define MAX_RETRIES 3
-
-
-/**
* Check if the two templates are identical.
*
* @param t1 template to compare
@@ -47,12 +41,12 @@ templates_equal (const struct TALER_MERCHANTDB_TemplateDetails *t1,
{
return ( (0 == strcmp (t1->template_description,
t2->template_description)) &&
- ( ( (NULL == t1->pos_key) &&
- (NULL == t2->pos_key) ) ||
- ( (NULL != t1->pos_key) &&
- (NULL != t2->pos_key) &&
- (0 == strcmp (t1->pos_key,
- t2->pos_key))) ) &&
+ ( ( (NULL == t1->otp_id) &&
+ (NULL == t2->otp_id) ) ||
+ ( (NULL != t1->otp_id) &&
+ (NULL != t2->otp_id) &&
+ (0 == strcmp (t1->otp_id,
+ t2->otp_id))) ) &&
(1 == json_equal (t1->template_contract,
t2->template_contract)) );
}
@@ -67,24 +61,20 @@ TMH_private_post_templates (const struct TMH_RequestHandler *rh,
struct TALER_MERCHANTDB_TemplateDetails tp = { 0 };
const char *template_id;
enum GNUNET_DB_QueryStatus qs;
- uint32_t pos_algorithm = 0;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("template_id",
&template_id),
GNUNET_JSON_spec_string ("template_description",
(const char **) &tp.template_description),
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_uint32 ("pos_algorithm",
- &pos_algorithm),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("pos_key",
- (const char **) &tp.pos_key),
+ GNUNET_JSON_spec_string ("otp_id",
+ (const char **) &tp.otp_id),
NULL),
GNUNET_JSON_spec_json ("template_contract",
&tp.template_contract),
GNUNET_JSON_spec_end ()
};
+ uint64_t otp_serial = 0;
GNUNET_assert (NULL != mi);
{
@@ -101,7 +91,6 @@ TMH_private_post_templates (const struct TMH_RequestHandler *rh,
: MHD_NO;
}
}
- tp.pos_algorithm = (enum TALER_MerchantConfirmationAlgorithm) pos_algorithm;
if (! TMH_template_contract_valid (tp.template_contract))
{
GNUNET_break_op (0);
@@ -115,23 +104,63 @@ TMH_private_post_templates (const struct TMH_RequestHandler *rh,
"template_contract");
}
- /* finally, interact with DB until no serialization error */
- for (unsigned int i = 0; i<MAX_RETRIES; i++)
+ if (NULL != tp.otp_id)
{
- /* Test if a template of this id is known */
- struct TALER_MERCHANTDB_TemplateDetails etp;
-
- if (GNUNET_OK !=
- TMH_db->start (TMH_db->cls,
- "/post templates"))
+ qs = TMH_db->select_otp_serial (TMH_db->cls,
+ mi->settings.id,
+ tp.otp_id,
+ &otp_serial);
+ switch (qs)
{
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
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,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "select_otp_serial");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN,
NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
}
+ }
+
+ qs = TMH_db->insert_template (TMH_db->cls,
+ mi->settings.id,
+ template_id,
+ otp_serial,
+ &tp);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_static (connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ break;
+ }
+
+ {
+ /* Test if a template of this id is known */
+ struct TALER_MERCHANTDB_TemplateDetails etp;
+
qs = TMH_db->lookup_template (TMH_db->cls,
mi->settings.id,
template_id,
@@ -139,79 +168,45 @@ TMH_private_post_templates (const struct TMH_RequestHandler *rh,
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_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;
+ GNUNET_break (0);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "logic error");
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* idempotency check: is etp == tp? */
- {
- bool eq;
-
- eq = templates_equal (&tp,
- &etp);
- TALER_MERCHANTDB_template_details_free (&etp);
- 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_TEMPLATES_CONFLICT_TEMPLATE_EXISTS,
- template_id);
- }
- } /* end switch (qs) */
-
- qs = TMH_db->insert_template (TMH_db->cls,
- mi->settings.id,
- template_id,
- &tp);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- TMH_db->rollback (TMH_db->cls);
break;
}
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ /* idempotency check: is etp == tp? */
{
- qs = TMH_db->commit (TMH_db->cls);
- if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
- break;
+ bool eq;
+
+ eq = templates_equal (&tp,
+ &etp);
+ TALER_MERCHANTDB_template_details_free (&etp);
+ 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_TEMPLATES_CONFLICT_TEMPLATE_EXISTS,
+ template_id);
}
-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);
}