diff options
Diffstat (limited to 'src/backenddb')
36 files changed, 1893 insertions, 511 deletions
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am index 3d7d7827..6081f722 100644 --- a/src/backenddb/Makefile.am +++ b/src/backenddb/Makefile.am @@ -84,6 +84,19 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \ pg_update_instance_auth.h pg_update_instance_auth.c \ pg_inactivate_account.h pg_inactivate_account.c \ pg_activate_account.h pg_activate_account.c \ + pg_insert_otp.h pg_insert_otp.c \ + pg_delete_otp.h pg_delete_otp.c \ + pg_update_otp.h pg_update_otp.c \ + pg_select_otp.h pg_select_otp.c \ + pg_select_otp_serial.h pg_select_otp_serial.c \ + pg_lookup_otp_devices.h pg_lookup_otp_devices.c \ + pg_select_account.h pg_select_account.c \ + pg_select_accounts.h pg_select_accounts.c \ + pg_delete_template.h pg_delete_template.c \ + pg_insert_template.h pg_insert_template.c \ + pg_update_template.h pg_update_template.c \ + pg_lookup_templates.h pg_lookup_templates.c \ + pg_lookup_template.h pg_lookup_template.c \ pg_lookup_products.h pg_lookup_products.c \ pg_lookup_product.h pg_lookup_product.c \ pg_delete_product.h pg_delete_product.c \ diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql index bbc97828..4d286db6 100644 --- a/src/backenddb/merchant-0001.sql +++ b/src/backenddb/merchant-0001.sql @@ -291,6 +291,7 @@ CREATE TABLE IF NOT EXISTS merchant_contract_terms REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE ,order_id TEXT NOT NULL ,contract_terms BYTEA NOT NULL + ,wallet_data BYTEA DEFAULT NULL ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64) ,creation_time INT8 NOT NULL ,pay_deadline INT8 NOT NULL @@ -313,6 +314,8 @@ COMMENT ON COLUMN merchant_contract_terms.merchant_serial IS 'Identifies the instance offering the contract'; COMMENT ON COLUMN merchant_contract_terms.contract_terms IS 'These contract terms include the wallet nonce'; +COMMENT ON COLUMN merchant_contract_terms.wallet_data + IS 'Data provided by the wallet when paying for the contract (subcontract selection, blinded tokens, etc.)'; COMMENT ON COLUMN merchant_contract_terms.h_contract_terms IS 'Hash over contract_terms'; COMMENT ON COLUMN merchant_contract_terms.refund_deadline @@ -643,14 +646,37 @@ COMMENT ON COLUMN merchant_kyc.exchange_url IS 'Which exchange base URL is this KYC status valid for'; +CREATE TABLE IF NOT EXISTS merchant_otp_devices + (otp_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY + ,merchant_serial BIGINT NOT NULL + REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE + ,otp_id TEXT NOT NULL + ,otp_description TEXT NOT NULL + ,otp_key TEXT DEFAULT NULL + ,otp_algorithm INT NOT NULL DEFAULT (0) + ,otp_ctr INT8 NOT NULL DEFAULT (0) + ,UNIQUE (merchant_serial, otp_id) + ); +COMMENT ON TABLE merchant_otp_devices + IS 'OTP device owned by a merchant'; +COMMENT ON COLUMN merchant_otp_devices.otp_description + IS 'Human-readable OTP device description'; +COMMENT ON COLUMN merchant_otp_devices.otp_key + IS 'A base64-encoded key of the point-of-sale. It will be use by the OTP device'; +COMMENT ON COLUMN merchant_otp_devices.otp_algorithm + IS 'algorithm to used to generate the confirmation code. It is linked with the otp_key and otp_ctr'; +COMMENT ON COLUMN merchant_otp_devices.otp_ctr + IS 'counter for counter-based OTP generators'; + + CREATE TABLE IF NOT EXISTS merchant_template (template_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ,merchant_serial BIGINT NOT NULL REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE ,template_id TEXT NOT NULL ,template_description TEXT NOT NULL - ,pos_key TEXT DEFAULT NULL - ,pos_algorithm INT NOT NULL DEFAULT (0) + ,otp_device_id BIGINT + REFERENCES merchant_otp_devices (otp_serial) ON DELETE SET NULL ,template_contract TEXT NOT NULL -- in JSON format ,UNIQUE (merchant_serial, template_id) ); @@ -658,14 +684,11 @@ COMMENT ON TABLE merchant_template IS 'template used by the merchant (may be incomplete, frontend can override)'; COMMENT ON COLUMN merchant_template.template_description IS 'Human-readable template description'; -COMMENT ON COLUMN merchant_template.pos_key - IS 'A base64-encoded key of the point-of-sale. It will be use by the TOTP'; -COMMENT ON COLUMN merchant_template.pos_algorithm - IS 'algorithm to used to generate the confirmation code. It is link with the pos_key'; COMMENT ON COLUMN merchant_template.template_contract IS 'The template contract will contains some additional information.'; + CREATE TABLE IF NOT EXISTS merchant_webhook (webhook_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ,merchant_serial BIGINT NOT NULL diff --git a/src/backenddb/merchantdb_helper.c b/src/backenddb/merchantdb_helper.c index ee52cccc..4ae75020 100644 --- a/src/backenddb/merchantdb_helper.c +++ b/src/backenddb/merchantdb_helper.c @@ -42,7 +42,7 @@ TALER_MERCHANTDB_template_details_free ( struct TALER_MERCHANTDB_TemplateDetails *tp) { GNUNET_free (tp->template_description); - GNUNET_free (tp->pos_key); + GNUNET_free (tp->otp_id); json_decref (tp->template_contract); } diff --git a/src/backenddb/pg_delete_otp.c b/src/backenddb/pg_delete_otp.c new file mode 100644 index 00000000..7d32b3fb --- /dev/null +++ b/src/backenddb/pg_delete_otp.c @@ -0,0 +1,55 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_delete_otp.c + * @brief Implementation of the delete_otp function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_delete_otp.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_delete_otp (void *cls, + const char *instance_id, + const char *otp_id) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (otp_id), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "delete_otp", + "DELETE" + " FROM merchant_otp_devices" + " WHERE merchant_otp_devices.merchant_serial=" + " (SELECT merchant_serial " + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND merchant_otp_devices.template_id=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "delete_otp", + params); +} + diff --git a/src/backenddb/pg_delete_otp.h b/src/backenddb/pg_delete_otp.h new file mode 100644 index 00000000..40e67e8a --- /dev/null +++ b/src/backenddb/pg_delete_otp.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_delete_otp.h + * @brief implementation of the delete_otp function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DELETE_OTP_H +#define PG_DELETE_OTP_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Delete information about an OTP device. + * + * @param cls closure + * @param instance_id instance to delete OTP device of + * @param otp_id otp device to delete + * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + * if template unknown. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_delete_otp (void *cls, + const char *instance_id, + const char *otp_id); + +#endif diff --git a/src/backenddb/pg_delete_template.c b/src/backenddb/pg_delete_template.c new file mode 100644 index 00000000..15531c6b --- /dev/null +++ b/src/backenddb/pg_delete_template.c @@ -0,0 +1,55 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_delete_template.c + * @brief Implementation of the delete_template function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_delete_template.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_delete_template (void *cls, + const char *instance_id, + const char *template_id) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (template_id), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "delete_template", + "DELETE" + " FROM merchant_template" + " WHERE merchant_template.merchant_serial=" + " (SELECT merchant_serial " + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND merchant_template.template_id=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "delete_template", + params); +} + diff --git a/src/backenddb/pg_delete_template.h b/src/backenddb/pg_delete_template.h new file mode 100644 index 00000000..ed0e0cf0 --- /dev/null +++ b/src/backenddb/pg_delete_template.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_delete_template.h + * @brief implementation of the delete_template function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DELETE_TEMPLATE_H +#define PG_DELETE_TEMPLATE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Delete information about a template. + * + * @param cls closure + * @param instance_id instance to delete template of + * @param template_id template to delete + * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + * if template unknown. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_delete_template (void *cls, + const char *instance_id, + const char *template_id); + + +#endif diff --git a/src/backenddb/pg_inactivate_account.c b/src/backenddb/pg_inactivate_account.c index 67c39462..7e0d10ae 100644 --- a/src/backenddb/pg_inactivate_account.c +++ b/src/backenddb/pg_inactivate_account.c @@ -38,8 +38,6 @@ TMH_PG_inactivate_account (void *cls, }; check_connection (pg); - /* the merchant instance is implied from the random salt - that is part of the h_wire calculation */ PREPARE (pg, "inactivate_account", "UPDATE merchant_accounts SET" diff --git a/src/backenddb/pg_insert_otp.c b/src/backenddb/pg_insert_otp.c new file mode 100644 index 00000000..feae2230 --- /dev/null +++ b/src/backenddb/pg_insert_otp.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_insert_otp.c + * @brief Implementation of the insert_otp function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_insert_otp.h" +#include "pg_helper.h" + + +/** + * Insert details about a particular OTP device. + * + * @param cls closure + * @param instance_id instance to insert OTP device for + * @param otp_id otp identifier of OTP device to insert + * @param td the OTP device details to insert + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_insert_otp (void *cls, + const char *instance_id, + const char *otp_id, + const struct TALER_MERCHANTDB_OtpDeviceDetails *td) +{ + struct PostgresClosure *pg = cls; + uint32_t pos32 = (uint32_t) td->otp_algorithm; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (otp_id), + GNUNET_PQ_query_param_string (td->otp_description), + GNUNET_PQ_query_param_string (td->otp_key), + GNUNET_PQ_query_param_uint32 (&pos32), + GNUNET_PQ_query_param_uint64 (&td->otp_ctr), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "insert_otp", + "INSERT INTO merchant_otp_devices" + "(merchant_serial" + ",otp_id" + ",otp_description" + ",otp_key" + ",otp_algorithm" + ",otp_ctr" + ")" + " SELECT merchant_serial," + " $2, $3, $4, $5, $6" + " FROM merchant_instances" + " WHERE merchant_id=$1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_otp", + params); +} diff --git a/src/backenddb/pg_insert_otp.h b/src/backenddb/pg_insert_otp.h new file mode 100644 index 00000000..70267d37 --- /dev/null +++ b/src/backenddb/pg_insert_otp.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_insert_otp.h + * @brief implementation of the insert_otp function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_OTP_H +#define PG_INSERT_OTP_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Insert details about a particular OTP device. + * + * @param cls closure + * @param instance_id instance to insert OTP device for + * @param otp_id otp identifier of OTP device to insert + * @param td the OTP device details to insert + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_insert_otp (void *cls, + const char *instance_id, + const char *otp_id, + const struct TALER_MERCHANTDB_OtpDeviceDetails *td); + + +#endif diff --git a/src/backenddb/pg_insert_template.c b/src/backenddb/pg_insert_template.c new file mode 100644 index 00000000..5fc76a1d --- /dev/null +++ b/src/backenddb/pg_insert_template.c @@ -0,0 +1,66 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_insert_template.c + * @brief Implementation of the insert_template function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_insert_template.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_insert_template (void *cls, + const char *instance_id, + const char *template_id, + uint64_t otp_serial_id, + const struct TALER_MERCHANTDB_TemplateDetails *td) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (template_id), + GNUNET_PQ_query_param_string (td->template_description), + (0 == otp_serial_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_uint64 (&otp_serial_id), + TALER_PQ_query_param_json (td->template_contract), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "insert_template", + "INSERT INTO merchant_template" + "(merchant_serial" + ",template_id" + ",template_description" + ",otp_device_id" + ",template_contract" + ")" + " SELECT merchant_serial," + " $2, $3, $4, $5" + " FROM merchant_instances" + " WHERE merchant_id=$1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_template", + params); +} + diff --git a/src/backenddb/pg_insert_template.h b/src/backenddb/pg_insert_template.h new file mode 100644 index 00000000..fb9c3700 --- /dev/null +++ b/src/backenddb/pg_insert_template.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_insert_template.h + * @brief implementation of the insert_template function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_TEMPLATE_H +#define PG_INSERT_TEMPLATE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Insert details about a particular template. + * + * @param cls closure + * @param instance_id instance to insert template for + * @param template_id template identifier of template to insert + * @param otp_serial_id 0 if no OTP device is associated + * @param td the template details to insert + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_insert_template (void *cls, + const char *instance_id, + const char *template_id, + uint64_t otp_serial_id, + const struct TALER_MERCHANTDB_TemplateDetails *td); + +#endif diff --git a/src/backenddb/pg_lookup_instances.c b/src/backenddb/pg_lookup_instances.c index 15137518..323b1957 100644 --- a/src/backenddb/pg_lookup_instances.c +++ b/src/backenddb/pg_lookup_instances.c @@ -92,17 +92,6 @@ prepare (struct PostgresClosure *pg) " merchant_priv" " FROM merchant_keys" " WHERE merchant_serial=$1"); - PREPARE (pg, - "lookup_accounts", - "SELECT" - " h_wire" - ",salt" - ",payto_uri" - ",credit_facade_url" - ",credit_facade_credentials" - ",active" - " FROM merchant_accounts" - " WHERE merchant_serial=$1"); return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; } @@ -112,13 +101,9 @@ prepare (struct PostgresClosure *pg) * Find the private key if possible, and invoke the callback. * * @param lic context we are handling - * @param num_accounts length of @a accounts array - * @param accounts information about accounts of the instance in @a lic */ static void -call_with_accounts (struct LookupInstancesContext *lic, - unsigned int num_accounts, - const struct TALER_MERCHANTDB_AccountDetails accounts[]) +call_cb (struct LookupInstancesContext *lic) { struct PostgresClosure *pg = lic->pg; enum GNUNET_DB_QueryStatus qs; @@ -157,91 +142,7 @@ call_with_accounts (struct LookupInstancesContext *lic, &lic->merchant_pub, (0 == qs) ? NULL : &merchant_priv, &lic->is, - &lic->ias, - num_accounts, - accounts); -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results about accounts. - * - * @param cls of type `struct LookupInstancesContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_accounts_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupInstancesContext *lic = cls; - char *paytos[GNUNET_NZL (num_results)]; - char *facade_urls[GNUNET_NZL (num_results)]; - json_t *credentials[GNUNET_NZL (num_results)]; - struct TALER_MERCHANTDB_AccountDetails accounts[GNUNET_NZL (num_results)]; - - memset (facade_urls, - 0, - sizeof (facade_urls)); - memset (credentials, - 0, - sizeof (credentials)); - /* Note: this memset is completely superfluous, but gcc-11 (and gcc-12) have - a bug creating a warning without it! See #7585 */ - memset (accounts, - 0, - sizeof (accounts)); - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_MERCHANTDB_AccountDetails *account = &accounts[i]; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("h_wire", - &account->h_wire), - GNUNET_PQ_result_spec_auto_from_type ("salt", - &account->salt), - GNUNET_PQ_result_spec_string ("payto_uri", - &paytos[i]), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("credit_facade_url", - &facade_urls[i]), - NULL), - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("credit_facade_credentials", - &credentials[i]), - NULL), - GNUNET_PQ_result_spec_bool ("active", - &account->active), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - lic->qs = GNUNET_DB_STATUS_HARD_ERROR; - for (unsigned int j = 0; j < i; j++) - { - GNUNET_free (paytos[j]); - GNUNET_free (facade_urls[j]); - json_decref (credentials[j]); - } - return; - } - account->payto_uri = paytos[i]; - } - call_with_accounts (lic, - num_results, - accounts); - for (unsigned int i = 0; i < num_results; i++) - { - GNUNET_free (paytos[i]); - GNUNET_free (facade_urls[i]); - json_decref (credentials[i]); - } + &lic->ias); } @@ -316,10 +217,6 @@ lookup_instances_cb (void *cls, NULL), GNUNET_PQ_result_spec_end }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&lic->instance_serial), - GNUNET_PQ_query_param_end - }; memset (&lic->ias.auth_salt, 0, @@ -337,19 +234,7 @@ lookup_instances_cb (void *cls, return; } lic->is.ut = (enum TALER_KYCLOGIC_KycUserType) ut32; - lic->qs = GNUNET_PQ_eval_prepared_multi_select (lic->pg->conn, - "lookup_accounts", - params, - &lookup_accounts_cb, - lic); - if (0 > lic->qs) - { - /* lookup_accounts_cb() did not run, still notify about the - account-less instance! */ - call_with_accounts (lic, - 0, - NULL); - } + call_cb (lic); GNUNET_PQ_cleanup_result (rs); if (0 > lic->qs) break; diff --git a/src/backenddb/pg_lookup_otp_devices.c b/src/backenddb/pg_lookup_otp_devices.c new file mode 100644 index 00000000..b4a2b569 --- /dev/null +++ b/src/backenddb/pg_lookup_otp_devices.c @@ -0,0 +1,133 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_lookup_otp_devices.c + * @brief Implementation of the lookup_otp_devices function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_lookup_otp_devices.h" +#include "pg_helper.h" + + +/** + * Context used for TMH_PG_lookup_otp_devices(). + */ +struct LookupOtpDeviceContext +{ + /** + * Function to call with the results. + */ + TALER_MERCHANTDB_OtpDeviceCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Did database result extraction fail? + */ + bool extract_failed; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results about otp_device. + * + * @param[in,out] cls of type `struct LookupOtpDeviceContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_otp_devices_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupOtpDeviceContext *tlc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + char *otp_device_id; + char *otp_device_description; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("otp_id", + &otp_device_id), + GNUNET_PQ_result_spec_string ("otp_description", + &otp_device_description), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + tlc->extract_failed = true; + return; + } + tlc->cb (tlc->cb_cls, + otp_device_id, + otp_device_description); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_otp_devices (void *cls, + const char *instance_id, + TALER_MERCHANTDB_OtpDeviceCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct LookupOtpDeviceContext tlc = { + .cb = cb, + .cb_cls = cb_cls, + /* Can be overwritten by the lookup_otp_device_cb */ + .extract_failed = false, + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "lookup_otp_devices", + "SELECT" + " otp_id" + ",otp_description" + " FROM merchant_otp_devices" + " JOIN merchant_instances" + " USING (merchant_serial)" + " WHERE merchant_instances.merchant_id=$1"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_otp_devices", + params, + &lookup_otp_devices_cb, + &tlc); + /* If there was an error inside lookup_otp_device_cb, return a hard error. */ + if (tlc.extract_failed) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/backenddb/pg_lookup_otp_devices.h b/src/backenddb/pg_lookup_otp_devices.h new file mode 100644 index 00000000..bb58b70f --- /dev/null +++ b/src/backenddb/pg_lookup_otp_devices.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_lookup_otp_devices.h + * @brief implementation of the lookup_otp_devices function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_OTP_DEVICES_H +#define PG_LOOKUP_OTP_DEVICES_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Lookup all of the OTP devices the given instance has configured. + * + * @param cls closure + * @param instance_id instance to lookup OTP devices for + * @param cb function to call on all OTP devices found + * @param cb_cls closure for @a cb + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_otp_devices (void *cls, + const char *instance_id, + TALER_MERCHANTDB_OtpDeviceCallback cb, + void *cb_cls); + + +#endif diff --git a/src/backenddb/pg_lookup_template.c b/src/backenddb/pg_lookup_template.c new file mode 100644 index 00000000..a0326bc8 --- /dev/null +++ b/src/backenddb/pg_lookup_template.c @@ -0,0 +1,98 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_lookup_template.c + * @brief Implementation of the lookup_template function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_lookup_template.h" +#include "pg_helper.h" + + +/** + * Lookup details about a particular template. + * + * @param cls closure + * @param instance_id instance to lookup template for + * @param template_id template to lookup + * @param[out] td set to the template details on success, can be NULL + * (in that case we only want to check if the template exists) + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_template (void *cls, + const char *instance_id, + const char *template_id, + struct TALER_MERCHANTDB_TemplateDetails *td) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (template_id), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "lookup_template", + "SELECT" + " mt.template_description" + ",mod.otp_id" + ",mt.template_contract" + " FROM merchant_template mt" + " JOIN merchant_instances mi" + " ON (mi.merchant_serial = mt.merchant_serial)" + " LEFT JOIN merchant_otp_devices mod" + " ON (mod.otp_serial = mt.otp_device_id)" + " WHERE mi.merchant_id=$1" + " AND mt.template_id=$2"); + if (NULL == td) + { + struct GNUNET_PQ_ResultSpec rs_null[] = { + GNUNET_PQ_result_spec_end + }; + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_template", + params, + rs_null); + } + else + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("template_description", + &td->template_description), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("otp_id", + &td->otp_id), + NULL), + TALER_PQ_result_spec_json ("template_contract", + &td->template_contract), + GNUNET_PQ_result_spec_end + }; + + td->otp_id = NULL; + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_template", + params, + rs); + } +} + diff --git a/src/backenddb/pg_lookup_template.h b/src/backenddb/pg_lookup_template.h new file mode 100644 index 00000000..44e01b08 --- /dev/null +++ b/src/backenddb/pg_lookup_template.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_lookup_template.h + * @brief implementation of the lookup_template function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_TEMPLATE_H +#define PG_LOOKUP_TEMPLATE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Lookup details about a particular template. + * + * @param cls closure + * @param instance_id instance to lookup template for + * @param template_id template to lookup + * @param[out] td set to the template details on success, can be NULL + * (in that case we only want to check if the template exists) + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_template (void *cls, + const char *instance_id, + const char *template_id, + struct TALER_MERCHANTDB_TemplateDetails *td); + + +#endif diff --git a/src/backenddb/pg_lookup_templates.c b/src/backenddb/pg_lookup_templates.c new file mode 100644 index 00000000..59240994 --- /dev/null +++ b/src/backenddb/pg_lookup_templates.c @@ -0,0 +1,135 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_lookup_templates.c + * @brief Implementation of the lookup_templates function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_lookup_templates.h" +#include "pg_helper.h" + + +/** + * Context used for TMH_PG_lookup_templates(). + */ +struct LookupTemplateContext +{ + /** + * Function to call with the results. + */ + TALER_MERCHANTDB_TemplatesCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Did database result extraction fail? + */ + bool extract_failed; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results about template. + * + * @param[in,out] cls of type `struct LookupTemplateContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_templates_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupTemplateContext *tlc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + char *template_id; + char *template_description; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("template_id", + &template_id), + GNUNET_PQ_result_spec_string ("template_description", + &template_description), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + tlc->extract_failed = true; + return; + } + tlc->cb (tlc->cb_cls, + template_id, + template_description); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_templates (void *cls, + const char *instance_id, + TALER_MERCHANTDB_TemplatesCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct LookupTemplateContext tlc = { + .cb = cb, + .cb_cls = cb_cls, + /* Can be overwritten by the lookup_template_cb */ + .extract_failed = false, + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "lookup_templates", + "SELECT" + " template_id" + ",template_description" + " FROM merchant_template" + " JOIN merchant_instances" + " USING (merchant_serial)" + " WHERE merchant_instances.merchant_id=$1"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_templates", + params, + &lookup_templates_cb, + &tlc); + /* If there was an error inside lookup_template_cb, return a hard error. */ + if (tlc.extract_failed) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} + + diff --git a/src/backenddb/pg_lookup_templates.h b/src/backenddb/pg_lookup_templates.h new file mode 100644 index 00000000..eee5be7e --- /dev/null +++ b/src/backenddb/pg_lookup_templates.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_lookup_templates.h + * @brief implementation of the lookup_templates function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_TEMPLATES_H +#define PG_LOOKUP_TEMPLATES_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Lookup all of the templates the given instance has configured. + * + * @param cls closure + * @param instance_id instance to lookup template for + * @param cb function to call on all template found + * @param cb_cls closure for @a cb + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_templates (void *cls, + const char *instance_id, + TALER_MERCHANTDB_TemplatesCallback cb, + void *cb_cls); + +#endif diff --git a/src/backenddb/pg_select_account.c b/src/backenddb/pg_select_account.c new file mode 100644 index 00000000..abf7e9a8 --- /dev/null +++ b/src/backenddb/pg_select_account.c @@ -0,0 +1,79 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_select_account.c + * @brief Implementation of the select_account function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_select_accounts.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_select_account (void *cls, + const char *id, + const struct TALER_MerchantWireHashP *h_wire, + struct TALER_MERCHANTDB_AccountDetails *ad) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (id), + GNUNET_PQ_query_param_auto_from_type (h_wire), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("salt", + &ad->salt), + GNUNET_PQ_result_spec_string ("payto_uri", + &ad->payto_uri), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("credit_facade_url", + &ad->credit_facade_url), + NULL), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("credit_facade_credentials", + &ad->credit_facade_credentials), + NULL), + GNUNET_PQ_result_spec_bool ("active", + &ad->active), + GNUNET_PQ_result_spec_end + }; + + ad->h_wire = *h_wire; + check_connection (pg); + PREPARE (pg, + "select_account", + "SELECT" + " salt" + ",payto_uri" + ",credit_facade_url" + ",credit_facade_credentials" + ",active" + " FROM merchant_accounts" + " WHERE merchant_serial=" + " (SELECT merchant_serial " + " FROM merchant_instances" + " WHERE merchant_id=$1) AND " + " h_wire=$2;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_account", + params, + rs); +} diff --git a/src/backenddb/pg_select_account.h b/src/backenddb/pg_select_account.h new file mode 100644 index 00000000..d74eaf1e --- /dev/null +++ b/src/backenddb/pg_select_account.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_select_account.h + * @brief implementation of the select_account function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_ACCOUNT_H +#define PG_SELECT_ACCOUNT_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Obtain information about an instance's accounts. + * + * @param cls closure + * @param id identifier of the instance + * @param h_wire wire hash of the account + * @param[out] ad account details returned + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_select_account (void *cls, + const char *id, + const struct TALER_MerchantWireHashP *h_wire, + struct TALER_MERCHANTDB_AccountDetails *ad); + +#endif diff --git a/src/backenddb/pg_select_accounts.c b/src/backenddb/pg_select_accounts.c new file mode 100644 index 00000000..cf15a765 --- /dev/null +++ b/src/backenddb/pg_select_accounts.c @@ -0,0 +1,158 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_select_accounts.c + * @brief Implementation of the select_accounts function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_select_accounts.h" +#include "pg_helper.h" + + +/** + * Context for select_accounts(). + */ +struct SelectAccountsContext +{ + /** + * Function to call with the results. + */ + TALER_MERCHANTDB_AccountCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Database context. + */ + struct PostgresClosure *pg; + + /** + * Set to the return value on errors. + */ + enum GNUNET_DB_QueryStatus qs; + +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results about accounts. + * + * @param cls of type `struct SelectAccountsContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +select_account_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct SelectAccountsContext *lic = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + char *payto; + char *facade_url = NULL; + json_t *credential = NULL; + struct TALER_MERCHANTDB_AccountDetails acc; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("h_wire", + &acc.h_wire), + GNUNET_PQ_result_spec_auto_from_type ("salt", + &acc.salt), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("credit_facade_url", + &facade_url), + NULL), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("credit_facade_credentials", + &credential), + NULL), + GNUNET_PQ_result_spec_bool ("active", + &acc.active), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + lic->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + acc.payto_uri = payto; + acc.credit_facade_url = facade_url; + acc.credit_facade_credentials = credential; + lic->cb (lic->cb_cls, + &acc); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_select_accounts (void *cls, + const char *id, + TALER_MERCHANTDB_AccountCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct SelectAccountsContext lic = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (id), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "select_accounts", + "SELECT" + " h_wire" + ",salt" + ",payto_uri" + ",credit_facade_url" + ",credit_facade_credentials" + ",active" + " FROM merchant_accounts" + " WHERE merchant_serial=" + " (SELECT merchant_serial " + " FROM merchant_instances" + " WHERE merchant_id=$1);"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_accounts", + params, + &select_account_cb, + &lic); + if (0 > lic.qs) + return lic.qs; + return qs; +} diff --git a/src/backenddb/pg_select_accounts.h b/src/backenddb/pg_select_accounts.h new file mode 100644 index 00000000..935fada6 --- /dev/null +++ b/src/backenddb/pg_select_accounts.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_select_accounts.h + * @brief implementation of the select_accounts function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_ACCOUNTS_H +#define PG_SELECT_ACCOUNTS_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Obtain information about an instance's accounts. + * + * @param cls closure + * @param id identifier of the instance + * @param cb function to call on each account + * @param cb_cls closure for @a cb + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_select_accounts (void *cls, + const char *id, + TALER_MERCHANTDB_AccountCallback cb, + void *cb_cls); + +#endif diff --git a/src/backenddb/pg_select_otp.c b/src/backenddb/pg_select_otp.c new file mode 100644 index 00000000..f105488a --- /dev/null +++ b/src/backenddb/pg_select_otp.c @@ -0,0 +1,91 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_select_otp.c + * @brief Implementation of the select_otp function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_select_otp.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_select_otp (void *cls, + const char *instance_id, + const char *otp_id, + struct TALER_MERCHANTDB_OtpDeviceDetails *td) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (otp_id), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "select_otp", + "SELECT" + " otp_description" + ",otp_ctr" + ",otp_key" + ",otp_algorithm" + " FROM merchant_otp_devices" + " JOIN merchant_instances" + " USING (merchant_serial)" + " WHERE merchant_instances.merchant_id=$1" + " AND merchant_otp_devices.otp_id=$2"); + if (NULL == td) + { + struct GNUNET_PQ_ResultSpec rs_null[] = { + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_otp", + params, + rs_null); + } + else + { + uint32_t pos32; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("otp_description", + &td->otp_description), + GNUNET_PQ_result_spec_uint64 ("otp_ctr", + &td->otp_ctr), + GNUNET_PQ_result_spec_string ("otp_key", + &td->otp_key), + GNUNET_PQ_result_spec_uint32 ("otp_algorithm", + &pos32), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_otp", + params, + rs); + td->otp_algorithm = (enum TALER_MerchantConfirmationAlgorithm) pos32; + return qs; + } +} + diff --git a/src/backenddb/pg_select_otp.h b/src/backenddb/pg_select_otp.h new file mode 100644 index 00000000..e015cf6b --- /dev/null +++ b/src/backenddb/pg_select_otp.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_select_otp.h + * @brief implementation of the select_otp function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_OTP_H +#define PG_SELECT_OTP_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Lookup details about an OTP device. + * + * @param cls closure + * @param instance_id instance to lookup template for + * @param otp_id OTP device to lookup + * @param[out] td set to the OTP device details on success, can be NULL + * (in that case we only want to check if the template exists) + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_select_otp (void *cls, + const char *instance_id, + const char *otp_id, + struct TALER_MERCHANTDB_OtpDeviceDetails *td); + +#endif diff --git a/src/backenddb/pg_select_otp_serial.c b/src/backenddb/pg_select_otp_serial.c new file mode 100644 index 00000000..c2011aad --- /dev/null +++ b/src/backenddb/pg_select_otp_serial.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_select_otp_serial.c + * @brief Implementation of the select_otp_serial function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_select_otp_serial.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_select_otp_serial (void *cls, + const char *instance_id, + const char *otp_id, + uint64_t *serial) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (otp_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("otp_serial", + serial), + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + PREPARE (pg, + "select_otp_serial", + "SELECT" + " otp_serial" + " FROM merchant_otp_devices" + " JOIN merchant_instances" + " USING (merchant_serial)" + " WHERE merchant_instances.merchant_id=$1" + " AND merchant_otp_devices.otp_id=$2"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "select_otp_serial", + params, + rs); +} diff --git a/src/backenddb/pg_select_otp_serial.h b/src/backenddb/pg_select_otp_serial.h new file mode 100644 index 00000000..46d128ae --- /dev/null +++ b/src/backenddb/pg_select_otp_serial.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_select_otp_serial.h + * @brief implementation of the select_otp_serial function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_OTP_SERIAL_H +#define PG_SELECT_OTP_SERIAL_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Lookup serial number of an OTP device. + * + * @param cls closure + * @param instance_id instance to lookup template for + * @param otp_id OTP device to lookup + * @param[out] serial set to the OTP device serial number * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_select_otp_serial (void *cls, + const char *instance_id, + const char *otp_id, + uint64_t *serial); + +#endif diff --git a/src/backenddb/pg_update_account.c b/src/backenddb/pg_update_account.c index 3e36596d..7458c095 100644 --- a/src/backenddb/pg_update_account.c +++ b/src/backenddb/pg_update_account.c @@ -30,19 +30,20 @@ enum GNUNET_DB_QueryStatus TMH_PG_update_account ( void *cls, const char *id, - const struct TALER_MERCHANTDB_AccountDetails *account_details) + const struct TALER_MerchantWireHashP *h_wire, + const char *credit_facade_url, + const json_t *credit_facade_credentials) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (id), - GNUNET_PQ_query_param_auto_from_type (&account_details->h_wire), - NULL ==account_details->credit_facade_url + GNUNET_PQ_query_param_auto_from_type (h_wire), + NULL == credit_facade_url ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (account_details->credit_facade_url), - NULL == account_details->credit_facade_credentials + : GNUNET_PQ_query_param_string (credit_facade_url), + NULL == credit_facade_credentials ? GNUNET_PQ_query_param_null () - : TALER_PQ_query_param_json (account_details->credit_facade_credentials), - GNUNET_PQ_query_param_bool (account_details->active), + : TALER_PQ_query_param_json (credit_facade_credentials), GNUNET_PQ_query_param_end }; @@ -52,7 +53,6 @@ TMH_PG_update_account ( "UPDATE merchant_accounts SET" " credit_facade_url=$3" ",credit_facade_credentials=COALESCE($4,credit_facade_credentials)" - ",active=$5" " WHERE h_wire=$2" " AND merchant_serial=" " (SELECT merchant_serial" diff --git a/src/backenddb/pg_update_account.h b/src/backenddb/pg_update_account.h index 52b476d9..794b99d8 100644 --- a/src/backenddb/pg_update_account.h +++ b/src/backenddb/pg_update_account.h @@ -31,14 +31,18 @@ * * @param cls closure * @param id identifier of the instance - * @param account_details details about the account + * @param h_wire which account to update + * @param credit_facade_url new facade URL, can be NULL + * @param credit_facade_credentials new credentials, can be NULL to keep previous credentials * @return database result code */ enum GNUNET_DB_QueryStatus TMH_PG_update_account ( void *cls, const char *id, - const struct TALER_MERCHANTDB_AccountDetails *account_details); + const struct TALER_MerchantWireHashP *h_wire, + const char *credit_facade_url, + const json_t *credit_facade_credentials); #endif diff --git a/src/backenddb/pg_update_instance.c b/src/backenddb/pg_update_instance.c index 0f44c833..228e2031 100644 --- a/src/backenddb/pg_update_instance.c +++ b/src/backenddb/pg_update_instance.c @@ -26,6 +26,7 @@ #include "pg_update_instance.h" #include "pg_helper.h" + enum GNUNET_DB_QueryStatus TMH_PG_update_instance (void *cls, const struct TALER_MERCHANTDB_InstanceSettings *is) @@ -40,7 +41,8 @@ TMH_PG_update_instance (void *cls, GNUNET_PQ_query_param_bool (is->use_stefan), GNUNET_PQ_query_param_relative_time ( &is->default_wire_transfer_delay), - GNUNET_PQ_query_param_relative_time (&is->default_pay_delay), + GNUNET_PQ_query_param_relative_time ( + &is->default_pay_delay), (NULL == is->website) ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (is->website), diff --git a/src/backenddb/pg_update_otp.c b/src/backenddb/pg_update_otp.c new file mode 100644 index 00000000..8f6c7176 --- /dev/null +++ b/src/backenddb/pg_update_otp.c @@ -0,0 +1,76 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_update_otp.c + * @brief Implementation of the update_otp function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_update_otp.h" +#include "pg_helper.h" + + +/** + * Update details about a particular OTP device. + * + * @param cls closure + * @param instance_id instance to update OTP device for + * @param otp_id OTP device to update + * @param td update to the OTP device details on success, can be NULL + * (in that case we only want to check if the template exists) + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template + * does not yet exist. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_update_otp (void *cls, + const char *instance_id, + const char *otp_id, + const struct TALER_MERCHANTDB_OtpDeviceDetails *td) +{ + struct PostgresClosure *pg = cls; + uint32_t pos32 = (uint32_t) td->otp_algorithm; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (otp_id), + GNUNET_PQ_query_param_string (td->otp_description), + GNUNET_PQ_query_param_uint32 (&pos32), + GNUNET_PQ_query_param_uint64 (&td->otp_ctr), + GNUNET_PQ_query_param_string (td->otp_key), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "update_otp", + "UPDATE merchant_otp_devices SET" + " otp_description=$3" + ",otp_algorithm=$4" + ",otp_ctr=$5" + ",otp_key=$6" + " WHERE merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND otp_id=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_otp", + params); +} + + diff --git a/src/backenddb/pg_update_otp.h b/src/backenddb/pg_update_otp.h new file mode 100644 index 00000000..7568608b --- /dev/null +++ b/src/backenddb/pg_update_otp.h @@ -0,0 +1,47 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_update_otp.h + * @brief implementation of the update_otp function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_UPDATE_OTP_H +#define PG_UPDATE_OTP_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Update details about a particular OTP device. + * + * @param cls closure + * @param instance_id instance to update OTP device for + * @param otp_id OTP device to update + * @param td update to the OTP device details on success, can be NULL + * (in that case we only want to check if the template exists) + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template + * does not yet exist. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_update_otp (void *cls, + const char *instance_id, + const char *otp_id, + const struct TALER_MERCHANTDB_OtpDeviceDetails *td); + + +#endif diff --git a/src/backenddb/pg_update_template.c b/src/backenddb/pg_update_template.c new file mode 100644 index 00000000..9f7f37c3 --- /dev/null +++ b/src/backenddb/pg_update_template.c @@ -0,0 +1,85 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_update_template.c + * @brief Implementation of the update_template function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_update_template.h" +#include "pg_helper.h" + + +/** + * Update details about a particular template. + * + * @param cls closure + * @param instance_id instance to update template for + * @param template_id template to update + * @param td update to the template details on success, can be NULL + * (in that case we only want to check if the template exists) + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template + * does not yet exist. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_update_template (void *cls, + const char *instance_id, + const char *template_id, + const struct TALER_MERCHANTDB_TemplateDetails *td) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (template_id), + GNUNET_PQ_query_param_string (td->template_description), + (NULL == td->otp_id) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (td->otp_id), + TALER_PQ_query_param_json (td->template_contract), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "update_template", + "WITH mid AS (" + " SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + ",otp AS (" + " SELECT otp_serial" + " FROM merchant_otp_devices" + " JOIN mid USING (merchant_serial)" + " WHERE otp_id=$4)" + "UPDATE merchant_template SET" + " template_description=$3" + ",otp_device_id=" + " COALESCE((SELECT otp_serial" + " FROM otp), NULL)" + ",template_contract=$5" + " WHERE merchant_serial=" + " (SELECT merchant_serial" + " FROM mid)" + " AND template_id=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_template", + params); +} + + diff --git a/src/backenddb/pg_update_template.h b/src/backenddb/pg_update_template.h new file mode 100644 index 00000000..26b932a2 --- /dev/null +++ b/src/backenddb/pg_update_template.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 backenddb/pg_update_template.h + * @brief implementation of the update_template function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_UPDATE_TEMPLATE_H +#define PG_UPDATE_TEMPLATE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Update details about a particular template. + * + * @param cls closure + * @param instance_id instance to update template for + * @param template_id template to update + * @param td update to the template details on success, can be NULL + * (in that case we only want to check if the template exists) + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template + * does not yet exist. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_update_template (void *cls, + const char *instance_id, + const char *template_id, + const struct TALER_MERCHANTDB_TemplateDetails *td); + +#endif diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 70a3e644..c4074c98 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -31,6 +31,11 @@ #include <taler/taler_mhd_lib.h> #include "taler_merchantdb_plugin.h" #include "pg_helper.h" +#include "pg_insert_otp.h" +#include "pg_delete_otp.h" +#include "pg_update_otp.h" +#include "pg_select_otp.h" +#include "pg_select_otp_serial.h" #include "pg_insert_account.h" #include "pg_update_account.h" #include "pg_lookup_instances.h" @@ -43,6 +48,7 @@ #include "pg_insert_exchange_account.h" #include "pg_lookup_reserves.h" #include "pg_lookup_instance_auth.h" +#include "pg_lookup_otp_devices.h" #include "pg_update_transfer_status.h" #include "pg_insert_instance.h" #include "pg_account_kyc_set_status.h" @@ -72,6 +78,11 @@ #include "pg_insert_contract_terms.h" #include "pg_update_contract_terms.h" #include "pg_delete_contract_terms.h" +#include "pg_delete_template.h" +#include "pg_insert_template.h" +#include "pg_update_template.h" +#include "pg_lookup_templates.h" +#include "pg_lookup_template.h" #include "pg_lookup_deposits.h" #include "pg_insert_exchange_signkey.h" #include "pg_insert_deposit.h" @@ -86,6 +97,8 @@ #include "pg_select_exchange_keys.h" #include "pg_insert_deposit_to_transfer.h" #include "pg_increase_refund.h" +#include "pg_select_account.h" +#include "pg_select_accounts.h" #include "pg_insert_transfer.h" #include "pg_insert_transfer_details.h" #include "pg_store_wire_fee_by_exchange.h" @@ -2309,283 +2322,6 @@ postgres_insert_pickup_blind_signature ( /** - * Delete information about a template. - * - * @param cls closure - * @param instance_id instance to delete template of - * @param template_id template to delete - * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - * if template unknown. - */ -static enum GNUNET_DB_QueryStatus -postgres_delete_template (void *cls, - const char *instance_id, - const char *template_id) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (template_id), - GNUNET_PQ_query_param_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "delete_template", - params); -} - - -/** - * Insert details about a particular template. - * - * @param cls closure - * @param instance_id instance to insert template for - * @param template_id template identifier of template to insert - * @param td the template details to insert - * @return database result code - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_template (void *cls, - const char *instance_id, - const char *template_id, - const struct TALER_MERCHANTDB_TemplateDetails *td) -{ - struct PostgresClosure *pg = cls; - uint32_t pos32 = (uint32_t) td->pos_algorithm; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (template_id), - GNUNET_PQ_query_param_string (td->template_description), - (NULL == td->pos_key) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (td->pos_key), - GNUNET_PQ_query_param_uint32 (&pos32), - TALER_PQ_query_param_json (td->template_contract), - GNUNET_PQ_query_param_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_template", - params); -} - - -/** - * Update details about a particular template. - * - * @param cls closure - * @param instance_id instance to update template for - * @param template_id template to update - * @param td update to the template details on success, can be NULL - * (in that case we only want to check if the template exists) - * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template - * does not yet exist. - */ -static enum GNUNET_DB_QueryStatus -postgres_update_template (void *cls, - const char *instance_id, - const char *template_id, - const struct TALER_MERCHANTDB_TemplateDetails *td) -{ - struct PostgresClosure *pg = cls; - uint32_t pos32 = (uint32_t) td->pos_algorithm; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (template_id), - GNUNET_PQ_query_param_string (td->template_description), - (NULL == td->pos_key) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (td->pos_key), - GNUNET_PQ_query_param_uint32 (&pos32), - TALER_PQ_query_param_json (td->template_contract), - GNUNET_PQ_query_param_end - }; - - - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_template", - params); -} - - -/** - * Context used for postgres_lookup_template(). - */ -struct LookupTemplateContext -{ - /** - * Function to call with the results. - */ - TALER_MERCHANTDB_TemplatesCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Did database result extraction fail? - */ - bool extract_failed; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results about template. - * - * @param[in,out] cls of type `struct LookupTemplateContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_templates_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupTemplateContext *tlc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - char *template_id; - char *template_description; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("template_id", - &template_id), - GNUNET_PQ_result_spec_string ("template_description", - &template_description), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - tlc->extract_failed = true; - return; - } - tlc->cb (tlc->cb_cls, - template_id, - template_description); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Lookup all of the templates the given instance has configured. - * - * @param cls closure - * @param instance_id instance to lookup template for - * @param cb function to call on all template found - * @param cb_cls closure for @a cb - * @return database result code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_templates (void *cls, - const char *instance_id, - TALER_MERCHANTDB_TemplatesCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct LookupTemplateContext tlc = { - .cb = cb, - .cb_cls = cb_cls, - /* Can be overwritten by the lookup_template_cb */ - .extract_failed = false, - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - check_connection (pg); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_templates", - params, - &lookup_templates_cb, - &tlc); - /* If there was an error inside lookup_template_cb, return a hard error. */ - if (tlc.extract_failed) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} - - -/** - * Lookup details about a particular template. - * - * @param cls closure - * @param instance_id instance to lookup template for - * @param template_id template to lookup - * @param[out] td set to the template details on success, can be NULL - * (in that case we only want to check if the template exists) - * @return database result code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_template (void *cls, - const char *instance_id, - const char *template_id, - struct TALER_MERCHANTDB_TemplateDetails *td) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (template_id), - GNUNET_PQ_query_param_end - }; - - if (NULL == td) - { - struct GNUNET_PQ_ResultSpec rs_null[] = { - GNUNET_PQ_result_spec_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_template", - params, - rs_null); - } - else - { - uint32_t pos32; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("template_description", - &td->template_description), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("pos_key", - &td->pos_key), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint32 ("pos_algorithm", - &pos32), - NULL), - TALER_PQ_result_spec_json ("template_contract", - &td->template_contract), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - check_connection (pg); - td->pos_key = NULL; - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_template", - params, - rs); - td->pos_algorithm = (enum TALER_MerchantConfirmationAlgorithm) pos32; - return qs; - } -} - - -/** * Delete information about a webhook. * * @param cls closure @@ -3747,62 +3483,6 @@ postgres_connect (void *cls) " pickup_serial, $2, $3" " FROM merchant_reward_pickups" " WHERE pickup_id=$1"), - /* for postgres_lookup_templates() */ - GNUNET_PQ_make_prepare ("lookup_templates", - "SELECT" - " template_id" - ",template_description" - " FROM merchant_template" - " JOIN merchant_instances" - " USING (merchant_serial)" - " WHERE merchant_instances.merchant_id=$1"), - /* for postgres_lookup_template() */ - GNUNET_PQ_make_prepare ("lookup_template", - "SELECT" - " template_description" - ",pos_key" - ",pos_algorithm" - ",template_contract" - " FROM merchant_template" - " JOIN merchant_instances" - " USING (merchant_serial)" - " WHERE merchant_instances.merchant_id=$1" - " AND merchant_template.template_id=$2"), - /* for postgres_delete_template() */ - GNUNET_PQ_make_prepare ("delete_template", - "DELETE" - " FROM merchant_template" - " WHERE merchant_template.merchant_serial=" - " (SELECT merchant_serial " - " FROM merchant_instances" - " WHERE merchant_id=$1)" - " AND merchant_template.template_id=$2"), - /* for postgres_insert_template() */ - GNUNET_PQ_make_prepare ("insert_template", - "INSERT INTO merchant_template" - "(merchant_serial" - ",template_id" - ",template_description" - ",pos_key" - ",pos_algorithm" - ",template_contract" - ")" - " SELECT merchant_serial," - " $2, $3, $4, $5, $6" - " FROM merchant_instances" - " WHERE merchant_id=$1"), - /* for postgres_update_template() */ - GNUNET_PQ_make_prepare ("update_template", - "UPDATE merchant_template SET" - " template_description=$3" - ",pos_key=$4" - ",pos_algorithm=$5" - ",template_contract=$6" - " WHERE merchant_serial=" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)" - " AND template_id=$2"), /* for postgres_lookup_webhooks() */ GNUNET_PQ_make_prepare ("lookup_webhooks", "SELECT" @@ -4010,6 +3690,18 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) = &TMH_PG_insert_instance; plugin->insert_account = &TMH_PG_insert_account; + plugin->lookup_otp_devices + = &TMH_PG_lookup_otp_devices; + plugin->delete_template + = &TMH_PG_delete_template; + plugin->insert_template + = &TMH_PG_insert_template; + plugin->update_template + = &TMH_PG_update_template; + plugin->lookup_templates + = &TMH_PG_lookup_templates; + plugin->lookup_template + = &TMH_PG_lookup_template; plugin->update_account = &TMH_PG_update_account; plugin->account_kyc_set_status @@ -4040,6 +3732,16 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) = &TMH_PG_insert_product; plugin->update_product = &TMH_PG_update_product; + plugin->insert_otp + = &TMH_PG_insert_otp; + plugin->delete_otp + = &TMH_PG_delete_otp; + plugin->update_otp + = &TMH_PG_update_otp; + plugin->select_otp + = &TMH_PG_select_otp; + plugin->select_otp_serial + = &TMH_PG_select_otp_serial; plugin->lock_product = &TMH_PG_lock_product; plugin->expire_locks @@ -4117,6 +3819,10 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) = &TMH_PG_update_wirewatch_progress; plugin->select_wirewatch_accounts = &TMH_PG_select_wirewatch_accounts; + plugin->select_account + = &TMH_PG_select_account; + plugin->select_accounts + = &TMH_PG_select_accounts; plugin->lookup_reserves = &TMH_PG_lookup_reserves; plugin->lookup_pending_reserves = &postgres_lookup_pending_reserves; @@ -4151,11 +3857,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) = &TMH_PG_authorize_reward; plugin->insert_pickup = &TMH_PG_insert_pickup; - plugin->lookup_templates = &postgres_lookup_templates; - plugin->lookup_template = &postgres_lookup_template; - plugin->delete_template = &postgres_delete_template; - plugin->insert_template = &postgres_insert_template; - plugin->update_template = &postgres_update_template; plugin->lookup_webhooks = &postgres_lookup_webhooks; plugin->lookup_webhook = &postgres_lookup_webhook; plugin->delete_webhook = &postgres_delete_webhook; diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c index 58470786..214bd5f8 100644 --- a/src/backenddb/test_merchantdb.c +++ b/src/backenddb/test_merchantdb.c @@ -259,6 +259,19 @@ check_accounts_equal (const struct TALER_MERCHANTDB_AccountDetails *a, } +// FIXME: use this! +void +lookup_accounts_cb (void *cls, + const struct TALER_MERCHANTDB_AccountDetails *account) +{ + const struct TALER_MERCHANTDB_AccountDetails *want = cls; + + GNUNET_assert (0 == + check_accounts_equal (want, + account)); +} + + /** * Called after testing 'lookup_instances'. * @@ -267,54 +280,33 @@ check_accounts_equal (const struct TALER_MERCHANTDB_AccountDetails *a, * @param merchant_priv private key of the instance, NULL if not available * @param is general instance settings * @param ias instance authentication settings - * @param accounts_length length of the @a accounts array - * @param accounts list of accounts of the merchant */ static void lookup_instances_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 TestLookupInstances_Closure *cmp = cls; + if (NULL == cmp) return; cmp->results_length += 1; /* Look through the closure and test each instance for equality */ for (unsigned int i = 0; cmp->instances_to_cmp_length > i; ++i) { - int accounts_matching[GNUNET_NZL (accounts_length)]; - bool accounts_match = true; if (0 != check_instances_equal (cmp->instances_to_cmp[i].instance, is)) continue; - if (accounts_length != cmp->instances_to_cmp[i].accounts_length) - continue; - /* Count matches between the accounts found and accounts in cls */ - for (unsigned int j = 0; accounts_length > j; ++j) - accounts_matching[j] = 0; - for (unsigned int j = 0; accounts_length > j; ++j) - { - for (unsigned int k = 0; accounts_length > k; ++k) - { - if (0 == check_accounts_equal (&cmp->instances_to_cmp[i].accounts[j], - &accounts[k])) - accounts_matching[j] += 1; - } - } - /* Each account from the lookup should match with one and only one from cls */ - for (unsigned int j = 0; accounts_length > j; ++j) - if (1 != accounts_matching[j]) - accounts_match = false; - if (true == accounts_match) - cmp->results_matching[i] += 1; + cmp->results_matching[i] += 1; } } + + + /** * Tests @e insert_instance. * @@ -6866,8 +6858,7 @@ make_template (const char *id, { template->id = id; template->template.template_description = "This is a test template"; - template->template.pos_key = NULL; - template->template.pos_algorithm = 0; + template->template.otp_id = NULL; template->template.template_contract = json_array (); GNUNET_assert (NULL != template->template.template_contract); } @@ -6881,7 +6872,7 @@ make_template (const char *id, static void free_template_data (struct TemplateData *template) { - GNUNET_free (template->template.pos_key); + GNUNET_free (template->template.otp_id); json_decref (template->template.template_contract); } @@ -6899,9 +6890,10 @@ check_templates_equal (const struct TALER_MERCHANTDB_TemplateDetails *a, { if ((0 != strcmp (a->template_description, b->template_description)) || - ( (NULL == a->pos_key) && (NULL != b->pos_key)) || - ( (NULL != a->pos_key) && (NULL == b->pos_key)) || - ( (NULL != a->pos_key) && (0 != strcmp (a->pos_key, b->pos_key))) || + ( (NULL == a->otp_id) && (NULL != b->otp_id)) || + ( (NULL != a->otp_id) && (NULL == b->otp_id)) || + ( (NULL != a->otp_id) && (0 != strcmp (a->otp_id, + b->otp_id))) || (1 != json_equal (a->template_contract, b->template_contract))) return 1; @@ -6967,6 +6959,7 @@ test_lookup_template (const struct InstanceData *instance, const struct TemplateData *template) { struct TALER_MERCHANTDB_TemplateDetails lookup_result; + if (0 > plugin->lookup_template (plugin->cls, instance->instance.id, template->id, @@ -7212,8 +7205,23 @@ run_test_templates (struct TestTemplates_Closure *cls) /* Test template update */ cls->templates[0].template.template_description = "This is a test template that has been updated!"; - GNUNET_free (cls->templates[0].template.pos_key); - cls->templates[0].template.pos_key = GNUNET_strdup ("pos_key"); + GNUNET_free (cls->templates[0].template.otp_id); + cls->templates[0].template.otp_id = GNUNET_strdup ("otp_id"); + { + /* ensure OTP device exists */ + struct TALER_MERCHANTDB_OtpDeviceDetails td = { + .otp_description = "my otp", + .otp_key = "my key", + .otp_algorithm = 1, + .otp_ctr = 42 + }; + GNUNET_assert (0 <= + plugin->insert_otp (plugin->cls, + cls->instance.instance.id, + "otp_id", + &td)); + } + GNUNET_assert (0 == json_array_append_new ( cls->templates[0].template.template_contract, |