summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-07-20 19:33:59 +0200
committerChristian Grothoff <christian@grothoff.org>2021-07-20 19:33:59 +0200
commit362bf0c5bd2270ed6a54dfbdfd83702dca892797 (patch)
tree62dc70b9111810c1375fedfb75efff882bb5058d /src
parent43dd7c8ae663fcb3db64fb7571c56144baa83a0e (diff)
downloadmerchant-362bf0c5bd2270ed6a54dfbdfd83702dca892797.tar.gz
merchant-362bf0c5bd2270ed6a54dfbdfd83702dca892797.tar.bz2
merchant-362bf0c5bd2270ed6a54dfbdfd83702dca892797.zip
-workshop refactoring
Diffstat (limited to 'src')
-rw-r--r--src/backend/Makefile.am2
-rw-r--r--src/backend/taler-merchant-httpd.c17
-rw-r--r--src/backend/taler-merchant-httpd.h6
-rw-r--r--src/backend/taler-merchant-httpd_helper.c106
-rw-r--r--src/backend/taler-merchant-httpd_helper.h50
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-instances-ID.c146
-rw-r--r--src/backend/taler-merchant-httpd_private-post-instances.c76
-rw-r--r--src/backenddb/merchant-0001.sql1
-rw-r--r--src/backenddb/merchant-0002.sql2
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c28
-rw-r--r--src/backenddb/test_merchantdb.c10
-rw-r--r--src/include/taler_merchantdb_plugin.h4
12 files changed, 269 insertions, 179 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index b25b8d3d..da825d3b 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -27,6 +27,8 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_get-orders-ID.h \
taler-merchant-httpd_get-tips-ID.c \
taler-merchant-httpd_get-tips-ID.h \
+ taler-merchant-httpd_helper.c \
+ taler-merchant-httpd_helper.h \
taler-merchant-httpd_private-get-tips.c \
taler-merchant-httpd_private-get-tips.h \
taler-merchant-httpd_private-get-tips-ID.c \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index bfc0337e..861b5f47 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -69,6 +69,10 @@
#include "taler-merchant-httpd_statics.h"
#include "taler-merchant-httpd_templating.h"
+/**
+ * Fixme: document.
+ */
+#define INSTANCE_STALENESS GNUNET_TIME_UNIT_MINUTES
/**
* Backlog for listen operation on unix-domain sockets.
@@ -908,6 +912,8 @@ struct TMH_MerchantInstance *
TMH_lookup_instance (const char *instance_id)
{
struct GNUNET_HashCode h_instance;
+ struct TMH_MerchantInstance *mi;
+ struct GNUNET_TIME_Relative age;
if (NULL == instance_id)
instance_id = "default";
@@ -920,8 +926,14 @@ TMH_lookup_instance (const char *instance_id)
instance_id);
/* We're fine if that returns NULL, the calling routine knows how
to handle that */
- return GNUNET_CONTAINER_multihashmap_get (TMH_by_id_map,
- &h_instance);
+ mi = GNUNET_CONTAINER_multihashmap_get (TMH_by_id_map,
+ &h_instance);
+ age = GNUNET_TIME_absolute_get_duration (mi->staleness);
+ if (age.rel_value_us > INSTANCE_STALENESS.rel_value_us)
+ {
+ // FIXME: referesh from DB
+ }
+ return mi;
}
@@ -2038,6 +2050,7 @@ add_instance_cb (void *cls,
else
mi->deleted = true;
mi->merchant_pub = *merchant_pub;
+ mi->staleness = GNUNET_TIME_absolute_get ();
for (unsigned int i = 0; i<accounts_length; i++)
{
const struct TALER_MERCHANTDB_AccountDetails *acc = &accounts[i];
diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h
index ab230783..29a67acc 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -138,6 +138,12 @@ struct TMH_MerchantInstance
struct TALER_MERCHANTDB_InstanceAuthSettings auth;
/**
+ * Timestamp when we last updated this instance's data
+ * with the information from the database.
+ */
+ struct GNUNET_TIME_Absolute staleness;
+
+ /**
* Reference counter on this structure. Only destroyed if the
* counter hits zero.
*/
diff --git a/src/backend/taler-merchant-httpd_helper.c b/src/backend/taler-merchant-httpd_helper.c
new file mode 100644
index 00000000..30ff4a90
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_helper.c
@@ -0,0 +1,106 @@
+/*
+ This file is part of TALER
+ (C) 2014--2020 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser 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_helper.c
+ * @brief shared logic for various handlers
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler-merchant-httpd_helper.h"
+
+/**
+ * check @a payto_uris for well-formedness
+ *
+ * @param payto_uris JSON array of payto URIs (presumably)
+ * @return true if they are all valid URIs (and this is an array of strings)
+ */
+bool
+TMH_payto_uri_array_valid (const json_t *payto_uris)
+{
+ bool payto_ok = true;
+
+ if (! json_is_array (payto_uris))
+ {
+ GNUNET_break_op (0);
+ payto_ok = false;
+ }
+ else
+ {
+ unsigned int len = json_array_size (payto_uris);
+
+ for (unsigned int i = 0; i<len; i++)
+ {
+ json_t *payto_uri = json_array_get (payto_uris,
+ i);
+ const char *uri;
+
+ if (! json_is_string (payto_uri))
+ payto_ok = false;
+ uri = json_string_value (payto_uri);
+ /* Test for the same payto:// URI being given twice */
+ for (unsigned int j = 0; j<i; j++)
+ {
+ json_t *old_uri = json_array_get (payto_uris,
+ j);
+ if (json_equal (payto_uri,
+ old_uri))
+ {
+ GNUNET_break_op (0);
+ payto_ok = false;
+ break;
+ }
+ }
+ if (! payto_ok)
+ break;
+ if (GNUNET_SYSERR ==
+ TALER_JSON_validate_payto (uri))
+ {
+ payto_ok = false;
+ break;
+ }
+ }
+ }
+ return payto_ok;
+}
+
+
+struct TMH_WireMethod *
+TMH_setup_wire_account (const char *payto_uri)
+{
+ struct GNUNET_HashCode salt;
+ struct TMH_WireMethod *wm;
+
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+ &salt,
+ sizeof (salt));
+ wm = GNUNET_new (struct TMH_WireMethod);
+ wm->j_wire = json_pack ("{s:s, s:o}",
+ "payto_uri", payto_uri,
+ "salt", GNUNET_JSON_from_data_auto (&salt));
+ GNUNET_assert (NULL != wm->j_wire);
+ /* This also tests for things like the IBAN being malformed */
+ GNUNET_assert (GNUNET_OK ==
+ TALER_JSON_merchant_wire_signature_hash (wm->j_wire,
+ &wm->h_wire));
+ wm->wire_method
+ = TALER_payto_get_method (payto_uri);
+ GNUNET_assert (NULL != wm->wire_method); /* checked earlier */
+ wm->active = true;
+ return wm;
+}
diff --git a/src/backend/taler-merchant-httpd_helper.h b/src/backend/taler-merchant-httpd_helper.h
new file mode 100644
index 00000000..5f478c18
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_helper.h
@@ -0,0 +1,50 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2021 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_helper.h
+ * @brief helpers for shared logic
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#ifndef TALER_EXCHANGE_HTTPD_HELPER_H
+#define TALER_EXCHANGE_HTTPD_HELPER_H
+
+
+#include "taler-merchant-httpd.h"
+
+/**
+ * check @a payto_uris for well-formedness
+ *
+ * @param payto_uris JSON array of payto URIs (presumably)
+ * @return true if they are all valid URIs (and this is an array of strings)
+ */
+bool
+TMH_payto_uri_array_valid (const json_t *payto_uris);
+
+
+/**
+ * Setup new wire method for the given @ payto_uri.
+ *
+ * @param payto_uri already validated payto URI
+ * @return new wire method object, never fails
+ */
+struct TMH_WireMethod *
+TMH_setup_wire_account (const char *payto_uri);
+
+
+#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 0a839a3a..8b0917e7 100644
--- a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
+++ b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
@@ -24,6 +24,7 @@
*/
#include "platform.h"
#include "taler-merchant-httpd_private-patch-instances-ID.h"
+#include "taler-merchant-httpd_helper.h"
#include <taler/taler_json_lib.h>
@@ -74,12 +75,12 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
&is.address),
GNUNET_JSON_spec_json ("jurisdiction",
&is.jurisdiction),
- TALER_JSON_spec_amount ("default_max_deposit_fee",
- &is.default_max_deposit_fee),
TALER_JSON_spec_amount ("default_max_wire_fee",
&is.default_max_wire_fee),
GNUNET_JSON_spec_uint32 ("default_wire_fee_amortization",
&is.default_wire_fee_amortization),
+ TALER_JSON_spec_amount ("default_max_deposit_fee",
+ &is.default_max_deposit_fee),
TALER_JSON_spec_relative_time ("default_wire_transfer_delay",
&is.default_wire_transfer_delay),
TALER_JSON_spec_relative_time ("default_pay_delay",
@@ -87,6 +88,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
GNUNET_JSON_spec_end ()
};
enum GNUNET_DB_QueryStatus qs;
+ bool committed = false;
GNUNET_assert (NULL != mi);
{
@@ -100,7 +102,19 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
? MHD_YES
: MHD_NO;
}
- if (! json_is_array (payto_uris))
+ if ((0 != strcasecmp (is.default_max_deposit_fee.currency,
+ TMH_currency)) ||
+ (0 != strcasecmp (is.default_max_wire_fee.currency,
+ TMH_currency)))
+ {
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_GENERIC_CURRENCY_MISMATCH,
+ NULL);
+ }
+ if (! TMH_payto_uri_array_valid (payto_uris))
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
@@ -119,18 +133,6 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
free_wm (wm);
}
}
- if ((0 != strcasecmp (is.default_max_deposit_fee.currency,
- TMH_currency)) ||
- (0 != strcasecmp (is.default_max_wire_fee.currency,
- TMH_currency)))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_GENERIC_CURRENCY_MISMATCH,
- NULL);
- }
if (GNUNET_OK !=
TMH_db->start (TMH_db->cls,
"PATCH /instances"))
@@ -199,31 +201,12 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
{
const char *str = json_string_value (json_array_get (payto_uris,
i));
- if (NULL == str)
- {
- GNUNET_break_op (0);
- TMH_db->rollback (TMH_db->cls);
- GNUNET_JSON_parse_free (spec);
- GNUNET_assert (NULL == wm_head);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
- NULL);
- }
if (0 == strcasecmp (uri,
str))
{
- if (NULL != matches[i])
- {
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- GNUNET_JSON_parse_free (spec);
- GNUNET_assert (NULL == wm_head);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
- str);
- }
+ /* 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;
matched = true;
break;
@@ -239,6 +222,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
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)
{
@@ -262,6 +246,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
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)
{
@@ -281,51 +266,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Adding NEW account `%s'\n",
ad.payto_uri);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &ad.salt,
- sizeof (ad.salt));
- wm = GNUNET_new (struct TMH_WireMethod);
- wm->j_wire = json_pack ("{s:s, s:o}",
- "payto_uri", ad.payto_uri,
- "salt", GNUNET_JSON_from_data_auto (&ad.salt));
- GNUNET_assert (NULL != wm->j_wire);
- wm->wire_method
- = TALER_payto_get_method (ad.payto_uri);
- if (NULL == wm->wire_method)
- {
- GNUNET_break_op (0);
- TMH_db->rollback (TMH_db->cls);
- GNUNET_JSON_parse_free (spec);
- json_decref (wm->j_wire);
- GNUNET_free (wm);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
- ad.payto_uri);
-
- }
- /* This also tests for things like the IBAN being malformed */
- if (GNUNET_OK !=
- TALER_JSON_merchant_wire_signature_hash (wm->j_wire,
- &wm->h_wire))
- {
- GNUNET_break_op (0);
- free_wm (wm);
- while (NULL != (wm = wm_head))
- {
- GNUNET_CONTAINER_DLL_remove (wm_head,
- wm_tail,
- wm);
- free_wm (wm);
- }
- TMH_db->rollback (TMH_db->cls);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
- ad.payto_uri);
- }
- wm->active = true;
+ wm = TMH_setup_wire_account (ad.payto_uri);
GNUNET_CONTAINER_DLL_insert (wm_head,
wm_tail,
wm);
@@ -349,10 +290,31 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
retry:
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
continue;
+ if (qs >= 0)
+ committed = true;
break;
} /* for(... MAX_RETRIES) */
giveup:
- if (0 > qs)
+ /* 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;
@@ -369,22 +331,6 @@ giveup:
TALER_EC_GENERIC_DB_COMMIT_FAILED,
NULL);
}
- /* 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 (wm->deleting)
- wm->active = false;
- if (wm->enabling)
- wm->active = true;
- wm->deleting = false;
- wm->enabling = false;
- }
/* Update our 'settings' */
GNUNET_free (mi->settings.name);
@@ -400,6 +346,8 @@ giveup:
{
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,
diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c
index f9df3d39..71739c3d 100644
--- a/src/backend/taler-merchant-httpd_private-post-instances.c
+++ b/src/backend/taler-merchant-httpd_private-post-instances.c
@@ -24,6 +24,7 @@
*/
#include "platform.h"
#include "taler-merchant-httpd_private-post-instances.h"
+#include "taler-merchant-httpd_helper.h"
#include <taler/taler_json_lib.h>
#include <regex.h>
@@ -234,56 +235,11 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
}
/* check payto_uris for well-formedness */
- {
- bool payto_ok = true;
-
- if (! json_is_array (payto_uris))
- {
- GNUNET_break_op (0);
- payto_ok = false;
- }
- else
- {
- unsigned int len = json_array_size (payto_uris);
-
- for (unsigned int i = 0; i<len; i++)
- {
- json_t *payto_uri = json_array_get (payto_uris,
- i);
- const char *uri;
-
- if (! json_is_string (payto_uri))
- payto_ok = false;
- uri = json_string_value (payto_uri);
- /* Test for the same payto:// URI being given twice */
- for (unsigned int j = 0; j<i; j++)
- {
- json_t *old_uri = json_array_get (payto_uris,
- j);
- if (json_equal (payto_uri,
- old_uri))
- {
- GNUNET_break_op (0);
- payto_ok = false;
- break;
- }
- }
- if (! payto_ok)
- break;
- if (GNUNET_SYSERR ==
- TALER_JSON_validate_payto (uri))
- {
- payto_ok = false;
- break;
- }
- }
- }
- if (! payto_ok)
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
- NULL);
- }
+ if (! TMH_payto_uri_array_valid (payto_uris))
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
+ NULL);
/* check 'id' well-formed */
{
@@ -402,24 +358,8 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
json_t *payto_uri = json_array_get (payto_uris,
i);
struct TMH_WireMethod *wm;
- struct GNUNET_HashCode salt;
-
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &salt,
- sizeof (salt));
- wm = GNUNET_new (struct TMH_WireMethod);
- wm->j_wire = json_pack ("{s:O, s:o}",
- "payto_uri", payto_uri,
- "salt", GNUNET_JSON_from_data_auto (&salt));
- GNUNET_assert (NULL != wm->j_wire);
- /* This also tests for things like the IBAN being malformed */
- GNUNET_assert (GNUNET_OK ==
- TALER_JSON_merchant_wire_signature_hash (wm->j_wire,
- &wm->h_wire));
- wm->wire_method
- = TALER_payto_get_method (json_string_value (payto_uri));
- GNUNET_assert (NULL != wm->wire_method); /* checked earlier */
- wm->active = true;
+
+ wm = TMH_setup_wire_account (json_string_value (payto_uri));
GNUNET_CONTAINER_DLL_insert (wm_head,
wm_tail,
wm);
diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql
index 74144e86..65ea94c9 100644
--- a/src/backenddb/merchant-0001.sql
+++ b/src/backenddb/merchant-0001.sql
@@ -101,6 +101,7 @@ CREATE TABLE IF NOT EXISTS merchant_accounts
,payto_uri VARCHAR NOT NULL
,active boolean NOT NULL
,UNIQUE (merchant_serial,payto_uri)
+ ,UNIQUE (h_wire)
);
COMMENT ON TABLE merchant_accounts
IS 'bank accounts of the instances';
diff --git a/src/backenddb/merchant-0002.sql b/src/backenddb/merchant-0002.sql
index 1cb1d7b2..46428dd9 100644
--- a/src/backenddb/merchant-0002.sql
+++ b/src/backenddb/merchant-0002.sql
@@ -18,7 +18,7 @@
BEGIN;
-- Check patch versioning is in place.
-SELECT _v.register_patch('merchant-0002', ARRAY['merchant-0001'], NULL);
+SELECT _v.register_patch('merchant-0002', NULL, NULL);
-- need serial IDs on various tables for exchange-auditor replication
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index ed051053..570c681a 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -795,15 +795,18 @@ postgres_update_instance_auth (
* Set an instance's account in our database to "inactive".
*
* @param cls closure
+ * @param merchant_id merchant backend instance ID
* @param h_wire hash of the wire account to set to inactive
* @return database result code
*/
static enum GNUNET_DB_QueryStatus
postgres_inactivate_account (void *cls,
+ const char *merchant_id,
const struct GNUNET_HashCode *h_wire)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (merchant_id),
GNUNET_PQ_query_param_auto_from_type (h_wire),
GNUNET_PQ_query_param_end
};
@@ -819,15 +822,18 @@ postgres_inactivate_account (void *cls,
* Set an instance's account in our database to "active".
*
* @param cls closure
+ * @param merchant_id merchant backend instance ID
* @param h_wire hash of the wire account to set to active
* @return database result code
*/
static enum GNUNET_DB_QueryStatus
postgres_activate_account (void *cls,
+ const char *merchant_id,
const struct GNUNET_HashCode *h_wire)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (merchant_id),
GNUNET_PQ_query_param_auto_from_type (h_wire),
GNUNET_PQ_query_param_end
};
@@ -6375,20 +6381,30 @@ postgres_connect (void *cls)
"UPDATE merchant_instances SET"
" auth_hash=$2"
",auth_salt=$3"
- " WHERE merchant_id = $1",
+ " WHERE merchant_id=$1",
3),
- /* for postgres_inactivate_account() */
+ /* for postgres_inactivate_account(); the merchant
+ instance is implied from the random salt that
+ is part of the h_wire calculation */
GNUNET_PQ_make_prepare ("inactivate_account",
"UPDATE merchant_accounts SET"
" active=FALSE"
- " WHERE h_wire = $1",
- 1),
+ " WHERE h_wire=$2 AND"
+ " merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)",
+ 2),
/* for postgres_activate_account() */
GNUNET_PQ_make_prepare ("activate_account",
"UPDATE merchant_accounts SET"
" active=TRUE"
- " WHERE h_wire = $1",
- 1),
+ " WHERE h_wire=$2 AND"
+ " merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)",
+ 2),
/* for postgres_lookup_products() */
GNUNET_PQ_make_prepare ("lookup_products",
"SELECT"
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index b3b43062..7a930296 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -478,11 +478,13 @@ test_insert_account (const struct InstanceData *instance,
* @return 0 on success, 1 otherwise.
*/
static int
-test_inactivate_account (const struct TALER_MERCHANTDB_AccountDetails *account,
+test_inactivate_account (const struct InstanceData *instance,
+ const struct TALER_MERCHANTDB_AccountDetails *account,
enum GNUNET_DB_QueryStatus expected_result)
{
TEST_COND_RET_ON_FAIL (expected_result ==
plugin->inactivate_account (plugin->cls,
+ instance->instance.id,
&account->h_wire),
"Deactivate account failed\n");
return 0;
@@ -618,9 +620,11 @@ run_test_instances (struct TestInstances_Closure *cls)
1,
instances));
/* Test deactivate account */
- TEST_RET_ON_FAIL (test_inactivate_account (&cls->accounts[0],
+ TEST_RET_ON_FAIL (test_inactivate_account (&cls->instances[0],
+ &cls->accounts[0],
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
- TEST_RET_ON_FAIL (test_inactivate_account (&cls->accounts[1],
+ TEST_RET_ON_FAIL (test_inactivate_account (&cls->instances[1],
+ &cls->accounts[1],
GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
cls->accounts[0].active = false;
TEST_RET_ON_FAIL (test_lookup_instances (false,
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index f3989790..0397b9aa 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -866,11 +866,13 @@ struct TALER_MERCHANTDB_Plugin
* Set an instance's account in our database to "inactive".
*
* @param cls closure
+ * @param merchant_id merchant backend instance ID
* @param h_wire hash of the wire account to set to inactive
* @return database result code
*/
enum GNUNET_DB_QueryStatus
(*inactivate_account)(void *cls,
+ const char *merchant_id,
const struct GNUNET_HashCode *h_wire);
@@ -878,11 +880,13 @@ struct TALER_MERCHANTDB_Plugin
* Set an instance's account in our database to "active".
*
* @param cls closure
+ * @param merchant_id merchant backend instance ID
* @param h_wire hash of the wire account to set to active
* @return database result code
*/
enum GNUNET_DB_QueryStatus
(*activate_account)(void *cls,
+ const char *merchant_id,
const struct GNUNET_HashCode *h_wire);
/**