From 36bbe89f13b18938d7b9cb05ce6e3399052aa24e Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Wed, 18 Oct 2023 20:54:48 -0600 Subject: Factor out 16 new functions (shit job) --- src/backenddb/Makefile.am | 16 + src/backenddb/pg_delete_pending_webhook.c | 48 + src/backenddb/pg_delete_pending_webhook.h | 40 + src/backenddb/pg_delete_reserve.c | 57 + src/backenddb/pg_delete_reserve.h | 42 + src/backenddb/pg_delete_webhook.c | 54 + src/backenddb/pg_delete_webhook.h | 42 + src/backenddb/pg_insert_pickup_blind_signature.c | 58 + src/backenddb/pg_insert_pickup_blind_signature.h | 46 + src/backenddb/pg_insert_webhook.c | 70 + src/backenddb/pg_insert_webhook.h | 43 + src/backenddb/pg_lookup_pending_reserves.c | 146 ++ src/backenddb/pg_lookup_pending_reserves.h | 41 + src/backenddb/pg_lookup_pickup.c | 174 +++ src/backenddb/pg_lookup_pickup.h | 52 + src/backenddb/pg_lookup_reserve.c | 241 ++++ src/backenddb/pg_lookup_reserve.h | 47 + src/backenddb/pg_lookup_reward.c | 84 ++ src/backenddb/pg_lookup_reward.h | 53 + src/backenddb/pg_lookup_reward_details.c | 208 +++ src/backenddb/pg_lookup_reward_details.h | 57 + src/backenddb/pg_lookup_rewards.c | 221 +++ src/backenddb/pg_lookup_rewards.h | 50 + src/backenddb/pg_lookup_webhook.c | 92 ++ src/backenddb/pg_lookup_webhook.h | 44 + src/backenddb/pg_lookup_webhook_by_event.c | 158 ++ src/backenddb/pg_lookup_webhook_by_event.h | 45 + src/backenddb/pg_lookup_webhooks.c | 133 ++ src/backenddb/pg_lookup_webhooks.h | 43 + src/backenddb/pg_purge_reserve.c | 54 + src/backenddb/pg_purge_reserve.h | 42 + src/backenddb/pg_update_webhook.c | 69 + src/backenddb/pg_update_webhook.h | 45 + src/backenddb/plugin_merchantdb_postgres.c | 1681 +--------------------- 34 files changed, 2663 insertions(+), 1633 deletions(-) create mode 100644 src/backenddb/pg_delete_pending_webhook.c create mode 100644 src/backenddb/pg_delete_pending_webhook.h create mode 100644 src/backenddb/pg_delete_reserve.c create mode 100644 src/backenddb/pg_delete_reserve.h create mode 100644 src/backenddb/pg_delete_webhook.c create mode 100644 src/backenddb/pg_delete_webhook.h create mode 100644 src/backenddb/pg_insert_pickup_blind_signature.c create mode 100644 src/backenddb/pg_insert_pickup_blind_signature.h create mode 100644 src/backenddb/pg_insert_webhook.c create mode 100644 src/backenddb/pg_insert_webhook.h create mode 100644 src/backenddb/pg_lookup_pending_reserves.c create mode 100644 src/backenddb/pg_lookup_pending_reserves.h create mode 100644 src/backenddb/pg_lookup_pickup.c create mode 100644 src/backenddb/pg_lookup_pickup.h create mode 100644 src/backenddb/pg_lookup_reserve.c create mode 100644 src/backenddb/pg_lookup_reserve.h create mode 100644 src/backenddb/pg_lookup_reward.c create mode 100644 src/backenddb/pg_lookup_reward.h create mode 100644 src/backenddb/pg_lookup_reward_details.c create mode 100644 src/backenddb/pg_lookup_reward_details.h create mode 100644 src/backenddb/pg_lookup_rewards.c create mode 100644 src/backenddb/pg_lookup_rewards.h create mode 100644 src/backenddb/pg_lookup_webhook.c create mode 100644 src/backenddb/pg_lookup_webhook.h create mode 100644 src/backenddb/pg_lookup_webhook_by_event.c create mode 100644 src/backenddb/pg_lookup_webhook_by_event.h create mode 100644 src/backenddb/pg_lookup_webhooks.c create mode 100644 src/backenddb/pg_lookup_webhooks.h create mode 100644 src/backenddb/pg_purge_reserve.c create mode 100644 src/backenddb/pg_purge_reserve.h create mode 100644 src/backenddb/pg_update_webhook.c create mode 100644 src/backenddb/pg_update_webhook.h (limited to 'src') diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am index ddf24df7..daa14832 100644 --- a/src/backenddb/Makefile.am +++ b/src/backenddb/Makefile.am @@ -147,6 +147,22 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \ pg_lookup_transfer.h pg_lookup_transfer.c \ pg_lookup_transfer_summary.h pg_lookup_transfer_summary.c \ pg_lookup_transfer_details.h pg_lookup_transfer_details.c \ + pg_lookup_pending_reserves.h pg_lookup_pending_reserves.c \ + pg_lookup_reserve.h pg_lookup_reserve.c \ + pg_delete_reserve.h pg_delete_reserve.c \ + pg_purge_reserve.h pg_purge_reserve.c \ + pg_lookup_pickup.h pg_lookup_pickup.c \ + pg_lookup_reward.h pg_lookup_reward.c \ + pg_lookup_rewards.h pg_lookup_rewards.c \ + pg_lookup_reward_details.h pg_lookup_reward_details.c \ + pg_insert_pickup_blind_signature.h pg_insert_pickup_blind_signature.c \ + pg_lookup_webhooks.h pg_lookup_webhooks.c \ + pg_lookup_webhook.h pg_lookup_webhook.c \ + pg_delete_webhook.h pg_delete_webhook.c \ + pg_insert_webhook.h pg_insert_webhook.c \ + pg_update_webhook.h pg_update_webhook.c \ + pg_lookup_webhook_by_event.h pg_lookup_webhook_by_event.c \ + pg_delete_pending_webhook.h pg_delete_pending_webhook.c \ plugin_merchantdb_postgres.c \ pg_helper.h pg_helper.c libtaler_plugin_merchantdb_postgres_la_LIBADD = \ diff --git a/src/backenddb/pg_delete_pending_webhook.c b/src/backenddb/pg_delete_pending_webhook.c new file mode 100644 index 00000000..9121fe41 --- /dev/null +++ b/src/backenddb/pg_delete_pending_webhook.c @@ -0,0 +1,48 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_delete_pending_webhook.c + * @brief Implementation of the delete_pending_webhook function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_delete_pending_webhook.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_delete_pending_webhook (void *cls, + uint64_t webhook_pending_serial) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&webhook_pending_serial), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "delete_pending_webhook", + "DELETE" + " FROM merchant_pending_webhooks" + " WHERE webhook_pending_serial=$1"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "delete_pending_webhook", + params); +} diff --git a/src/backenddb/pg_delete_pending_webhook.h b/src/backenddb/pg_delete_pending_webhook.h new file mode 100644 index 00000000..1247cf4e --- /dev/null +++ b/src/backenddb/pg_delete_pending_webhook.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_delete_pending_webhook.h + * @brief implementation of the delete_pending_webhook function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_DELETE_PENDING_WEBHOOK_H +#define PG_DELETE_PENDING_WEBHOOK_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Delete a webhook in the pending webhook after the + * webhook was completed successfully. + * + * @param cls closure + * @param webhook_pending_serial identifies the row that needs to be deleted in the pending webhook table + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_delete_pending_webhook (void *cls, + uint64_t webhook_pending_serial); + +#endif diff --git a/src/backenddb/pg_delete_reserve.c b/src/backenddb/pg_delete_reserve.c new file mode 100644 index 00000000..f31e7c7a --- /dev/null +++ b/src/backenddb/pg_delete_reserve.c @@ -0,0 +1,57 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_delete_reserve.c + * @brief Implementation of the delete_reserve function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_delete_reserve.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_delete_reserve (void *cls, + const char *instance_id, + const struct TALER_ReservePublicKeyP *reserve_pub) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "delete_reserve", + "DELETE" + " FROM merchant_reward_reserve_keys" + " WHERE reserve_serial=" + " (SELECT reserve_serial" + " FROM merchant_reward_reserves" + " WHERE reserve_pub=$2" + " AND merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1))"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "delete_reserve", + params); +} diff --git a/src/backenddb/pg_delete_reserve.h b/src/backenddb/pg_delete_reserve.h new file mode 100644 index 00000000..f3aa2403 --- /dev/null +++ b/src/backenddb/pg_delete_reserve.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_delete_reserve.h + * @brief implementation of the delete_reserve function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_DELETE_RESERVE_H +#define PG_DELETE_RESERVE_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Delete a reserve's private key. + * + * @param cls closure, typically a connection to the db + * @param instance_id which instance is the reserve tied to + * @param reserve_pub which reserve is to be deleted + * @return transaction status, usually + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success + */ +enum GNUNET_DB_QueryStatus +TMH_PG_delete_reserve (void *cls, + const char *instance_id, + const struct TALER_ReservePublicKeyP *reserve_pub); + +#endif diff --git a/src/backenddb/pg_delete_webhook.c b/src/backenddb/pg_delete_webhook.c new file mode 100644 index 00000000..ba2173cb --- /dev/null +++ b/src/backenddb/pg_delete_webhook.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_delete_webhook.c + * @brief Implementation of the delete_webhook function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_delete_webhook.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_delete_webhook (void *cls, + const char *instance_id, + const char *webhook_id) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (webhook_id), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "delete_webhook", + "DELETE" + " FROM merchant_webhook" + " WHERE merchant_webhook.merchant_serial=" + " (SELECT merchant_serial " + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND merchant_webhook.webhook_id=$2"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "delete_webhook", + params); +} diff --git a/src/backenddb/pg_delete_webhook.h b/src/backenddb/pg_delete_webhook.h new file mode 100644 index 00000000..02f021ab --- /dev/null +++ b/src/backenddb/pg_delete_webhook.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_delete_webhook.h + * @brief implementation of the delete_webhook function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_DELETE_WEBHOOK_H +#define PG_DELETE_WEBHOOK_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Delete information about a webhook. + * + * @param cls closure + * @param instance_id instance to delete webhook of + * @param webhook_id webhook to delete + * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + * if webhook unknown. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_delete_webhook (void *cls, + const char *instance_id, + const char *webhook_id); + +#endif diff --git a/src/backenddb/pg_insert_pickup_blind_signature.c b/src/backenddb/pg_insert_pickup_blind_signature.c new file mode 100644 index 00000000..89d51346 --- /dev/null +++ b/src/backenddb/pg_insert_pickup_blind_signature.c @@ -0,0 +1,58 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_insert_pickup_blind_signature.c + * @brief Implementation of the insert_pickup_blind_signature function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_insert_pickup_blind_signature.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_insert_pickup_blind_signature (void *cls, + const struct TALER_PickupIdentifierP *pickup_id, + uint32_t offset, + const struct TALER_BlindedDenominationSignature *blind_sig) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (pickup_id), + GNUNET_PQ_query_param_uint32 (&offset), + TALER_PQ_query_param_blinded_denom_sig (blind_sig), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "insert_pickup_blind_signature", + "INSERT INTO merchant_reward_pickup_signatures" + "(pickup_serial" + ",coin_offset" + ",blind_sig" + ") " + "SELECT" + " pickup_serial, $2, $3" + " FROM merchant_reward_pickups" + " WHERE pickup_id=$1"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_pickup_blind_signature", + params); +} diff --git a/src/backenddb/pg_insert_pickup_blind_signature.h b/src/backenddb/pg_insert_pickup_blind_signature.h new file mode 100644 index 00000000..a4f98275 --- /dev/null +++ b/src/backenddb/pg_insert_pickup_blind_signature.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_insert_pickup_blind_signature.h + * @brief implementation of the insert_pickup_blind_signature function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_INSERT_PICKUP_BLIND_SIGNATURE_H +#define PG_INSERT_PICKUP_BLIND_SIGNATURE_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Insert blind signature obtained from the exchange during a + * reward pickup operation. + * + * @param cls closure, typically a connection to the db + * @param pickup_id unique ID for the operation + * @param offset offset of the blind signature for the pickup + * @param blind_sig the blind signature + * @return transaction status, usually + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a credit_uuid already known + */ +enum GNUNET_DB_QueryStatus +TMH_PG_insert_pickup_blind_signature (void *cls, + const struct TALER_PickupIdentifierP *pickup_id, + uint32_t offset, + const struct TALER_BlindedDenominationSignature *blind_sig); + +#endif diff --git a/src/backenddb/pg_insert_webhook.c b/src/backenddb/pg_insert_webhook.c new file mode 100644 index 00000000..53049a43 --- /dev/null +++ b/src/backenddb/pg_insert_webhook.c @@ -0,0 +1,70 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_insert_webhook.c + * @brief Implementation of the insert_webhook function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_insert_webhook.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_insert_webhook (void *cls, + const char *instance_id, + const char *webhook_id, + const struct TALER_MERCHANTDB_WebhookDetails *wb) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (webhook_id), + GNUNET_PQ_query_param_string (wb->event_type), + GNUNET_PQ_query_param_string (wb->url), + GNUNET_PQ_query_param_string (wb->http_method), + (NULL == wb->header_template) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (wb->header_template), + (NULL == wb->body_template) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (wb->body_template), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "insert_webhook", + "INSERT INTO merchant_webhook" + "(merchant_serial" + ",webhook_id" + ",event_type" + ",url" + ",http_method" + ",header_template" + ",body_template" + ")" + " SELECT merchant_serial," + " $2, $3, $4, $5, $6, $7" + " FROM merchant_instances" + " WHERE merchant_id=$1"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_webhook", + params); +} diff --git a/src/backenddb/pg_insert_webhook.h b/src/backenddb/pg_insert_webhook.h new file mode 100644 index 00000000..fe89d113 --- /dev/null +++ b/src/backenddb/pg_insert_webhook.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_insert_webhook.h + * @brief implementation of the insert_webhook function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_INSERT_WEBHOOK_H +#define PG_INSERT_WEBHOOK_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Insert details about a particular webhook. + * + * @param cls closure + * @param instance_id instance to insert webhook for + * @param webhook_id webhook identifier of webhook to insert + * @param wb the webhook details to insert + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_insert_webhook (void *cls, + const char *instance_id, + const char *webhook_id, + const struct TALER_MERCHANTDB_WebhookDetails *wb); + +#endif diff --git a/src/backenddb/pg_lookup_pending_reserves.c b/src/backenddb/pg_lookup_pending_reserves.c new file mode 100644 index 00000000..f35021c6 --- /dev/null +++ b/src/backenddb/pg_lookup_pending_reserves.c @@ -0,0 +1,146 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_pending_reserves.c + * @brief Implementation of the lookup_pending_reserves function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_pending_reserves.h" +#include "pg_helper.h" + +/** + * Closure for #lookup_pending_reserves_cb. + */ +struct LookupPendingReservesContext +{ + /** + * Postgres context. + */ + struct PostgresClosure *pg; + + /** + * Function to call with the results + */ + TALER_MERCHANTDB_PendingReservesCallback cb; + + /** + * Closure for @e cb + */ + void *cb_cls; + + /** + * Set in case of 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[in,out] cls of type `struct LookupReservesContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_pending_reserves_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupPendingReservesContext *lrc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_Amount merchant_initial_balance; + char *exchange_url; + char *instance_id; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + &reserve_pub), + GNUNET_PQ_result_spec_string ("merchant_id", + &instance_id), + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), + TALER_PQ_result_spec_amount_with_currency ("merchant_initial_balance", + &merchant_initial_balance), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + lrc->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + lrc->cb (lrc->cb_cls, + instance_id, + exchange_url, + &reserve_pub, + &merchant_initial_balance); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_pending_reserves (void *cls, + TALER_MERCHANTDB_PendingReservesCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct LookupPendingReservesContext lrc = { + .pg = pg, + .cb = cb, + .cb_cls = cb_cls + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "lookup_pending_reserves", + "SELECT" + " reserve_pub" + ",merchant_id" + ",exchange_url" + ",merchant_initial_balance" + " FROM merchant_reward_reserves mrr" + " JOIN merchant_instances USING (merchant_serial)" + " JOIN merchant_reward_reserve_keys USING (reserve_serial)" + " WHERE (mrr.exchange_initial_balance).val=0" + " AND (mrr.exchange_initial_balance).frac=0"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_pending_reserves", + params, + &lookup_pending_reserves_cb, + &lrc); + if (lrc.qs < 0) + return lrc.qs; + return qs; +} diff --git a/src/backenddb/pg_lookup_pending_reserves.h b/src/backenddb/pg_lookup_pending_reserves.h new file mode 100644 index 00000000..4ffff78f --- /dev/null +++ b/src/backenddb/pg_lookup_pending_reserves.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_pending_reserves.h + * @brief implementation of the lookup_pending_reserves function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_PENDING_RESERVES_H +#define PG_LOOKUP_PENDING_RESERVES_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup reserves pending activation across all instances. + * + * @param cls closure + * @param cb function to call with reserve summary data + * @param cb_cls closure for @a cb + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_pending_reserves (void *cls, + TALER_MERCHANTDB_PendingReservesCallback cb, + void *cb_cls); + +#endif diff --git a/src/backenddb/pg_lookup_pickup.c b/src/backenddb/pg_lookup_pickup.c new file mode 100644 index 00000000..f10b948b --- /dev/null +++ b/src/backenddb/pg_lookup_pickup.c @@ -0,0 +1,174 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_pickup.c + * @brief Implementation of the lookup_pickup function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_pickup.h" +#include "pg_helper.h" + +/** + * Closure for #lookup_signatures_cb(). + */ +struct LookupSignaturesContext +{ + /** + * Length of the @e sigs array + */ + unsigned int sigs_length; + + /** + * Where to store the signatures. + */ + struct TALER_BlindedDenominationSignature *sigs; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results about accounts. + * + * @param[in,out] cls of type `struct LookupSignaturesContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_signatures_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupSignaturesContext *lsc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint32_t offset; + struct TALER_BlindedDenominationSignature bsig; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint32 ("coin_offset", + &offset), + TALER_PQ_result_spec_blinded_denom_sig ("blind_sig", + &bsig), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + return; + } + if (offset >= lsc->sigs_length) + { + GNUNET_break_op (0); + GNUNET_PQ_cleanup_result (rs); + continue; + } + /* Must be NULL due to UNIQUE constraint on offset and + requirement that client launched us with 'sigs' + pre-initialized to NULL. */ + lsc->sigs[offset] = bsig; + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_pickup (void *cls, + const char *instance_id, + const struct TALER_RewardIdentifierP *reward_id, + const struct TALER_PickupIdentifierP *pickup_id, + char **exchange_url, + struct TALER_ReservePrivateKeyP *reserve_priv, + unsigned int sigs_length, + struct TALER_BlindedDenominationSignature sigs[]) +{ + struct PostgresClosure *pg = cls; + uint64_t pickup_serial; + + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_auto_from_type (reward_id), + GNUNET_PQ_query_param_auto_from_type (pickup_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("exchange_url", + exchange_url), + GNUNET_PQ_result_spec_auto_from_type ("reserve_priv", + reserve_priv), + GNUNET_PQ_result_spec_uint64 ("pickup_serial", + &pickup_serial), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "lookup_pickup", + "SELECT" + " exchange_url" + ",reserve_priv" + ",pickup_serial" + " FROM merchant_reward_pickups" + " JOIN merchant_rewards USING (reward_serial)" + " JOIN merchant_reward_reserves USING (reserve_serial)" + " JOIN merchant_reward_reserve_keys USING (reserve_serial)" + " WHERE pickup_id = $3" + " AND reward_id = $2" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_pickup", + params, + rs); + if (qs <= 0) + return qs; + } + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&pickup_serial), + GNUNET_PQ_query_param_end + }; + struct LookupSignaturesContext lsc = { + .sigs_length = sigs_length, + .sigs = sigs + }; + + PREPARE (pg, + "lookup_pickup_signatures", + "SELECT" + " coin_offset" + ",blind_sig" + " FROM merchant_reward_pickup_signatures" + " WHERE pickup_serial = $1"); + + return GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_pickup_signatures", + params, + &lookup_signatures_cb, + &lsc); + } +} diff --git a/src/backenddb/pg_lookup_pickup.h b/src/backenddb/pg_lookup_pickup.h new file mode 100644 index 00000000..b3814731 --- /dev/null +++ b/src/backenddb/pg_lookup_pickup.h @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_pickup.h + * @brief implementation of the lookup_pickup function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_PICKUP_H +#define PG_LOOKUP_PICKUP_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup pickup details for pickup @a pickup_id. + * + * @param cls closure, typically a connection to the db + * @param instance_id which instance should we lookup reward details for + * @param reward_id which reward should we lookup details on + * @param pickup_id which pickup should we lookup details on + * @param[out] exchange_url which exchange is the reward withdrawn from + * @param[out] reserve_priv private key the reward is withdrawn from (set if still available!) + * @param sigs_length length of the @a sigs array + * @param[out] sigs set to the (blind) signatures we have for this @a pickup_id, + * those that are unavailable are left at NULL + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_pickup (void *cls, + const char *instance_id, + const struct TALER_RewardIdentifierP *reward_id, + const struct TALER_PickupIdentifierP *pickup_id, + char **exchange_url, + struct TALER_ReservePrivateKeyP *reserve_priv, + unsigned int sigs_length, + struct TALER_BlindedDenominationSignature sigs[]); + +#endif diff --git a/src/backenddb/pg_lookup_reserve.c b/src/backenddb/pg_lookup_reserve.c new file mode 100644 index 00000000..392db057 --- /dev/null +++ b/src/backenddb/pg_lookup_reserve.c @@ -0,0 +1,241 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_reserve.c + * @brief Implementation of the lookup_reserve function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_reserve.h" +#include "pg_helper.h" + +/** + * Closure for #lookup_reserve_rewards_cb(). + */ +struct LookupRewardsContext +{ + /** + * Postgres context. + */ + struct PostgresClosure *pg; + + /** + * Array with information about rewards generated from this reserve. + */ + struct TALER_MERCHANTDB_RewardDetails *rewards; + + /** + * Length of the @e rewards array. + */ + unsigned int rewards_length; + + /** + * Set in case of 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[in,out] cls of type `struct LookupRewardsContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_reserve_rewards_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRewardsContext *ltc = cls; + + GNUNET_array_grow (ltc->rewards, + ltc->rewards_length, + num_results); + for (unsigned int i = 0; i < num_results; i++) + { + struct TALER_MERCHANTDB_RewardDetails *td = <c->rewards[i]; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("justification", + &td->reason), + GNUNET_PQ_result_spec_auto_from_type ("reward_id", + &td->reward_id), + TALER_PQ_result_spec_amount_with_currency ("amount", + &td->total_amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ltc->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_reserve (void *cls, + const char *instance_id, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool fetch_rewards, + TALER_MERCHANTDB_ReserveDetailsCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct LookupRewardsContext ltc = { + .pg = pg, + .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_TIME_Timestamp creation_time; + struct GNUNET_TIME_Timestamp expiration_time; + struct TALER_Amount merchant_initial_balance; + struct TALER_Amount exchange_initial_balance; + struct TALER_Amount pickup_amount; + struct TALER_Amount committed_amount; + struct TALER_MasterPublicKeyP master_pub; + bool active; + char *exchange_url = NULL; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_timestamp ("creation_time", + &creation_time), + GNUNET_PQ_result_spec_timestamp ("expiration", + &expiration_time), + TALER_PQ_result_spec_amount_with_currency ("merchant_initial_balance", + &merchant_initial_balance), + TALER_PQ_result_spec_amount_with_currency ("exchange_initial_balance", + &exchange_initial_balance), + TALER_PQ_result_spec_amount_with_currency ("rewards_picked_up", + &pickup_amount), + TALER_PQ_result_spec_amount_with_currency ("rewards_committed", + &committed_amount), + GNUNET_PQ_result_spec_auto_from_type ("master_pub", + &master_pub), + GNUNET_PQ_result_spec_bool ("active", + &active), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), + NULL), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "lookup_reserve", + "SELECT" + " creation_time" + ",expiration" + ",merchant_initial_balance" + ",exchange_initial_balance" + ",rewards_committed" + ",rewards_picked_up" + ",reserve_priv IS NOT NULL AS active" + ",exchange_url" + ",master_pub" + " FROM merchant_reward_reserves" + " FULL OUTER JOIN merchant_reward_reserve_keys USING (reserve_serial)" + " WHERE reserve_pub = $2" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_reserve", + params, + rs); + if (qs < 0) + return qs; + if (! fetch_rewards) + { + cb (cb_cls, + creation_time, + expiration_time, + &merchant_initial_balance, + &exchange_initial_balance, + &pickup_amount, + &committed_amount, + active, + &master_pub, + exchange_url, + 0, + NULL); + GNUNET_PQ_cleanup_result (rs); + return qs; + } + + PREPARE (pg, + "lookup_reserve_rewards", + "SELECT" + " justification" + ",reward_id" + ",amount" + " FROM merchant_rewards" + " WHERE reserve_serial =" + " (SELECT reserve_serial" + " FROM merchant_reward_reserves" + " WHERE reserve_pub=$2" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1))"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_reserve_rewards", + params, + &lookup_reserve_rewards_cb, + <c); + if (qs < 0) + return qs; + if (ltc.qs >= 0) + { + cb (cb_cls, + creation_time, + expiration_time, + &merchant_initial_balance, + &exchange_initial_balance, + &pickup_amount, + &committed_amount, + active, + &master_pub, + exchange_url, + ltc.rewards_length, + ltc.rewards); + } + for (unsigned int i = 0; i + */ +/** + * @file backenddb/pg_lookup_reserve.h + * @brief implementation of the lookup_reserve function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_RESERVE_H +#define PG_LOOKUP_RESERVE_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup reserve details. + * + * @param cls closure + * @param instance_id instance to lookup payments for + * @param reserve_pub public key of the reserve to inspect + * @param fetch_rewards if true, also return information about rewards + * @param cb function to call with reserve summary data + * @param cb_cls closure for @a cb + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_reserve (void *cls, + const char *instance_id, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool fetch_rewards, + TALER_MERCHANTDB_ReserveDetailsCallback cb, + void *cb_cls); + +#endif diff --git a/src/backenddb/pg_lookup_reward.c b/src/backenddb/pg_lookup_reward.c new file mode 100644 index 00000000..cb887586 --- /dev/null +++ b/src/backenddb/pg_lookup_reward.c @@ -0,0 +1,84 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_reward.c + * @brief Implementation of the lookup_reward function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_reward.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_reward (void *cls, + const char *instance_id, + const struct TALER_RewardIdentifierP *reward_id, + struct TALER_Amount *total_authorized, + struct TALER_Amount *total_picked_up, + struct GNUNET_TIME_Timestamp *expiration, + char **exchange_url, + char **next_url, + struct TALER_ReservePrivateKeyP *reserve_priv) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_auto_from_type (reward_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_amount_with_currency ("amount", + total_authorized), + TALER_PQ_result_spec_amount_with_currency ("picked_up", + total_picked_up), + GNUNET_PQ_result_spec_timestamp ("expiration", + expiration), + GNUNET_PQ_result_spec_string ("exchange_url", + exchange_url), + GNUNET_PQ_result_spec_string ("next_url", + next_url), + GNUNET_PQ_result_spec_auto_from_type ("reserve_priv", + reserve_priv), + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + PREPARE (pg, + "lookup_reward", + "SELECT" + " amount" + ",picked_up" + ",merchant_rewards.expiration" + ",exchange_url" + ",next_url" + ",reserve_priv" + " FROM merchant_rewards" + " JOIN merchant_reward_reserves USING (reserve_serial)" + " JOIN merchant_reward_reserve_keys USING (reserve_serial)" + " WHERE reward_id = $2" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)"); + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_reward", + params, + rs); +} diff --git a/src/backenddb/pg_lookup_reward.h b/src/backenddb/pg_lookup_reward.h new file mode 100644 index 00000000..fc23c9ea --- /dev/null +++ b/src/backenddb/pg_lookup_reward.h @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_reward.h + * @brief implementation of the lookup_reward function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_REWARD_H +#define PG_LOOKUP_REWARD_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup reward details for reward @a reward_id. + * + * @param cls closure, typically a connection to the db + * @param instance_id which instance should we lookup reward details for + * @param reward_id which reward should we lookup details on + * @param[out] total_authorized amount how high is the reward (with fees) + * @param[out] total_picked_up how much of the reward was so far picked up (with fees) + * @param[out] expiration set to when the reward expires + * @param[out] exchange_url set to the exchange URL where the reserve is + * @param[out] next_url set to the URL where the wallet should navigate after getting the reward + * @param[out] reserve_priv set to private key of reserve to be debited + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_reward (void *cls, + const char *instance_id, + const struct TALER_RewardIdentifierP *reward_id, + struct TALER_Amount *total_authorized, + struct TALER_Amount *total_picked_up, + struct GNUNET_TIME_Timestamp *expiration, + char **exchange_url, + char **next_url, + struct TALER_ReservePrivateKeyP *reserve_priv); + +#endif diff --git a/src/backenddb/pg_lookup_reward_details.c b/src/backenddb/pg_lookup_reward_details.c new file mode 100644 index 00000000..062fbdd4 --- /dev/null +++ b/src/backenddb/pg_lookup_reward_details.c @@ -0,0 +1,208 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_reward_details.c + * @brief Implementation of the lookup_reward_details function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_reward_details.h" +#include "pg_helper.h" + +/** + * Closure for #lookup_pickup_details_cb(). + */ +struct LookupRewardDetailsContext +{ + /** + * Length of the @e sigs array + */ + unsigned int *pickups_length; + + /** + * Where to store the signatures. + */ + struct TALER_MERCHANTDB_PickupDetails **pickups; + + /** + * Database handle. + */ + struct PostgresClosure *pg; + + /** + * Transaction status. + */ + enum GNUNET_DB_QueryStatus qs; + +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results about pickups. + * + * @param[in,out] cls of type `struct LookupRewardDetailsContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_pickup_details_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRewardDetailsContext *ltdc = cls; + + *ltdc->pickups_length = num_results; + *ltdc->pickups = GNUNET_new_array (num_results, + struct TALER_MERCHANTDB_PickupDetails); + for (unsigned int i = 0; i < num_results; i++) + { + struct TALER_MERCHANTDB_PickupDetails *pd = &((*ltdc->pickups)[i]); + uint64_t num_planchets = 0; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("pickup_id", + &pd->pickup_id), + TALER_PQ_result_spec_amount_with_currency ("amount", + &pd->requested_amount), + GNUNET_PQ_result_spec_uint64 ("num_planchets", + &num_planchets), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ltdc->qs = GNUNET_DB_STATUS_HARD_ERROR; + GNUNET_array_grow (*ltdc->pickups, + *ltdc->pickups_length, + 0); + return; + } + + pd->num_planchets = num_planchets; + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_reward_details (void *cls, + const char *instance_id, + const struct TALER_RewardIdentifierP *reward_id, + bool fpu, + struct TALER_Amount *total_authorized, + struct TALER_Amount *total_picked_up, + char **justification, + struct GNUNET_TIME_Timestamp *expiration, + struct TALER_ReservePublicKeyP *reserve_pub, + unsigned int *pickups_length, + struct TALER_MERCHANTDB_PickupDetails **pickups) +{ + struct PostgresClosure *pg = cls; + uint64_t reward_serial; + enum GNUNET_DB_QueryStatus qs; + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_auto_from_type (reward_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("reward_serial", + &reward_serial), + TALER_PQ_result_spec_amount_with_currency ("amount", + total_authorized), + TALER_PQ_result_spec_amount_with_currency ("picked_up", + total_picked_up), + GNUNET_PQ_result_spec_string ("justification", + justification), + GNUNET_PQ_result_spec_timestamp ("expiration", + expiration), + GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", + reserve_pub), + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + PREPARE (pg, + "lookup_reward_details", + "SELECT" + " reward_serial" + ",amount" + ",picked_up" + ",justification" + ",merchant_rewards.expiration" + ",reserve_pub" + " FROM merchant_rewards" + " JOIN merchant_reward_reserves USING (reserve_serial)" + " WHERE reward_id = $2" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)"); + + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_reward_details", + params, + rs); + if (qs <= 0) + return qs; + if (! fpu) + { + *pickups_length = 0; + *pickups = NULL; + return qs; + } + } + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&reward_serial), + GNUNET_PQ_query_param_end + }; + + struct LookupRewardDetailsContext ltdc = { + .pickups_length = pickups_length, + .pickups = pickups, + .pg = pg, + .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT + }; + + PREPARE (pg, + "lookup_pickup_details", + "SELECT" + " pickup_id" + ",amount" + ",COUNT(blind_sig) AS num_planchets" + " FROM merchant_reward_pickups" + " JOIN merchant_reward_pickup_signatures USING (pickup_serial)" + " WHERE reward_serial = $1" + " GROUP BY pickup_serial"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_pickup_details", + params, + &lookup_pickup_details_cb, + <dc); + if (qs < 0) + return qs; + return ltdc.qs; + } +} diff --git a/src/backenddb/pg_lookup_reward_details.h b/src/backenddb/pg_lookup_reward_details.h new file mode 100644 index 00000000..61ff301f --- /dev/null +++ b/src/backenddb/pg_lookup_reward_details.h @@ -0,0 +1,57 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_reward_details.h + * @brief implementation of the lookup_reward_details function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_REWARD_DETAILS_H +#define PG_LOOKUP_REWARD_DETAILS_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup reward details for reward @a reward_id. + * + * @param cls closure, typically a connection to the db + * @param instance_id which instance should we lookup reward details for + * @param reward_id which reward should we lookup details on + * @param fpu should we fetch details about individual pickups + * @param[out] total_authorized amount how high is the reward (with fees) + * @param[out] total_picked_up how much of the reward was so far picked up (with fees) + * @param[out] justification why was the reward approved + * @param[out] expiration set to when the reward expires + * @param[out] reserve_pub set to which reserve is debited + * @param[out] pickups_length set to the length of @e pickups + * @param[out] pickups if @a fpu is true, set to details about the pickup operations + * @return transaction status, + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_reward_details (void *cls, + const char *instance_id, + const struct TALER_RewardIdentifierP *reward_id, + bool fpu, + struct TALER_Amount *total_authorized, + struct TALER_Amount *total_picked_up, + char **justification, + struct GNUNET_TIME_Timestamp *expiration, + struct TALER_ReservePublicKeyP *reserve_pub, + unsigned int *pickups_length, + struct TALER_MERCHANTDB_PickupDetails **pickups); + +#endif diff --git a/src/backenddb/pg_lookup_rewards.c b/src/backenddb/pg_lookup_rewards.c new file mode 100644 index 00000000..4914ad58 --- /dev/null +++ b/src/backenddb/pg_lookup_rewards.c @@ -0,0 +1,221 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_rewards.c + * @brief Implementation of the lookup_rewards function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_rewards.h" +#include "pg_helper.h" + +/** + * Context used for postgres_lookup_rewards(). + */ +struct LookupMerchantRewardsContext +{ + /** + * Postgres context. + */ + struct PostgresClosure *pg; + + /** + * Function to call with the results. + */ + TALER_MERCHANTDB_RewardsCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Internal result. + */ + enum GNUNET_DB_QueryStatus qs; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results about rewards. + * + * @param[in,out] cls of type `struct LookupRewardsContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_rewards_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupMerchantRewardsContext *plc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint64_t row_id; + struct TALER_RewardIdentifierP reward_id; + struct TALER_Amount reward_amount; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("reward_serial", + &row_id), + GNUNET_PQ_result_spec_auto_from_type ("reward_id", + &reward_id), + TALER_PQ_result_spec_amount_with_currency ("amount", + &reward_amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + plc->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + plc->cb (plc->cb_cls, + row_id, + reward_id, + reward_amount); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_rewards (void *cls, + const char *instance_id, + enum TALER_EXCHANGE_YesNoAll expired, + int64_t limit, + uint64_t offset, + TALER_MERCHANTDB_RewardsCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct LookupMerchantRewardsContext plc = { + .pg = pg, + .cb = cb, + .cb_cls = cb_cls + }; + uint64_t ulimit = (limit > 0) ? limit : -limit; + uint8_t bexpired; + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_uint64 (&ulimit), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_auto_from_type (&bexpired), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + char stmt[128]; + + bexpired = (TALER_EXCHANGE_YNA_YES == expired); + GNUNET_snprintf (stmt, + sizeof (stmt), + "lookup_rewards_%s%s", + (limit > 0) ? "inc" : "dec", + (TALER_EXCHANGE_YNA_ALL == expired) ? "" : "_expired"); + + check_connection (pg); + PREPARE (pg, + "lookup_rewards_inc", + "SELECT" + " reward_serial" + ",reward_id" + ",amount" + ",CAST($4 as BIGINT)" /* otherwise $4 is unused and Postgres unhappy */ + ",CAST($5 as BOOL)" /* otherwise $5 is unused and Postgres unhappy */ + " FROM merchant_rewards" + " JOIN merchant_reward_reserves USING (reserve_serial)" + " WHERE merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND" + " reward_serial > $3" + " ORDER BY reward_serial ASC" + " LIMIT $2"); + PREPARE (pg, + "lookup_rewards_dec", + "SELECT" + " reward_serial" + ",reward_id" + ",amount" + ",CAST($4 as BIGINT)" /* otherwise $4 is unused and Postgres unhappy */ + ",CAST($5 as BOOL)" /* otherwise $5 is unused and Postgres unhappy */ + " FROM merchant_rewards" + " JOIN merchant_reward_reserves USING (reserve_serial)" + " WHERE merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND" + " reward_serial < $3" + " ORDER BY reward_serial DESC" + " LIMIT $2"); + PREPARE (pg, + "lookup_rewards_inc_expired", + "SELECT" + " reward_serial" + ",reward_id" + ",amount" + " FROM merchant_rewards" + " JOIN merchant_reward_reserves USING (reserve_serial)" + " WHERE merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND" + " reward_serial > $3" + " AND" + " CAST($5 as BOOL) = (merchant_rewards.expiration < $4)" + " ORDER BY reward_serial ASC" + " LIMIT $2"); + PREPARE (pg, + "lookup_rewards_dec_expired", + "SELECT" + " reward_serial" + ",reward_id" + ",amount" + " FROM merchant_rewards" + " JOIN merchant_reward_reserves USING (reserve_serial)" + " WHERE merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND" + " reward_serial < $3" + " AND" + " CAST($5 as BOOL) = (merchant_rewards.expiration < $4)" + " ORDER BY reward_serial DESC" + " LIMIT $2"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + stmt, + params, + &lookup_rewards_cb, + &plc); + if (0 != plc.qs) + return plc.qs; + return qs; +} diff --git a/src/backenddb/pg_lookup_rewards.h b/src/backenddb/pg_lookup_rewards.h new file mode 100644 index 00000000..a4fc61ec --- /dev/null +++ b/src/backenddb/pg_lookup_rewards.h @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_rewards.h + * @brief implementation of the lookup_rewards function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_REWARDS_H +#define PG_LOOKUP_REWARDS_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup rewards + * + * @param cls closure, typically a connection to the db + * @param instance_id which instance should we lookup rewards for + * @param expired should we include expired rewards? + * @param limit maximum number of results to return, positive for + * ascending row id, negative for descending + * @param offset row id to start returning results from + * @param cb function to call with reward data + * @param cb_cls closure for @a cb + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_rewards (void *cls, + const char *instance_id, + enum TALER_EXCHANGE_YesNoAll expired, + int64_t limit, + uint64_t offset, + TALER_MERCHANTDB_RewardsCallback cb, + void *cb_cls); + +#endif diff --git a/src/backenddb/pg_lookup_webhook.c b/src/backenddb/pg_lookup_webhook.c new file mode 100644 index 00000000..3dcf396c --- /dev/null +++ b/src/backenddb/pg_lookup_webhook.c @@ -0,0 +1,92 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_webhook.c + * @brief Implementation of the lookup_webhook function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_webhook.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_webhook (void *cls, + const char *instance_id, + const char *webhook_id, + struct TALER_MERCHANTDB_WebhookDetails *wb) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (webhook_id), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "lookup_webhook", + "SELECT" + " event_type" + ",url" + ",http_method" + ",header_template" + ",body_template" + " FROM merchant_webhook" + " JOIN merchant_instances" + " USING (merchant_serial)" + " WHERE merchant_instances.merchant_id=$1" + " AND merchant_webhook.webhook_id=$2"); + + if (NULL == wb) + { + struct GNUNET_PQ_ResultSpec rs_null[] = { + GNUNET_PQ_result_spec_end + }; + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_webhook", + params, + rs_null); + } + else + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("event_type", + &wb->event_type), + GNUNET_PQ_result_spec_string ("url", + &wb->url), + GNUNET_PQ_result_spec_string ("http_method", + &wb->http_method), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("header_template", + &wb->header_template), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("body_template", + &wb->body_template), + NULL), + GNUNET_PQ_result_spec_end + }; + + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_webhook", + params, + rs); + } +} diff --git a/src/backenddb/pg_lookup_webhook.h b/src/backenddb/pg_lookup_webhook.h new file mode 100644 index 00000000..d39828f1 --- /dev/null +++ b/src/backenddb/pg_lookup_webhook.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_webhook.h + * @brief implementation of the lookup_webhook function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_WEBHOOK_H +#define PG_LOOKUP_WEBHOOK_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup details about a particular webhook. + * + * @param cls closure + * @param instance_id instance to lookup webhook for + * @param webhook_id webhook to lookup + * @param[out] wb set to the webhook details on success, can be NULL + * (in that case we only want to check if the webhook exists) + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_webhook (void *cls, + const char *instance_id, + const char *webhook_id, + struct TALER_MERCHANTDB_WebhookDetails *wb); + +#endif diff --git a/src/backenddb/pg_lookup_webhook_by_event.c b/src/backenddb/pg_lookup_webhook_by_event.c new file mode 100644 index 00000000..97960bbe --- /dev/null +++ b/src/backenddb/pg_lookup_webhook_by_event.c @@ -0,0 +1,158 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_webhook_by_event.c + * @brief Implementation of the lookup_webhook_by_event function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_webhook_by_event.h" +#include "pg_helper.h" + +/** + * Context used for lookup_webhook_by_event_cb(). + */ +struct LookupWebhookDetailContext +{ + /** + * Function to call with the results. + */ + TALER_MERCHANTDB_WebhookDetailCallback 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 webhook. + * + * @param[in,out] cls of type `struct LookupPendingWebhookContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_webhook_by_event_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupWebhookDetailContext *wlc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint64_t webhook_serial; + char *event_type; + char *url; + char *http_method; + char *header_template; + char *body_template; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("webhook_serial", + &webhook_serial), + GNUNET_PQ_result_spec_string ("event_type", + &event_type), + GNUNET_PQ_result_spec_string ("url", + &url), + GNUNET_PQ_result_spec_string ("http_method", + &http_method), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("header_template", + &header_template), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("body_template", + &body_template), + NULL), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + wlc->extract_failed = true; + return; + } + wlc->cb (wlc->cb_cls, + webhook_serial, + event_type, + url, + http_method, + header_template, + body_template); + GNUNET_PQ_cleanup_result (rs); + } +} + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_webhook_by_event (void *cls, + const char *instance_id, + const char *event_type, + TALER_MERCHANTDB_WebhookDetailCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct LookupWebhookDetailContext wlc = { + .cb = cb, + .cb_cls = cb_cls, + .extract_failed = false, + }; + + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (event_type), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "lookup_webhook_by_event", + "SELECT" + " webhook_serial" + ",event_type" + ",url" + ",http_method" + ",header_template" + ",body_template" + " FROM merchant_webhook" + " JOIN merchant_instances" + " USING (merchant_serial)" + " WHERE merchant_instances.merchant_id=$1" + " AND event_type=$2"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_webhook_by_event", + params, + &lookup_webhook_by_event_cb, + &wlc); + + if (wlc.extract_failed) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/backenddb/pg_lookup_webhook_by_event.h b/src/backenddb/pg_lookup_webhook_by_event.h new file mode 100644 index 00000000..ccabc1ec --- /dev/null +++ b/src/backenddb/pg_lookup_webhook_by_event.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_webhook_by_event.h + * @brief implementation of the lookup_webhook_by_event function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_WEBHOOK_BY_EVENT_H +#define PG_LOOKUP_WEBHOOK_BY_EVENT_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup webhook by event + * + * @param cls closure + * @param instance_id instance to lookup webhook for + * @param event_type event that we need to put in the pending webhook + * @param[out] cb set to the webhook details on success + * @param cb_cls callback closure + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_webhook_by_event (void *cls, + const char *instance_id, + const char *event_type, + TALER_MERCHANTDB_WebhookDetailCallback cb, + void *cb_cls); + +#endif diff --git a/src/backenddb/pg_lookup_webhooks.c b/src/backenddb/pg_lookup_webhooks.c new file mode 100644 index 00000000..0a85d527 --- /dev/null +++ b/src/backenddb/pg_lookup_webhooks.c @@ -0,0 +1,133 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_webhooks.c + * @brief Implementation of the lookup_webhooks function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_lookup_webhooks.h" +#include "pg_helper.h" + +/** + * Context used for postgres_lookup_webhooks(). + */ +struct LookupWebhookContext +{ + /** + * Function to call with the results. + */ + TALER_MERCHANTDB_WebhooksCallback 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 webhook. + * + * @param[in,out] cls of type `struct LookupWebhookContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_webhooks_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupWebhookContext *wlc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + char *webhook_id; + char *event_type; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("webhook_id", + &webhook_id), + GNUNET_PQ_result_spec_string ("event_type", + &event_type), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + wlc->extract_failed = true; + return; + } + wlc->cb (wlc->cb_cls, + webhook_id, + event_type); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_webhooks (void *cls, + const char *instance_id, + TALER_MERCHANTDB_WebhooksCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct LookupWebhookContext wlc = { + .cb = cb, + .cb_cls = cb_cls, + /* Can be overwritten by the lookup_webhook_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_webhooks", + "SELECT" + " webhook_id" + ",event_type" + " FROM merchant_webhook" + " JOIN merchant_instances" + " USING (merchant_serial)" + " WHERE merchant_instances.merchant_id=$1"); + + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_webhooks", + params, + &lookup_webhooks_cb, + &wlc); + /* If there was an error inside lookup_webhook_cb, return a hard error. */ + if (wlc.extract_failed) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/backenddb/pg_lookup_webhooks.h b/src/backenddb/pg_lookup_webhooks.h new file mode 100644 index 00000000..84509267 --- /dev/null +++ b/src/backenddb/pg_lookup_webhooks.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_lookup_webhooks.h + * @brief implementation of the lookup_webhooks function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_LOOKUP_WEBHOOKS_H +#define PG_LOOKUP_WEBHOOKS_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Lookup all of the webhooks the given instance has configured. + * + * @param cls closure + * @param instance_id instance to lookup webhook for + * @param cb function to call on all webhook found + * @param cb_cls closure for @a cb + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_webhooks (void *cls, + const char *instance_id, + TALER_MERCHANTDB_WebhooksCallback cb, + void *cb_cls); + +#endif diff --git a/src/backenddb/pg_purge_reserve.c b/src/backenddb/pg_purge_reserve.c new file mode 100644 index 00000000..cb01069a --- /dev/null +++ b/src/backenddb/pg_purge_reserve.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_purge_reserve.c + * @brief Implementation of the purge_reserve function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_purge_reserve.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_purge_reserve (void *cls, + const char *instance_id, + const struct TALER_ReservePublicKeyP *reserve_pub) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_auto_from_type (reserve_pub), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "purge_reserve", + "DELETE" + " FROM merchant_reward_reserves" + " WHERE reserve_pub=$2" + " AND merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "purge_reserve", + params); +} diff --git a/src/backenddb/pg_purge_reserve.h b/src/backenddb/pg_purge_reserve.h new file mode 100644 index 00000000..83c1b44f --- /dev/null +++ b/src/backenddb/pg_purge_reserve.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_purge_reserve.h + * @brief implementation of the purge_reserve function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_PURGE_RESERVE_H +#define PG_PURGE_RESERVE_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Purge all of the information about a reserve, including rewards. + * + * @param cls closure, typically a connection to the db + * @param instance_id which instance is the reserve tied to + * @param reserve_pub which reserve is to be purged + * @return transaction status, usually + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success + */ +enum GNUNET_DB_QueryStatus +TMH_PG_purge_reserve (void *cls, + const char *instance_id, + const struct TALER_ReservePublicKeyP *reserve_pub); + +#endif diff --git a/src/backenddb/pg_update_webhook.c b/src/backenddb/pg_update_webhook.c new file mode 100644 index 00000000..c12ae9e3 --- /dev/null +++ b/src/backenddb/pg_update_webhook.c @@ -0,0 +1,69 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_update_webhook.c + * @brief Implementation of the update_webhook function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include +#include +#include +#include "pg_update_webhook.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_update_webhook (void *cls, + const char *instance_id, + const char *webhook_id, + const struct TALER_MERCHANTDB_WebhookDetails *wb) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (webhook_id), + GNUNET_PQ_query_param_string (wb->event_type), + GNUNET_PQ_query_param_string (wb->url), + GNUNET_PQ_query_param_string (wb->http_method), + (NULL == wb->header_template) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (wb->header_template), + (NULL == wb->body_template) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (wb->body_template), + GNUNET_PQ_query_param_end + }; + + + check_connection (pg); + PREPARE (pg, + "update_webhook", + "UPDATE merchant_webhook SET" + " event_type=$3" + ",url=$4" + ",http_method=$5" + ",header_template=$6" + ",body_template=$7" + " WHERE merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND webhook_id=$2"); + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_webhook", + params); +} diff --git a/src/backenddb/pg_update_webhook.h b/src/backenddb/pg_update_webhook.h new file mode 100644 index 00000000..a34eb598 --- /dev/null +++ b/src/backenddb/pg_update_webhook.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2023 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 + */ +/** + * @file backenddb/pg_update_webhook.h + * @brief implementation of the update_webhook function for Postgres + * @author Iván Ávalos + */ +#ifndef PG_UPDATE_WEBHOOK_H +#define PG_UPDATE_WEBHOOK_H + +#include +#include +#include "taler_merchantdb_plugin.h" + +/** + * Update details about a particular webhook. + * + * @param cls closure + * @param instance_id instance to update template for + * @param webhook_id webhook to update + * @param wb update to the webhook details on success, can be NULL + * (in that case we only want to check if the webhook exists) + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the webhook + * does not yet exist. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_update_webhook (void *cls, + const char *instance_id, + const char *webhook_id, + const struct TALER_MERCHANTDB_WebhookDetails *wb); + +#endif diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 214902dd..35f2ecb9 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -112,6 +112,22 @@ #include "pg_lookup_transfer.h" #include "pg_lookup_transfer_summary.h" #include "pg_lookup_transfer_details.h" +#include "pg_lookup_pending_reserves.h" +#include "pg_lookup_reserve.h" +#include "pg_delete_reserve.h" +#include "pg_purge_reserve.h" +#include "pg_lookup_pickup.h" +#include "pg_lookup_reward.h" +#include "pg_lookup_rewards.h" +#include "pg_lookup_reward_details.h" +#include "pg_insert_pickup_blind_signature.h" +#include "pg_lookup_webhooks.h" +#include "pg_lookup_webhook.h" +#include "pg_delete_webhook.h" +#include "pg_insert_webhook.h" +#include "pg_update_webhook.h" +#include "pg_lookup_webhook_by_event.h" +#include "pg_delete_pending_webhook.h" #include "pg_set_transfer_status_to_confirmed.h" #include "pg_insert_exchange_keys.h" #include "pg_select_exchange_keys.h" @@ -275,1306 +291,6 @@ check_connection (struct PostgresClosure *pg) } -/** - * Closure for #lookup_pending_reserves_cb. - */ -struct LookupPendingReservesContext -{ - /** - * Postgres context. - */ - struct PostgresClosure *pg; - - /** - * Function to call with the results - */ - TALER_MERCHANTDB_PendingReservesCallback cb; - - /** - * Closure for @e cb - */ - void *cb_cls; - - /** - * Set in case of 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[in,out] cls of type `struct LookupReservesContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_pending_reserves_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupPendingReservesContext *lrc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_Amount merchant_initial_balance; - char *exchange_url; - char *instance_id; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - &reserve_pub), - GNUNET_PQ_result_spec_string ("merchant_id", - &instance_id), - GNUNET_PQ_result_spec_string ("exchange_url", - &exchange_url), - TALER_PQ_result_spec_amount_with_currency ("merchant_initial_balance", - &merchant_initial_balance), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - lrc->qs = GNUNET_DB_STATUS_HARD_ERROR; - return; - } - lrc->cb (lrc->cb_cls, - instance_id, - exchange_url, - &reserve_pub, - &merchant_initial_balance); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Lookup reserves pending activation across all instances. - * - * @param cls closure - * @param cb function to call with reserve summary data - * @param cb_cls closure for @a cb - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_pending_reserves (void *cls, - TALER_MERCHANTDB_PendingReservesCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct LookupPendingReservesContext lrc = { - .pg = pg, - .cb = cb, - .cb_cls = cb_cls - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - check_connection (pg); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_pending_reserves", - params, - &lookup_pending_reserves_cb, - &lrc); - if (lrc.qs < 0) - return lrc.qs; - return qs; -} - - -/** - * Closure for #lookup_reserve_rewards_cb(). - */ -struct LookupRewardsContext -{ - /** - * Postgres context. - */ - struct PostgresClosure *pg; - - /** - * Array with information about rewards generated from this reserve. - */ - struct TALER_MERCHANTDB_RewardDetails *rewards; - - /** - * Length of the @e rewards array. - */ - unsigned int rewards_length; - - /** - * Set in case of 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[in,out] cls of type `struct LookupRewardsContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_reserve_rewards_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRewardsContext *ltc = cls; - - GNUNET_array_grow (ltc->rewards, - ltc->rewards_length, - num_results); - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_MERCHANTDB_RewardDetails *td = <c->rewards[i]; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("justification", - &td->reason), - GNUNET_PQ_result_spec_auto_from_type ("reward_id", - &td->reward_id), - TALER_PQ_result_spec_amount_with_currency ("amount", - &td->total_amount), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ltc->qs = GNUNET_DB_STATUS_HARD_ERROR; - return; - } - } -} - - -/** - * Lookup reserve details. - * - * @param cls closure - * @param instance_id instance to lookup payments for - * @param reserve_pub public key of the reserve to inspect - * @param fetch_rewards if true, also return information about rewards - * @param cb function to call with reserve summary data - * @param cb_cls closure for @a cb - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_reserve (void *cls, - const char *instance_id, - const struct TALER_ReservePublicKeyP *reserve_pub, - bool fetch_rewards, - TALER_MERCHANTDB_ReserveDetailsCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct LookupRewardsContext ltc = { - .pg = pg, - .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT - }; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_TIME_Timestamp creation_time; - struct GNUNET_TIME_Timestamp expiration_time; - struct TALER_Amount merchant_initial_balance; - struct TALER_Amount exchange_initial_balance; - struct TALER_Amount pickup_amount; - struct TALER_Amount committed_amount; - struct TALER_MasterPublicKeyP master_pub; - bool active; - char *exchange_url = NULL; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("creation_time", - &creation_time), - GNUNET_PQ_result_spec_timestamp ("expiration", - &expiration_time), - TALER_PQ_result_spec_amount_with_currency ("merchant_initial_balance", - &merchant_initial_balance), - TALER_PQ_result_spec_amount_with_currency ("exchange_initial_balance", - &exchange_initial_balance), - TALER_PQ_result_spec_amount_with_currency ("rewards_picked_up", - &pickup_amount), - TALER_PQ_result_spec_amount_with_currency ("rewards_committed", - &committed_amount), - GNUNET_PQ_result_spec_auto_from_type ("master_pub", - &master_pub), - GNUNET_PQ_result_spec_bool ("active", - &active), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("exchange_url", - &exchange_url), - NULL), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - check_connection (pg); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_reserve", - params, - rs); - if (qs < 0) - return qs; - if (! fetch_rewards) - { - cb (cb_cls, - creation_time, - expiration_time, - &merchant_initial_balance, - &exchange_initial_balance, - &pickup_amount, - &committed_amount, - active, - &master_pub, - exchange_url, - 0, - NULL); - GNUNET_PQ_cleanup_result (rs); - return qs; - } - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_reserve_rewards", - params, - &lookup_reserve_rewards_cb, - <c); - if (qs < 0) - return qs; - if (ltc.qs >= 0) - { - cb (cb_cls, - creation_time, - expiration_time, - &merchant_initial_balance, - &exchange_initial_balance, - &pickup_amount, - &committed_amount, - active, - &master_pub, - exchange_url, - ltc.rewards_length, - ltc.rewards); - } - for (unsigned int i = 0; iconn, - "delete_reserve", - params); -} - - -/** - * Purge all of the information about a reserve, including rewards. - * - * @param cls closure, typically a connection to the db - * @param instance_id which instance is the reserve tied to - * @param reserve_pub which reserve is to be purged - * @return transaction status, usually - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success - */ -static enum GNUNET_DB_QueryStatus -postgres_purge_reserve (void *cls, - const char *instance_id, - const struct TALER_ReservePublicKeyP *reserve_pub) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "purge_reserve", - params); -} - - -/** - * Closure for #lookup_signatures_cb(). - */ -struct LookupSignaturesContext -{ - /** - * Length of the @e sigs array - */ - unsigned int sigs_length; - - /** - * Where to store the signatures. - */ - struct TALER_BlindedDenominationSignature *sigs; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results about accounts. - * - * @param[in,out] cls of type `struct LookupSignaturesContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_signatures_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupSignaturesContext *lsc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - uint32_t offset; - struct TALER_BlindedDenominationSignature bsig; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint32 ("coin_offset", - &offset), - TALER_PQ_result_spec_blinded_denom_sig ("blind_sig", - &bsig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - return; - } - if (offset >= lsc->sigs_length) - { - GNUNET_break_op (0); - GNUNET_PQ_cleanup_result (rs); - continue; - } - /* Must be NULL due to UNIQUE constraint on offset and - requirement that client launched us with 'sigs' - pre-initialized to NULL. */ - lsc->sigs[offset] = bsig; - } -} - - -/** - * Lookup pickup details for pickup @a pickup_id. - * - * @param cls closure, typically a connection to the db - * @param instance_id which instance should we lookup reward details for - * @param reward_id which reward should we lookup details on - * @param pickup_id which pickup should we lookup details on - * @param[out] exchange_url which exchange is the reward withdrawn from - * @param[out] reserve_priv private key the reward is withdrawn from (set if still available!) - * @param sigs_length length of the @a sigs array - * @param[out] sigs set to the (blind) signatures we have for this @a pickup_id, - * those that are unavailable are left at NULL - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_pickup (void *cls, - const char *instance_id, - const struct TALER_RewardIdentifierP *reward_id, - const struct TALER_PickupIdentifierP *pickup_id, - char **exchange_url, - struct TALER_ReservePrivateKeyP *reserve_priv, - unsigned int sigs_length, - struct TALER_BlindedDenominationSignature sigs[]) -{ - struct PostgresClosure *pg = cls; - uint64_t pickup_serial; - - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_auto_from_type (reward_id), - GNUNET_PQ_query_param_auto_from_type (pickup_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("exchange_url", - exchange_url), - GNUNET_PQ_result_spec_auto_from_type ("reserve_priv", - reserve_priv), - GNUNET_PQ_result_spec_uint64 ("pickup_serial", - &pickup_serial), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_pickup", - params, - rs); - if (qs <= 0) - return qs; - } - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&pickup_serial), - GNUNET_PQ_query_param_end - }; - struct LookupSignaturesContext lsc = { - .sigs_length = sigs_length, - .sigs = sigs - }; - - return GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_pickup_signatures", - params, - &lookup_signatures_cb, - &lsc); - } -} - - -/** - * Lookup reward details for reward @a reward_id. - * - * @param cls closure, typically a connection to the db - * @param instance_id which instance should we lookup reward details for - * @param reward_id which reward should we lookup details on - * @param[out] total_authorized amount how high is the reward (with fees) - * @param[out] total_picked_up how much of the reward was so far picked up (with fees) - * @param[out] expiration set to when the reward expires - * @param[out] exchange_url set to the exchange URL where the reserve is - * @param[out] next_url set to the URL where the wallet should navigate after getting the reward - * @param[out] reserve_priv set to private key of reserve to be debited - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_reward (void *cls, - const char *instance_id, - const struct TALER_RewardIdentifierP *reward_id, - struct TALER_Amount *total_authorized, - struct TALER_Amount *total_picked_up, - struct GNUNET_TIME_Timestamp *expiration, - char **exchange_url, - char **next_url, - struct TALER_ReservePrivateKeyP *reserve_priv) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_auto_from_type (reward_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_amount_with_currency ("amount", - total_authorized), - TALER_PQ_result_spec_amount_with_currency ("picked_up", - total_picked_up), - GNUNET_PQ_result_spec_timestamp ("expiration", - expiration), - GNUNET_PQ_result_spec_string ("exchange_url", - exchange_url), - GNUNET_PQ_result_spec_string ("next_url", - next_url), - GNUNET_PQ_result_spec_auto_from_type ("reserve_priv", - reserve_priv), - GNUNET_PQ_result_spec_end - }; - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_reward", - params, - rs); -} - - -/** - * Context used for postgres_lookup_rewards(). - */ -struct LookupMerchantRewardsContext -{ - /** - * Postgres context. - */ - struct PostgresClosure *pg; - - /** - * Function to call with the results. - */ - TALER_MERCHANTDB_RewardsCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Internal result. - */ - enum GNUNET_DB_QueryStatus qs; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results about rewards. - * - * @param[in,out] cls of type `struct LookupRewardsContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_rewards_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupMerchantRewardsContext *plc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - uint64_t row_id; - struct TALER_RewardIdentifierP reward_id; - struct TALER_Amount reward_amount; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("reward_serial", - &row_id), - GNUNET_PQ_result_spec_auto_from_type ("reward_id", - &reward_id), - TALER_PQ_result_spec_amount_with_currency ("amount", - &reward_amount), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - plc->qs = GNUNET_DB_STATUS_HARD_ERROR; - return; - } - plc->cb (plc->cb_cls, - row_id, - reward_id, - reward_amount); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Lookup rewards - * - * @param cls closure, typically a connection to the db - * @param instance_id which instance should we lookup rewards for - * @param expired should we include expired rewards? - * @param limit maximum number of results to return, positive for - * ascending row id, negative for descending - * @param offset row id to start returning results from - * @param cb function to call with reward data - * @param cb_cls closure for @a cb - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_rewards (void *cls, - const char *instance_id, - enum TALER_EXCHANGE_YesNoAll expired, - int64_t limit, - uint64_t offset, - TALER_MERCHANTDB_RewardsCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct LookupMerchantRewardsContext plc = { - .pg = pg, - .cb = cb, - .cb_cls = cb_cls - }; - uint64_t ulimit = (limit > 0) ? limit : -limit; - uint8_t bexpired; - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_uint64 (&ulimit), - GNUNET_PQ_query_param_uint64 (&offset), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_auto_from_type (&bexpired), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - char stmt[128]; - - bexpired = (TALER_EXCHANGE_YNA_YES == expired); - GNUNET_snprintf (stmt, - sizeof (stmt), - "lookup_rewards_%s%s", - (limit > 0) ? "inc" : "dec", - (TALER_EXCHANGE_YNA_ALL == expired) ? "" : "_expired"); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - stmt, - params, - &lookup_rewards_cb, - &plc); - if (0 != plc.qs) - return plc.qs; - return qs; -} - - -/** - * Closure for #lookup_pickup_details_cb(). - */ -struct LookupRewardDetailsContext -{ - /** - * Length of the @e sigs array - */ - unsigned int *pickups_length; - - /** - * Where to store the signatures. - */ - struct TALER_MERCHANTDB_PickupDetails **pickups; - - /** - * Database handle. - */ - struct PostgresClosure *pg; - - /** - * Transaction status. - */ - enum GNUNET_DB_QueryStatus qs; - -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results about pickups. - * - * @param[in,out] cls of type `struct LookupRewardDetailsContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_pickup_details_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupRewardDetailsContext *ltdc = cls; - - *ltdc->pickups_length = num_results; - *ltdc->pickups = GNUNET_new_array (num_results, - struct TALER_MERCHANTDB_PickupDetails); - for (unsigned int i = 0; i < num_results; i++) - { - struct TALER_MERCHANTDB_PickupDetails *pd = &((*ltdc->pickups)[i]); - uint64_t num_planchets = 0; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("pickup_id", - &pd->pickup_id), - TALER_PQ_result_spec_amount_with_currency ("amount", - &pd->requested_amount), - GNUNET_PQ_result_spec_uint64 ("num_planchets", - &num_planchets), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ltdc->qs = GNUNET_DB_STATUS_HARD_ERROR; - GNUNET_array_grow (*ltdc->pickups, - *ltdc->pickups_length, - 0); - return; - } - - pd->num_planchets = num_planchets; - } -} - - -/** - * Lookup reward details for reward @a reward_id. - * - * @param cls closure, typically a connection to the db - * @param instance_id which instance should we lookup reward details for - * @param reward_id which reward should we lookup details on - * @param fpu should we fetch details about individual pickups - * @param[out] total_authorized amount how high is the reward (with fees) - * @param[out] total_picked_up how much of the reward was so far picked up (with fees) - * @param[out] justification why was the reward approved - * @param[out] expiration set to when the reward expires - * @param[out] reserve_pub set to which reserve is debited - * @param[out] pickups_length set to the length of @e pickups - * @param[out] pickups if @a fpu is true, set to details about the pickup operations - * @return transaction status, - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_reward_details (void *cls, - const char *instance_id, - const struct TALER_RewardIdentifierP *reward_id, - bool fpu, - struct TALER_Amount *total_authorized, - struct TALER_Amount *total_picked_up, - char **justification, - struct GNUNET_TIME_Timestamp *expiration, - struct TALER_ReservePublicKeyP *reserve_pub, - unsigned int *pickups_length, - struct TALER_MERCHANTDB_PickupDetails **pickups) -{ - struct PostgresClosure *pg = cls; - uint64_t reward_serial; - enum GNUNET_DB_QueryStatus qs; - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_auto_from_type (reward_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("reward_serial", - &reward_serial), - TALER_PQ_result_spec_amount_with_currency ("amount", - total_authorized), - TALER_PQ_result_spec_amount_with_currency ("picked_up", - total_picked_up), - GNUNET_PQ_result_spec_string ("justification", - justification), - GNUNET_PQ_result_spec_timestamp ("expiration", - expiration), - GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", - reserve_pub), - GNUNET_PQ_result_spec_end - }; - - check_connection (pg); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_reward_details", - params, - rs); - if (qs <= 0) - return qs; - if (! fpu) - { - *pickups_length = 0; - *pickups = NULL; - return qs; - } - } - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&reward_serial), - GNUNET_PQ_query_param_end - }; - - struct LookupRewardDetailsContext ltdc = { - .pickups_length = pickups_length, - .pickups = pickups, - .pg = pg, - .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT - }; - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_pickup_details", - params, - &lookup_pickup_details_cb, - <dc); - if (qs < 0) - return qs; - return ltdc.qs; - } -} - - -/** - * Insert blind signature obtained from the exchange during a - * reward pickup operation. - * - * @param cls closure, typically a connection to the db - * @param pickup_id unique ID for the operation - * @param offset offset of the blind signature for the pickup - * @param blind_sig the blind signature - * @return transaction status, usually - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a credit_uuid already known - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_pickup_blind_signature ( - void *cls, - const struct TALER_PickupIdentifierP *pickup_id, - uint32_t offset, - const struct TALER_BlindedDenominationSignature *blind_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (pickup_id), - GNUNET_PQ_query_param_uint32 (&offset), - TALER_PQ_query_param_blinded_denom_sig (blind_sig), - GNUNET_PQ_query_param_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_pickup_blind_signature", - params); -} - - -/** - * Delete information about a webhook. - * - * @param cls closure - * @param instance_id instance to delete webhook of - * @param webhook_id webhook to delete - * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS - * if webhook unknown. - */ -static enum GNUNET_DB_QueryStatus -postgres_delete_webhook (void *cls, - const char *instance_id, - const char *webhook_id) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (webhook_id), - GNUNET_PQ_query_param_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "delete_webhook", - params); -} - - -/** - * Insert details about a particular webhook. - * - * @param cls closure - * @param instance_id instance to insert webhook for - * @param webhook_id webhook identifier of webhook to insert - * @param wb the webhook details to insert - * @return database result code - */ -static enum GNUNET_DB_QueryStatus -postgres_insert_webhook (void *cls, - const char *instance_id, - const char *webhook_id, - const struct TALER_MERCHANTDB_WebhookDetails *wb) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (webhook_id), - GNUNET_PQ_query_param_string (wb->event_type), - GNUNET_PQ_query_param_string (wb->url), - GNUNET_PQ_query_param_string (wb->http_method), - (NULL == wb->header_template) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (wb->header_template), - (NULL == wb->body_template) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (wb->body_template), - GNUNET_PQ_query_param_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_webhook", - params); -} - - -/** - * Update details about a particular webhook. - * - * @param cls closure - * @param instance_id instance to update template for - * @param webhook_id webhook to update - * @param wb update to the webhook details on success, can be NULL - * (in that case we only want to check if the webhook exists) - * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the webhook - * does not yet exist. - */ -static enum GNUNET_DB_QueryStatus -postgres_update_webhook (void *cls, - const char *instance_id, - const char *webhook_id, - const struct TALER_MERCHANTDB_WebhookDetails *wb) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (webhook_id), - GNUNET_PQ_query_param_string (wb->event_type), - GNUNET_PQ_query_param_string (wb->url), - GNUNET_PQ_query_param_string (wb->http_method), - (NULL == wb->header_template) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (wb->header_template), - (NULL == wb->body_template) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (wb->body_template), - GNUNET_PQ_query_param_end - }; - - - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_webhook", - params); -} - - -/** - * Context used for postgres_lookup_webhook(). - */ -struct LookupWebhookContext -{ - /** - * Function to call with the results. - */ - TALER_MERCHANTDB_WebhooksCallback 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 webhook. - * - * @param[in,out] cls of type `struct LookupWebhookContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_webhooks_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupWebhookContext *wlc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - char *webhook_id; - char *event_type; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("webhook_id", - &webhook_id), - GNUNET_PQ_result_spec_string ("event_type", - &event_type), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - wlc->extract_failed = true; - return; - } - wlc->cb (wlc->cb_cls, - webhook_id, - event_type); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Lookup all of the webhooks the given instance has configured. - * - * @param cls closure - * @param instance_id instance to lookup webhook for - * @param cb function to call on all webhook found - * @param cb_cls closure for @a cb - * @return database result code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_webhooks (void *cls, - const char *instance_id, - TALER_MERCHANTDB_WebhooksCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct LookupWebhookContext wlc = { - .cb = cb, - .cb_cls = cb_cls, - /* Can be overwritten by the lookup_webhook_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_webhooks", - params, - &lookup_webhooks_cb, - &wlc); - /* If there was an error inside lookup_webhook_cb, return a hard error. */ - if (wlc.extract_failed) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} - - -/** - * Lookup details about a particular webhook. - * - * @param cls closure - * @param instance_id instance to lookup webhook for - * @param webhook_id webhook to lookup - * @param[out] wb set to the webhook details on success, can be NULL - * (in that case we only want to check if the webhook exists) - * @return database result code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_webhook (void *cls, - const char *instance_id, - const char *webhook_id, - struct TALER_MERCHANTDB_WebhookDetails *wb) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (webhook_id), - GNUNET_PQ_query_param_end - }; - - if (NULL == wb) - { - struct GNUNET_PQ_ResultSpec rs_null[] = { - GNUNET_PQ_result_spec_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_webhook", - params, - rs_null); - } - else - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("event_type", - &wb->event_type), - GNUNET_PQ_result_spec_string ("url", - &wb->url), - GNUNET_PQ_result_spec_string ("http_method", - &wb->http_method), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("header_template", - &wb->header_template), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("body_template", - &wb->body_template), - NULL), - GNUNET_PQ_result_spec_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_webhook", - params, - rs); - } -} - - -/** - * Context used for postgres_lookup_webhook(). - */ -struct LookupWebhookDetailContext -{ - /** - * Function to call with the results. - */ - TALER_MERCHANTDB_WebhookDetailCallback 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 webhook. - * - * @param[in,out] cls of type `struct LookupPendingWebhookContext *` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -lookup_webhook_by_event_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct LookupWebhookDetailContext *wlc = cls; - - for (unsigned int i = 0; i < num_results; i++) - { - uint64_t webhook_serial; - char *event_type; - char *url; - char *http_method; - char *header_template; - char *body_template; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("webhook_serial", - &webhook_serial), - GNUNET_PQ_result_spec_string ("event_type", - &event_type), - GNUNET_PQ_result_spec_string ("url", - &url), - GNUNET_PQ_result_spec_string ("http_method", - &http_method), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("header_template", - &header_template), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("body_template", - &body_template), - NULL), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - wlc->extract_failed = true; - return; - } - wlc->cb (wlc->cb_cls, - webhook_serial, - event_type, - url, - http_method, - header_template, - body_template); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Lookup webhook by event - * - * @param cls closure - * @param instance_id instance to lookup webhook for - * @param event_type event that we need to put in the pending webhook - * @param[out] cb set to the webhook details on success - * @param cb_cls callback closure - * @return database result code - */ -static enum GNUNET_DB_QueryStatus -postgres_lookup_webhook_by_event (void *cls, - const char *instance_id, - const char *event_type, - TALER_MERCHANTDB_WebhookDetailCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct LookupWebhookDetailContext wlc = { - .cb = cb, - .cb_cls = cb_cls, - .extract_failed = false, - }; - - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (event_type), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - check_connection (pg); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "lookup_webhook_by_event", - params, - &lookup_webhook_by_event_cb, - &wlc); - - if (wlc.extract_failed) - return GNUNET_DB_STATUS_HARD_ERROR; - return qs; -} - - /** * Insert webhook in the pending webhook. * @@ -1863,30 +579,6 @@ postgres_update_pending_webhook (void *cls, } -/** - * Delete a webhook in the pending webhook after the - * webhook was completed successfully. - * - * @param cls closure - * @param webhook_pending_serial identifies the row that needs to be deleted in the pending webhook table - * @return database result code - */ -static enum GNUNET_DB_QueryStatus -postgres_delete_pending_webhook (void *cls, - uint64_t webhook_pending_serial) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&webhook_pending_serial), - GNUNET_PQ_query_param_end - }; - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "delete_pending_webhook", - params); -} - - /** * Establish connection to the database. * @@ -1915,298 +607,6 @@ postgres_connect (void *cls) " (SELECT merchant_serial" " FROM merchant_instances" " WHERE merchant_id=$1)"), - /* For postgres_lookup_pending_reserves() */ - GNUNET_PQ_make_prepare ("lookup_pending_reserves", - "SELECT" - " reserve_pub" - ",merchant_id" - ",exchange_url" - ",merchant_initial_balance" - " FROM merchant_reward_reserves mrr" - " JOIN merchant_instances USING (merchant_serial)" - " JOIN merchant_reward_reserve_keys USING (reserve_serial)" - " WHERE (mrr.exchange_initial_balance).val=0" - " AND (mrr.exchange_initial_balance).frac=0"), - /* For postgres_lookup_reserve() */ - GNUNET_PQ_make_prepare ("lookup_reserve", - "SELECT" - " creation_time" - ",expiration" - ",merchant_initial_balance" - ",exchange_initial_balance" - ",rewards_committed" - ",rewards_picked_up" - ",reserve_priv IS NOT NULL AS active" - ",exchange_url" - ",master_pub" - " FROM merchant_reward_reserves" - " FULL OUTER JOIN merchant_reward_reserve_keys USING (reserve_serial)" - " WHERE reserve_pub = $2" - " AND merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)"), - /* For postgres_lookup_reserve() */ - GNUNET_PQ_make_prepare ("lookup_reserve_rewards", - "SELECT" - " justification" - ",reward_id" - ",amount" - " FROM merchant_rewards" - " WHERE reserve_serial =" - " (SELECT reserve_serial" - " FROM merchant_reward_reserves" - " WHERE reserve_pub=$2" - " AND merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1))"), - /* for postgres_delete_reserve() */ - GNUNET_PQ_make_prepare ("delete_reserve", - "DELETE" - " FROM merchant_reward_reserve_keys" - " WHERE reserve_serial=" - " (SELECT reserve_serial" - " FROM merchant_reward_reserves" - " WHERE reserve_pub=$2" - " AND merchant_serial=" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1))"), - /* for postgres_purge_reserve() */ - GNUNET_PQ_make_prepare ("purge_reserve", - "DELETE" - " FROM merchant_reward_reserves" - " WHERE reserve_pub=$2" - " AND merchant_serial=" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)"), - /* For postgres_lookup_pickup() */ - GNUNET_PQ_make_prepare ("lookup_pickup", - "SELECT" - " exchange_url" - ",reserve_priv" - ",pickup_serial" - " FROM merchant_reward_pickups" - " JOIN merchant_rewards USING (reward_serial)" - " JOIN merchant_reward_reserves USING (reserve_serial)" - " JOIN merchant_reward_reserve_keys USING (reserve_serial)" - " WHERE pickup_id = $3" - " AND reward_id = $2" - " AND merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)"), - /* For postgres_lookup_pickup() */ - GNUNET_PQ_make_prepare ("lookup_pickup_signatures", - "SELECT" - " coin_offset" - ",blind_sig" - " FROM merchant_reward_pickup_signatures" - " WHERE pickup_serial = $1"), - - /* For postgres_lookup_reward() */ - GNUNET_PQ_make_prepare ("lookup_reward", - "SELECT" - " amount" - ",picked_up" - ",merchant_rewards.expiration" - ",exchange_url" - ",next_url" - ",reserve_priv" - " FROM merchant_rewards" - " JOIN merchant_reward_reserves USING (reserve_serial)" - " JOIN merchant_reward_reserve_keys USING (reserve_serial)" - " WHERE reward_id = $2" - " AND merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)"), - /* For postgres_lookup_reward() */ - GNUNET_PQ_make_prepare ("lookup_rewards_inc", - "SELECT" - " reward_serial" - ",reward_id" - ",amount" - ",CAST($4 as BIGINT)" /* otherwise $4 is unused and Postgres unhappy */ - ",CAST($5 as BOOL)" /* otherwise $5 is unused and Postgres unhappy */ - " FROM merchant_rewards" - " JOIN merchant_reward_reserves USING (reserve_serial)" - " WHERE merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)" - " AND" - " reward_serial > $3" - " ORDER BY reward_serial ASC" - " LIMIT $2"), - GNUNET_PQ_make_prepare ("lookup_rewards_dec", - "SELECT" - " reward_serial" - ",reward_id" - ",amount" - ",CAST($4 as BIGINT)" /* otherwise $4 is unused and Postgres unhappy */ - ",CAST($5 as BOOL)" /* otherwise $5 is unused and Postgres unhappy */ - " FROM merchant_rewards" - " JOIN merchant_reward_reserves USING (reserve_serial)" - " WHERE merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)" - " AND" - " reward_serial < $3" - " ORDER BY reward_serial DESC" - " LIMIT $2"), - GNUNET_PQ_make_prepare ("lookup_rewards_inc_expired", - "SELECT" - " reward_serial" - ",reward_id" - ",amount" - " FROM merchant_rewards" - " JOIN merchant_reward_reserves USING (reserve_serial)" - " WHERE merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)" - " AND" - " reward_serial > $3" - " AND" - " CAST($5 as BOOL) = (merchant_rewards.expiration < $4)" - " ORDER BY reward_serial ASC" - " LIMIT $2"), - GNUNET_PQ_make_prepare ("lookup_rewards_dec_expired", - "SELECT" - " reward_serial" - ",reward_id" - ",amount" - " FROM merchant_rewards" - " JOIN merchant_reward_reserves USING (reserve_serial)" - " WHERE merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)" - " AND" - " reward_serial < $3" - " AND" - " CAST($5 as BOOL) = (merchant_rewards.expiration < $4)" - " ORDER BY reward_serial DESC" - " LIMIT $2"), - /* for postgres_lookup_reward_details() */ - GNUNET_PQ_make_prepare ("lookup_reward_details", - "SELECT" - " reward_serial" - ",amount" - ",picked_up" - ",justification" - ",merchant_rewards.expiration" - ",reserve_pub" - " FROM merchant_rewards" - " JOIN merchant_reward_reserves USING (reserve_serial)" - " WHERE reward_id = $2" - " AND merchant_serial =" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)"), - /* for postgres_lookup_reward_details() */ - GNUNET_PQ_make_prepare ("lookup_pickup_details", - "SELECT" - " pickup_id" - ",amount" - ",COUNT(blind_sig) AS num_planchets" - " FROM merchant_reward_pickups" - " JOIN merchant_reward_pickup_signatures USING (pickup_serial)" - " WHERE reward_serial = $1" - " GROUP BY pickup_serial"), - /* for postgres_insert_pickup_blind_signature() */ - GNUNET_PQ_make_prepare ("insert_pickup_blind_signature", - "INSERT INTO merchant_reward_pickup_signatures" - "(pickup_serial" - ",coin_offset" - ",blind_sig" - ") " - "SELECT" - " pickup_serial, $2, $3" - " FROM merchant_reward_pickups" - " WHERE pickup_id=$1"), - /* for postgres_lookup_webhooks() */ - GNUNET_PQ_make_prepare ("lookup_webhooks", - "SELECT" - " webhook_id" - ",event_type" - " FROM merchant_webhook" - " JOIN merchant_instances" - " USING (merchant_serial)" - " WHERE merchant_instances.merchant_id=$1"), - /* for postgres_lookup_webhook() */ - GNUNET_PQ_make_prepare ("lookup_webhook", - "SELECT" - " event_type" - ",url" - ",http_method" - ",header_template" - ",body_template" - " FROM merchant_webhook" - " JOIN merchant_instances" - " USING (merchant_serial)" - " WHERE merchant_instances.merchant_id=$1" - " AND merchant_webhook.webhook_id=$2"), - /* for postgres_delete_webhook() */ - GNUNET_PQ_make_prepare ("delete_webhook", - "DELETE" - " FROM merchant_webhook" - " WHERE merchant_webhook.merchant_serial=" - " (SELECT merchant_serial " - " FROM merchant_instances" - " WHERE merchant_id=$1)" - " AND merchant_webhook.webhook_id=$2"), - /* for postgres_insert_webhook() */ - GNUNET_PQ_make_prepare ("insert_webhook", - "INSERT INTO merchant_webhook" - "(merchant_serial" - ",webhook_id" - ",event_type" - ",url" - ",http_method" - ",header_template" - ",body_template" - ")" - " SELECT merchant_serial," - " $2, $3, $4, $5, $6, $7" - " FROM merchant_instances" - " WHERE merchant_id=$1"), - /* for postgres_update_webhook() */ - GNUNET_PQ_make_prepare ("update_webhook", - "UPDATE merchant_webhook SET" - " event_type=$3" - ",url=$4" - ",http_method=$5" - ",header_template=$6" - ",body_template=$7" - " WHERE merchant_serial=" - " (SELECT merchant_serial" - " FROM merchant_instances" - " WHERE merchant_id=$1)" - " AND webhook_id=$2"), - /* for postgres_lookup_webhook_by_event() */ - GNUNET_PQ_make_prepare ("lookup_webhook_by_event", - "SELECT" - " webhook_serial" - ",event_type" - ",url" - ",http_method" - ",header_template" - ",body_template" - " FROM merchant_webhook" - " JOIN merchant_instances" - " USING (merchant_serial)" - " WHERE merchant_instances.merchant_id=$1" - " AND event_type=$2"), - /* for postgres_delete_pending_webhook() */ - GNUNET_PQ_make_prepare ("delete_pending_webhook", - "DELETE" - " FROM merchant_pending_webhooks" - " WHERE webhook_pending_serial=$1"), /* for postgres_insert_pending_webhook() */ GNUNET_PQ_make_prepare ("insert_pending_webhook", "INSERT INTO merchant_pending_webhooks" @@ -2494,16 +894,24 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) = &TMH_PG_select_accounts; plugin->lookup_reserves = &TMH_PG_lookup_reserves; - plugin->lookup_pending_reserves = &postgres_lookup_pending_reserves; - plugin->lookup_reserve = &postgres_lookup_reserve; - plugin->delete_reserve = &postgres_delete_reserve; - plugin->purge_reserve = &postgres_purge_reserve; - plugin->lookup_pickup = &postgres_lookup_pickup; - plugin->lookup_reward = &postgres_lookup_reward; - plugin->lookup_rewards = &postgres_lookup_rewards; - plugin->lookup_reward_details = &postgres_lookup_reward_details; - plugin->insert_pickup_blind_signature = - &postgres_insert_pickup_blind_signature; + plugin->lookup_pending_reserves + = &TMH_PG_lookup_pending_reserves; + plugin->lookup_reserve + = &TMH_PG_lookup_reserve; + plugin->delete_reserve + = &TMH_PG_delete_reserve; + plugin->purge_reserve + = &TMH_PG_purge_reserve; + plugin->lookup_pickup + = &TMH_PG_lookup_pickup; + plugin->lookup_reward + = &TMH_PG_lookup_reward; + plugin->lookup_rewards + = &TMH_PG_lookup_rewards; + plugin->lookup_reward_details + = &TMH_PG_lookup_reward_details; + plugin->insert_pickup_blind_signature + = &TMH_PG_insert_pickup_blind_signature; plugin->select_open_transfers = &TMH_PG_select_open_transfers; plugin->insert_exchange_keys @@ -2526,16 +934,23 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) = &TMH_PG_authorize_reward; plugin->insert_pickup = &TMH_PG_insert_pickup; - plugin->lookup_webhooks = &postgres_lookup_webhooks; - plugin->lookup_webhook = &postgres_lookup_webhook; - plugin->delete_webhook = &postgres_delete_webhook; - plugin->insert_webhook = &postgres_insert_webhook; - plugin->update_webhook = &postgres_update_webhook; - plugin->lookup_webhook_by_event = &postgres_lookup_webhook_by_event; + plugin->lookup_webhooks + = &TMH_PG_lookup_webhooks; + plugin->lookup_webhook + = &TMH_PG_lookup_webhook; + plugin->delete_webhook + = &TMH_PG_delete_webhook; + plugin->insert_webhook + = &TMH_PG_insert_webhook; + plugin->update_webhook + = &TMH_PG_update_webhook; + plugin->lookup_webhook_by_event + = &TMH_PG_lookup_webhook_by_event; plugin->lookup_all_webhooks = &postgres_lookup_all_webhooks; plugin->lookup_future_webhook = &postgres_lookup_future_webhook; plugin->lookup_pending_webhooks = &postgres_lookup_pending_webhooks; - plugin->delete_pending_webhook = &postgres_delete_pending_webhook; + plugin->delete_pending_webhook + = &TMH_PG_delete_pending_webhook; plugin->insert_pending_webhook = &postgres_insert_pending_webhook; plugin->update_pending_webhook = &postgres_update_pending_webhook; plugin->delete_exchange_accounts -- cgit v1.2.3