diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-07-20 19:33:59 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-07-20 19:33:59 +0200 |
commit | 362bf0c5bd2270ed6a54dfbdfd83702dca892797 (patch) | |
tree | 62dc70b9111810c1375fedfb75efff882bb5058d /src | |
parent | 43dd7c8ae663fcb3db64fb7571c56144baa83a0e (diff) | |
download | merchant-362bf0c5bd2270ed6a54dfbdfd83702dca892797.tar.gz merchant-362bf0c5bd2270ed6a54dfbdfd83702dca892797.tar.bz2 merchant-362bf0c5bd2270ed6a54dfbdfd83702dca892797.zip |
-workshop refactoring
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/Makefile.am | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 17 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.h | 6 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_helper.c | 106 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_helper.h | 50 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-patch-instances-ID.c | 146 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-instances.c | 76 | ||||
-rw-r--r-- | src/backenddb/merchant-0001.sql | 1 | ||||
-rw-r--r-- | src/backenddb/merchant-0002.sql | 2 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 28 | ||||
-rw-r--r-- | src/backenddb/test_merchantdb.c | 10 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 4 |
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); /** |