merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit 3e17cd9c65f071514cce08726f1d191bef90b083
parent 80e27a8c6b13b74887ab668397c68b619305cf08
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 22 Jul 2026 03:18:24 +0200

merchantdb: more renaming

Diffstat:
Msrc/backend/taler-merchant-donaukeyupdate.c | 4++--
Msrc/backend/taler-merchant-exchangekeyupdate.c | 4++--
Msrc/backend/taler-merchant-httpd_delete-management-instances-INSTANCE.c | 12++++++------
Msrc/backend/taler-merchant-httpd_delete-private-accounts-H_WIRE.c | 8++++----
Msrc/backend/taler-merchant-httpd_get-private-orders-ORDER_ID.c | 6+++---
Msrc/backend/taler-merchant-httpd_mfa.c | 4++--
Msrc/backend/taler-merchant-httpd_post-challenge-ID-confirm.c | 14+++++++-------
Msrc/backend/taler-merchant-httpd_post-orders-ORDER_ID-abort.c | 16++++++++--------
Msrc/backend/taler-merchant-httpd_post-orders-ORDER_ID-pay.c | 16++++++++--------
Msrc/backend/taler-merchant-httpd_post-private-accounts.c | 14+++++++-------
Msrc/backend/taler-merchant-httpd_post-private-orders-ORDER_ID-refund.c | 16++++++++--------
Msrc/backend/taler-merchant-httpd_post-private-orders.c | 10+++++-----
Msrc/backend/taler-merchant-httpd_post-private-products-PRODUCT_ID-lock.c | 20++++++++++----------
Msrc/backend/taler-merchant-reconciliation.c | 18+++++++++---------
Dsrc/backenddb/activate_account.c | 80-------------------------------------------------------------------------------
Dsrc/backenddb/create_mfa_challenge.c | 86-------------------------------------------------------------------------------
Asrc/backenddb/delete_instance.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/backenddb/delete_instance_private_key.c | 45---------------------------------------------
Asrc/backenddb/delete_inventory_lock.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/do_expire_locks.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/backenddb/expire_locks.sql -> src/backenddb/do_expire_locks.sql | 0
Asrc/backenddb/do_increase_refund.c | 740+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/do_insert_account.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/backenddb/activate_account.sql -> src/backenddb/do_insert_account.sql | 0
Asrc/backenddb/do_solve_mfa_challenge.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/backenddb/solve_mfa_challenge.sql -> src/backenddb/do_solve_mfa_challenge.sql | 0
Dsrc/backenddb/expire_locks.c | 60------------------------------------------------------------
Dsrc/backenddb/finalize_transfer_status.c | 76----------------------------------------------------------------------------
Dsrc/backenddb/inactivate_account.c | 61-------------------------------------------------------------
Dsrc/backenddb/increase_refund.c | 740-------------------------------------------------------------------------------
Dsrc/backenddb/increment_money_pots.c | 76----------------------------------------------------------------------------
Asrc/backenddb/insert_donau_keys.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/insert_inventory_lock.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/insert_mfa_challenge.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/insert_refund_by_coin.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/insert_wire_fee.c | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/backenddb/lock_product.c | 93-------------------------------------------------------------------------------
Dsrc/backenddb/mark_contract_paid.c | 107-------------------------------------------------------------------------------
Dsrc/backenddb/mark_order_wired.c | 45---------------------------------------------
Msrc/backenddb/meson.build | 34+++++++++++++++++-----------------
Dsrc/backenddb/purge_instance.c | 52----------------------------------------------------
Dsrc/backenddb/refund_coin.c | 74--------------------------------------------------------------------------
Dsrc/backenddb/solve_mfa_challenge.c | 80-------------------------------------------------------------------------------
Msrc/backenddb/sql-schema/meson.build | 10+++++-----
Dsrc/backenddb/store_wire_fee_by_exchange.c | 72------------------------------------------------------------------------
Msrc/backenddb/test_merchantdb.c | 196++++++++++++++++++++++++++++++++++++++++----------------------------------------
Dsrc/backenddb/unlock_inventory.c | 45---------------------------------------------
Asrc/backenddb/update_money_pot_totals.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/backenddb/increment_money_pots.sql -> src/backenddb/update_money_pot_totals.sql | 0
Asrc/backenddb/update_to_account_inactive.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/backenddb/inactivate_account.sql -> src/backenddb/update_to_account_inactive.sql | 0
Asrc/backenddb/update_to_contract_terms_paid.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/update_to_contract_terms_wired.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/update_to_instance_private_key_deleted.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/update_to_transfer_finalized.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/backenddb/upsert_donau_keys.c | 70----------------------------------------------------------------------
Dsrc/include/merchant-database/activate_account.h | 50--------------------------------------------------
Msrc/include/merchant-database/all.h | 34+++++++++++++++++-----------------
Dsrc/include/merchant-database/create_mfa_challenge.h | 63---------------------------------------------------------------
Asrc/include/merchant-database/delete_instance.h | 42++++++++++++++++++++++++++++++++++++++++++
Dsrc/include/merchant-database/delete_instance_private_key.h | 41-----------------------------------------
Asrc/include/merchant-database/delete_inventory_lock.h | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/do_expire_locks.h | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/do_increase_refund.h | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/do_insert_account.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/do_solve_mfa_challenge.h | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/include/merchant-database/expire_locks.h | 41-----------------------------------------
Dsrc/include/merchant-database/finalize_transfer_status.h | 54------------------------------------------------------
Dsrc/include/merchant-database/inactivate_account.h | 44--------------------------------------------
Dsrc/include/merchant-database/increase_refund.h | 79-------------------------------------------------------------------------------
Dsrc/include/merchant-database/increment_money_pots.h | 50--------------------------------------------------
Asrc/include/merchant-database/insert_donau_keys.h | 46++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/insert_inventory_lock.h | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/insert_mfa_challenge.h | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/insert_refund_by_coin.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/insert_wire_fee.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/include/merchant-database/lock_product.h | 54------------------------------------------------------
Dsrc/include/merchant-database/mark_contract_paid.h | 50--------------------------------------------------
Dsrc/include/merchant-database/mark_order_wired.h | 41-----------------------------------------
Dsrc/include/merchant-database/purge_instance.h | 42------------------------------------------
Dsrc/include/merchant-database/refund_coin.h | 53-----------------------------------------------------
Dsrc/include/merchant-database/solve_mfa_challenge.h | 54------------------------------------------------------
Dsrc/include/merchant-database/store_wire_fee_by_exchange.h | 52----------------------------------------------------
Dsrc/include/merchant-database/unlock_inventory.h | 44--------------------------------------------
Asrc/include/merchant-database/update_money_pot_totals.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/update_to_account_inactive.h | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/update_to_contract_terms_paid.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/update_to_contract_terms_wired.h | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/update_to_instance_private_key_deleted.h | 42++++++++++++++++++++++++++++++++++++++++++
Asrc/include/merchant-database/update_to_transfer_finalized.h | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/include/merchant-database/upsert_donau_keys.h | 46----------------------------------------------
91 files changed, 2939 insertions(+), 2938 deletions(-)

diff --git a/src/backend/taler-merchant-donaukeyupdate.c b/src/backend/taler-merchant-donaukeyupdate.c @@ -33,7 +33,7 @@ #include "merchant-database/iterate_all_donau_instances.h" #include "merchant-database/get_donau_instance_by_serial.h" #include "merchant-database/update_donau_instance.h" -#include "merchant-database/upsert_donau_keys.h" +#include "merchant-database/insert_donau_keys.h" #include "merchant-database/event_listen.h" #include "merchant-database/preflight.h" #include "merchant-database/start.h" @@ -339,7 +339,7 @@ insert_donau_keys_data (const struct DONAU_Keys *keys, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Inserting Donau keys into the database %s\n", keys->donau_url); - return TALER_MERCHANTDB_upsert_donau_keys (pg, + return TALER_MERCHANTDB_insert_donau_keys (pg, keys, first_retry); } diff --git a/src/backend/taler-merchant-exchangekeyupdate.c b/src/backend/taler-merchant-exchangekeyupdate.c @@ -40,7 +40,7 @@ struct Exchange; #include "merchant-database/event_listen.h" #include "merchant-database/insert_exchange_account.h" #include "merchant-database/get_exchange_keys.h" -#include "merchant-database/store_wire_fee_by_exchange.h" +#include "merchant-database/insert_wire_fee.h" /** * Maximum frequency for the exchange interaction. @@ -450,7 +450,7 @@ insert_keys_data (const struct TALER_EXCHANGE_Keys *keys, GNUNET_CRYPTO_hash (wire_method, strlen (wire_method) + 1, &h_wire_method); - qs = TALER_MERCHANTDB_store_wire_fee_by_exchange ( + qs = TALER_MERCHANTDB_insert_wire_fee ( pg, &keys->master_pub, &h_wire_method, diff --git a/src/backend/taler-merchant-httpd_delete-management-instances-INSTANCE.c b/src/backend/taler-merchant-httpd_delete-management-instances-INSTANCE.c @@ -23,9 +23,9 @@ #include <taler/taler_json_lib.h> #include <taler/taler_dbevents.h> #include "taler-merchant-httpd_mfa.h" -#include "merchant-database/delete_instance_private_key.h" +#include "merchant-database/update_to_instance_private_key_deleted.h" #include "merchant-database/event_notify.h" -#include "merchant-database/purge_instance.h" +#include "merchant-database/delete_instance.h" /** * Handle a DELETE "/instances/$ID" request. @@ -73,11 +73,11 @@ delete_instances_ID (struct TMH_HandlerContext *hc, "yes")); } if (purge) - qs = TALER_MERCHANTDB_purge_instance (TMH_db, - mi->settings.id); + qs = TALER_MERCHANTDB_delete_instance (TMH_db, + mi->settings.id); else - qs = TALER_MERCHANTDB_delete_instance_private_key (TMH_db, - mi->settings.id); + qs = TALER_MERCHANTDB_update_to_instance_private_key_deleted (TMH_db, + mi->settings.id); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: diff --git a/src/backend/taler-merchant-httpd_delete-private-accounts-H_WIRE.c b/src/backend/taler-merchant-httpd_delete-private-accounts-H_WIRE.c @@ -23,7 +23,7 @@ #include <taler/taler_json_lib.h> #include <taler/taler_dbevents.h> #include "taler-merchant-httpd_mfa.h" -#include "merchant-database/inactivate_account.h" +#include "merchant-database/update_to_account_inactive.h" #include "merchant-database/event_notify.h" @@ -69,9 +69,9 @@ TMH_private_delete_account_ID (const struct TMH_RequestHandler *rh, : MHD_NO; } } - qs = TALER_MERCHANTDB_inactivate_account (TMH_db, - mi->settings.id, - &h_wire); + qs = TALER_MERCHANTDB_update_to_account_inactive (TMH_db, + mi->settings.id, + &h_wire); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: diff --git a/src/backend/taler-merchant-httpd_get-private-orders-ORDER_ID.c b/src/backend/taler-merchant-httpd_get-private-orders-ORDER_ID.c @@ -38,7 +38,7 @@ #include "merchant-database/get_order_by_fulfillment.h" #include "merchant-database/iterate_refunds_detailed.h" #include "merchant-database/iterate_transfer_details_by_order.h" -#include "merchant-database/mark_order_wired.h" +#include "merchant-database/update_to_contract_terms_wired.h" #include "merchant-database/preflight.h" #include "merchant-database/event_listen.h" @@ -1681,8 +1681,8 @@ phase_check_local_transfers (struct GetOrderRequestContext *gorc) { /* expect_total <= gorc->deposits_total: good: we got the wire transfer */ gorc->wired = true; - qs = TALER_MERCHANTDB_mark_order_wired (TMH_db, - gorc->order_serial); + qs = TALER_MERCHANTDB_update_to_contract_terms_wired (TMH_db, + gorc->order_serial); GNUNET_break (qs >= 0); /* just warn if transaction failed */ TMH_notify_order_change (hc->instance, TMH_OSF_PAID diff --git a/src/backend/taler-merchant-httpd_mfa.c b/src/backend/taler-merchant-httpd_mfa.c @@ -25,7 +25,7 @@ #include "platform.h" #include "taler-merchant-httpd.h" #include "taler-merchant-httpd_mfa.h" -#include "merchant-database/create_mfa_challenge.h" +#include "merchant-database/insert_mfa_challenge.h" #include "merchant-database/get_mfa_challenge.h" @@ -272,7 +272,7 @@ mfa_challenge_start ( "%04llu-%04llu", challenge_num / 10000, challenge_num % 10000); - qs = TALER_MERCHANTDB_create_mfa_challenge (TMH_db, + qs = TALER_MERCHANTDB_insert_mfa_challenge (TMH_db, instance_name, op, &h_body, diff --git a/src/backend/taler-merchant-httpd_post-challenge-ID-confirm.c b/src/backend/taler-merchant-httpd_post-challenge-ID-confirm.c @@ -26,7 +26,7 @@ #include "taler-merchant-httpd.h" #include "taler-merchant-httpd_mfa.h" #include "taler-merchant-httpd_post-challenge-ID-confirm.h" -#include "merchant-database/solve_mfa_challenge.h" +#include "merchant-database/do_solve_mfa_challenge.h" enum MHD_Result @@ -91,14 +91,14 @@ TMH_post_challenge_ID_confirm (const struct TMH_RequestHandler *rh, } } - qs = TALER_MERCHANTDB_solve_mfa_challenge (TMH_db, - challenge_serial, - &h_body, - (NULL == xtan) + qs = TALER_MERCHANTDB_do_solve_mfa_challenge (TMH_db, + challenge_serial, + &h_body, + (NULL == xtan) ? tan : xtan, - &solved, - &retry_counter); + &solved, + &retry_counter); GNUNET_free (xtan); switch (qs) { diff --git a/src/backend/taler-merchant-httpd_post-orders-ORDER_ID-abort.c b/src/backend/taler-merchant-httpd_post-orders-ORDER_ID-abort.c @@ -34,7 +34,7 @@ struct RefundDetails; #include "taler-merchant-httpd_post-orders-ORDER_ID-abort.h" #include "merchant-database/iterate_deposits.h" #include "merchant-database/get_order_status.h" -#include "merchant-database/refund_coin.h" +#include "merchant-database/insert_refund_by_coin.h" #include "merchant-database/preflight.h" #include "merchant-database/start.h" #include "merchant-database/set_instance.h" @@ -708,13 +708,13 @@ refund_coins (void *cls, rdi->found_deposit = true; rdi->amount_with_fee = *amount_with_fee; /* Store refund in DB */ - qs = TALER_MERCHANTDB_refund_coin (TMH_db, - ac->hc->instance->settings.id, - &ac->h_contract_terms, - now, - coin_pub, - /* justification */ - "incomplete abortment aborted"); + qs = TALER_MERCHANTDB_insert_refund_by_coin (TMH_db, + ac->hc->instance->settings.id, + &ac->h_contract_terms, + now, + coin_pub, + /* justification */ + "incomplete abortment aborted"); if (0 > qs) { /* Always report on hard error to enable diagnostics */ diff --git a/src/backend/taler-merchant-httpd_post-orders-ORDER_ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ORDER_ID-pay.c @@ -52,7 +52,7 @@ struct ExchangeGroup; #include <donau/donau_service.h> #include <donau/donau_util.h> #include <donau/donau_json_lib.h> -#include "merchant-database/increment_money_pots.h" +#include "merchant-database/update_money_pot_totals.h" #include "merchant-database/insert_deposit.h" #include "merchant-database/insert_deposit_confirmation.h" #include "merchant-database/insert_issued_token.h" @@ -66,7 +66,7 @@ struct ExchangeGroup; #include "merchant-database/set_instance.h" #include "merchant-database/iterate_spent_tokens_by_order.h" #include "merchant-database/get_token_family_key.h" -#include "merchant-database/mark_contract_paid.h" +#include "merchant-database/update_to_contract_terms_paid.h" #include "merchant-database/iterate_order_blinded_sigs.h" #include "merchant-database/start.h" #include "merchant-database/preflight.h" @@ -3147,11 +3147,11 @@ phase_execute_pay_transaction (struct PayContext *pc) { enum GNUNET_DB_QueryStatus qs; - qs = TALER_MERCHANTDB_mark_contract_paid (TMH_db, - instance_id, - &pc->check_contract.h_contract_terms, - pc->parse_pay.session_id, - pc->parse_wallet_data.choice_index); + qs = TALER_MERCHANTDB_update_to_contract_terms_paid (TMH_db, + instance_id, + &pc->check_contract.h_contract_terms, + pc->parse_pay.session_id, + pc->parse_wallet_data.choice_index); if (qs < 0) { TALER_MERCHANTDB_rollback (TMH_db); @@ -3176,7 +3176,7 @@ phase_execute_pay_transaction (struct PayContext *pc) "Incrementing %u money pots by %s\n", pc->compute_money_pots.num_pots, TALER_amount2s (&pc->compute_money_pots.increments[0])); - qs = TALER_MERCHANTDB_increment_money_pots ( + qs = TALER_MERCHANTDB_update_money_pot_totals ( TMH_db, instance_id, pc->compute_money_pots.num_pots, diff --git a/src/backend/taler-merchant-httpd_post-private-accounts.c b/src/backend/taler-merchant-httpd_post-private-accounts.c @@ -30,7 +30,7 @@ #include <taler/taler_json_lib.h> #include "taler-merchant-httpd_mfa.h" #include <regex.h> -#include "merchant-database/activate_account.h" +#include "merchant-database/do_insert_account.h" #include "merchant-database/iterate_accounts_by_instance.h" #include "merchant-database/preflight.h" @@ -404,12 +404,12 @@ TMH_private_post_account (const struct TMH_RequestHandler *rh, bool conflict; TALER_MERCHANTDB_preflight (TMH_db); - qs = TALER_MERCHANTDB_activate_account (TMH_db, - &ad, - &h_wire, - &salt, - &not_found, - &conflict); + qs = TALER_MERCHANTDB_do_insert_account (TMH_db, + &ad, + &h_wire, + &salt, + &not_found, + &conflict); switch (qs) { case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: diff --git a/src/backend/taler-merchant-httpd_post-private-orders-ORDER_ID-refund.c b/src/backend/taler-merchant-httpd_post-private-orders-ORDER_ID-refund.c @@ -29,7 +29,7 @@ #include "taler-merchant-httpd_get-private-orders.h" #include "taler-merchant-httpd_helper.h" #include "taler-merchant-httpd_get-exchanges.h" -#include "merchant-database/increase_refund.h" +#include "merchant-database/do_increase_refund.h" #include "merchant-database/get_contract_terms.h" #include "merchant-database/get_order_summary.h" #include "merchant-database/start.h" @@ -306,13 +306,13 @@ TMH_private_post_orders_ID_refund ( TALER_EC_GENERIC_DB_START_FAILED, NULL); } - rs = TALER_MERCHANTDB_increase_refund (TMH_db, - hc->instance->settings.id, - hc->infix, - &refund, - &get_refund_limit, - NULL, - reason); + rs = TALER_MERCHANTDB_do_increase_refund (TMH_db, + hc->instance->settings.id, + hc->infix, + &refund, + &get_refund_limit, + NULL, + reason); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "increase refund returned %d\n", rs); diff --git a/src/backend/taler-merchant-httpd_post-private-orders.c b/src/backend/taler-merchant-httpd_post-private-orders.c @@ -51,7 +51,7 @@ #include "merchant-database/event_listen.h" #include "merchant-database/event_notify.h" #include "merchant-database/preflight.h" -#include "merchant-database/expire_locks.h" +#include "merchant-database/do_expire_locks.h" #include "merchant-database/get_missing_money_pot.h" #include "merchant-database/insert_order.h" #include "merchant-database/insert_order_lock.h" @@ -63,7 +63,7 @@ #include "merchant-database/iterate_token_family_keys.h" #include "merchant-database/iterate_donau_instances_filtered.h" #include "merchant-database/get_otp.h" -#include "merchant-database/unlock_inventory.h" +#include "merchant-database/delete_inventory_lock.h" /** @@ -1002,8 +1002,8 @@ execute_transaction (struct OrderContext *oc) /* Migrate locks from UUIDs to new order: first release old locks */ for (unsigned int i = 0; i<oc->parse_request.uuids_length; i++) { - qs = TALER_MERCHANTDB_unlock_inventory (TMH_db, - &oc->parse_request.uuids[i]); + qs = TALER_MERCHANTDB_delete_inventory_lock (TMH_db, + &oc->parse_request.uuids[i]); if (qs < 0) { TALER_MERCHANTDB_rollback (TMH_db); @@ -4054,7 +4054,7 @@ phase_parse_request (struct OrderContext *oc) "Refund delay is %s\n", GNUNET_TIME_relative2s (oc->parse_request.refund_delay, false)); - TALER_MERCHANTDB_expire_locks (TMH_db); + TALER_MERCHANTDB_do_expire_locks (TMH_db); if (NULL != otp_id) { struct TALER_MERCHANTDB_OtpDeviceDetails td; diff --git a/src/backend/taler-merchant-httpd_post-private-products-PRODUCT_ID-lock.c b/src/backend/taler-merchant-httpd_post-private-products-PRODUCT_ID-lock.c @@ -26,8 +26,8 @@ #include "taler-merchant-httpd_post-private-products-PRODUCT_ID-lock.h" #include "taler-merchant-httpd_helper.h" #include <taler/taler_json_lib.h> -#include "merchant-database/expire_locks.h" -#include "merchant-database/lock_product.h" +#include "merchant-database/do_expire_locks.h" +#include "merchant-database/insert_inventory_lock.h" #include "merchant-database/get_product.h" @@ -78,7 +78,7 @@ TMH_private_post_products_ID_lock ( } TMH_uuid_from_string (uuids, &uuid); - TALER_MERCHANTDB_expire_locks (TMH_db); + TALER_MERCHANTDB_do_expire_locks (TMH_db); { struct TALER_MERCHANTDB_ProductDetails pd = { 0 }; size_t num_categories; @@ -163,13 +163,13 @@ TMH_private_post_products_ID_lock ( } } quantity = normalized_quantity; - qs = TALER_MERCHANTDB_lock_product (TMH_db, - mi->settings.id, - product_id, - &uuid, - quantity, - normalized_quantity_frac, - GNUNET_TIME_relative_to_timestamp (duration)); + qs = TALER_MERCHANTDB_insert_inventory_lock (TMH_db, + mi->settings.id, + product_id, + &uuid, + quantity, + normalized_quantity_frac, + GNUNET_TIME_relative_to_timestamp (duration)); TALER_MERCHANTDB_product_details_free (&pd); } switch (qs) diff --git a/src/backend/taler-merchant-reconciliation.c b/src/backend/taler-merchant-reconciliation.c @@ -30,7 +30,7 @@ struct Inquiry; #include "taler/taler_merchant_bank_lib.h" #include "merchantdb_lib.h" #include "merchantdb_lib.h" -#include "merchant-database/finalize_transfer_status.h" +#include "merchant-database/update_to_transfer_finalized.h" #include "merchant-database/insert_transfer_details.h" #include "merchant-database/iterate_deposits_by_contract_and_coin.h" #include "merchant-database/get_wire_fee.h" @@ -965,14 +965,14 @@ wire_transfer_cb (struct Inquiry *w, { enum GNUNET_DB_QueryStatus qs; - qs = TALER_MERCHANTDB_finalize_transfer_status (pg, - w->exchange->exchange_url, - &w->wtid, - &td->h_details, - &td->total_amount, - &td->wire_fee, - &td->exchange_pub, - &td->exchange_sig); + qs = TALER_MERCHANTDB_update_to_transfer_finalized (pg, + w->exchange->exchange_url, + &w->wtid, + &td->h_details, + &td->total_amount, + &td->wire_fee, + &td->exchange_pub, + &td->exchange_sig); if (qs < 0) { GNUNET_break (0); diff --git a/src/backenddb/activate_account.c b/src/backenddb/activate_account.c @@ -1,80 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/activate_account.c - * @brief Implementation of the activate_account function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/activate_account.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_activate_account ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const struct TALER_MERCHANTDB_AccountDetails *account_details, - struct TALER_MerchantWireHashP *h_wire, - struct TALER_WireSaltP *salt, - bool *not_found, - bool *conflict) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&account_details->h_wire), - GNUNET_PQ_query_param_auto_from_type (&account_details->salt), - GNUNET_PQ_query_param_string (account_details->payto_uri.full_payto), - NULL ==account_details->credit_facade_url - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (account_details->credit_facade_url), - NULL == account_details->credit_facade_credentials - ? GNUNET_PQ_query_param_null () - : TALER_PQ_query_param_json (account_details->credit_facade_credentials), - NULL == account_details->extra_wire_subject_metadata - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string ( - account_details->extra_wire_subject_metadata), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("not_found", - not_found), - GNUNET_PQ_result_spec_bool ("conflict", - conflict), - GNUNET_PQ_result_spec_auto_from_type ("h_wire", - h_wire), - GNUNET_PQ_result_spec_auto_from_type ("salt", - salt), - GNUNET_PQ_result_spec_end - }; - - GNUNET_assert (account_details->active); - GNUNET_assert (NULL != pg->current_merchant_id); - GNUNET_assert (0 == strcmp (account_details->instance_id, - pg->current_merchant_id)); - TMH_PQ_prepare_anon (pg, - "SELECT " - " out_h_wire AS h_wire" - " ,out_salt AS salt" - " ,out_conflict AS conflict" - " ,out_not_found AS not_found" - " FROM merchant_do_activate_account" - " ($1,$2,$3,$4,$5,$6);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "", - params, - rs); -} diff --git a/src/backenddb/create_mfa_challenge.c b/src/backenddb/create_mfa_challenge.c @@ -1,86 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/create_mfa_challenge.c - * @brief Implementation of the create_mfa_challenge function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "taler/taler_merchant_util.h" -#include "merchantdb_lib.h" -#include "merchant-database/create_mfa_challenge.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_create_mfa_challenge ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_name, - enum TALER_MERCHANT_MFA_CriticalOperation op, - const struct TALER_MERCHANT_MFA_BodyHash *h_body, - const struct TALER_MERCHANT_MFA_BodySalt *salt, - const char *code, - struct GNUNET_TIME_Absolute expiration_date, - struct GNUNET_TIME_Absolute retransmission_date, - enum TALER_MERCHANT_MFA_Channel tan_channel, - const char *required_address, - uint64_t *challenge_id) -{ - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); - const char *op_str = TALER_MERCHANT_MFA_co_to_string (op); - const char *channel_str = TALER_MERCHANT_MFA_channel_to_string (tan_channel); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_body), - GNUNET_PQ_query_param_auto_from_type (salt), - GNUNET_PQ_query_param_string (op_str), - GNUNET_PQ_query_param_string (code), - GNUNET_PQ_query_param_absolute_time (&now), /* $5 */ - GNUNET_PQ_query_param_absolute_time (&expiration_date), - GNUNET_PQ_query_param_absolute_time (&retransmission_date), - GNUNET_PQ_query_param_string (channel_str), - GNUNET_PQ_query_param_string (required_address), /* $9 */ - GNUNET_PQ_query_param_string (instance_name), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("challenge_id", - challenge_id), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "create_mfa_challenge", - "INSERT INTO merchant.tan_challenges" - " (h_body" - " ,salt" - " ,op" - " ,code" - " ,creation_date" - " ,expiration_date" - " ,retransmission_date" - " ,retry_counter" /* always set to 3 */ - " ,tan_channel" - " ,required_address" - " ,instance_name)" - " VALUES" - " ($1, $2, $3, $4, $5, $6, $7, 3, $8, $9, $10)" - " RETURNING challenge_id;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "create_mfa_challenge", - params, - rs); -} diff --git a/src/backenddb/delete_instance.c b/src/backenddb/delete_instance.c @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/delete_instance.c + * @brief Implementation of the delete_instance function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/delete_instance.h" +#include "helper.h" + + +/** + * Purge an instance and all associated information from our database. + * Highly likely to cause undesired data loss. Use with caution. + * + * @param pg database context + * @param merchant_id identifier of the instance + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_delete_instance ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *merchant_id) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (merchant_id), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "purge_instance", + "DELETE FROM merchant.merchant_instances" + " WHERE merchant_id = $1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "purge_instance", + params); +} diff --git a/src/backenddb/delete_instance_private_key.c b/src/backenddb/delete_instance_private_key.c @@ -1,45 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/delete_instance_private_key.c - * @brief Implementation of the delete_instance_private_key function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/delete_instance_private_key.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_delete_instance_private_key ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *merchant_id) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (merchant_id), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "delete_instance_private_key", - "UPDATE merchant.merchant_instances" - " SET merchant_priv = NULL" - " WHERE merchant_id = $1"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "delete_instance_private_key", - params); -} diff --git a/src/backenddb/delete_inventory_lock.c b/src/backenddb/delete_inventory_lock.c @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/delete_inventory_lock.c + * @brief Implementation of the delete_inventory_lock function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/delete_inventory_lock.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_delete_inventory_lock ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const struct GNUNET_Uuid *uuid) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (uuid), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (NULL != pg->current_merchant_id); + TMH_PQ_prepare_anon (pg, + "DELETE" + " FROM merchant_inventory_locks" + " WHERE lock_uuid=$1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "", + params); +} diff --git a/src/backenddb/do_expire_locks.c b/src/backenddb/do_expire_locks.c @@ -0,0 +1,60 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/do_expire_locks.c + * @brief Implementation of the do_expire_locks function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/do_expire_locks.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_do_expire_locks (struct TALER_MERCHANTDB_PostgresContext *pg) +{ + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + uint64_t total; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("expire_locks", + &total), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (pg, + "expire_locks", + "SELECT expire_locks($1) " + " AS expire_locks"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "expire_locks", + params, + rs); + if (qs < 0) + { + GNUNET_break (0); + return qs; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Released %llu locks for the current instance\n", + (unsigned long long) total); + return (enum GNUNET_DB_QueryStatus) total; +} diff --git a/src/backenddb/expire_locks.sql b/src/backenddb/do_expire_locks.sql diff --git a/src/backenddb/do_increase_refund.c b/src/backenddb/do_increase_refund.c @@ -0,0 +1,740 @@ +/* + This file is part of TALER + Copyright (C) 2022-2024 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/do_increase_refund.c + * @brief Implementation of the do_increase_refund function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/do_increase_refund.h" +#include "helper.h" + + +/** + * Information about refund limits per exchange. + */ +struct ExchangeLimit +{ + /** + * Kept in a DLL. + */ + struct ExchangeLimit *next; + + /** + * Kept in a DLL. + */ + struct ExchangeLimit *prev; + + /** + * Exchange the limit is about. + */ + char *exchange_url; + + /** + * Refund amount remaining at this exchange. + */ + struct TALER_Amount remaining_refund_limit; + +}; + + +/** + * Closure for #process_refund_cb(). + */ +struct FindRefundContext +{ + + /** + * Plugin context. + */ + struct TALER_MERCHANTDB_PostgresContext *pg; + + /** + * Updated to reflect total amount refunded so far. + */ + struct TALER_Amount refunded_amount; + + /** + * Set to the largest refund transaction ID encountered. + */ + uint64_t max_rtransaction_id; + + /** + * Set to true on hard errors. + */ + bool err; +}; + + +/** + * Closure for #process_deposits_for_refund_cb(). + */ +struct InsertRefundContext +{ + /** + * Used to provide a connection to the db + */ + struct TALER_MERCHANTDB_PostgresContext *pg; + + /** + * Head of DLL of per-exchange refund limits. + */ + struct ExchangeLimit *el_head; + + /** + * Tail of DLL of per-exchange refund limits. + */ + struct ExchangeLimit *el_tail; + + /** + * Amount to which increase the refund for this contract + */ + const struct TALER_Amount *refund; + + /** + * Human-readable reason behind this refund + */ + const char *reason; + + /** + * Function to call to determine per-exchange limits. + * NULL for no limits. + */ + TALER_MERCHANTDB_OperationLimitCallback olc; + + /** + * Closure for @e olc. + */ + void *olc_cls; + + /** + * Transaction status code. + */ + enum TALER_MERCHANTDB_RefundStatus rs; + + /** + * Did we have to cap refunds of any coin + * due to legal limits? + */ + bool legal_capped; + +}; + + +/** + * Data extracted per coin. + */ +struct RefundCoinData +{ + + /** + * Public key of a coin. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Amount deposited for this coin. + */ + struct TALER_Amount deposited_with_fee; + + /** + * Amount refunded already for this coin. + */ + struct TALER_Amount refund_amount; + + /** + * Order serial (actually not really per-coin). + */ + uint64_t order_serial; + + /** + * Maximum rtransaction_id for this coin so far. + */ + uint64_t max_rtransaction_id; + + /** + * Exchange this coin was issued by. + */ + char *exchange_url; + +}; + + +/** + * Find an exchange record for the refund limit enforcement. + * + * @param irc refund context + * @param exchange_url base URL of the exchange + */ +static struct ExchangeLimit * +find_exchange (struct InsertRefundContext *irc, + const char *exchange_url) +{ + if (NULL == irc->olc) + return NULL; /* no limits */ + /* Check if entry exists, if so, do nothing */ + for (struct ExchangeLimit *el = irc->el_head; + NULL != el; + el = el->next) + if (0 == strcmp (exchange_url, + el->exchange_url)) + return el; + return NULL; +} + + +/** + * Setup an exchange for the refund limit enforcement and initialize the + * original refund limit for the exchange. + * + * @param irc refund context + * @param exchange_url base URL of the exchange + * @return limiting data structure + */ +static struct ExchangeLimit * +setup_exchange (struct InsertRefundContext *irc, + const char *exchange_url) +{ + struct ExchangeLimit *el; + + if (NULL == irc->olc) + return NULL; /* no limits */ + /* Check if entry exists, if so, do nothing */ + if (NULL != + (el = find_exchange (irc, + exchange_url))) + return el; + el = GNUNET_new (struct ExchangeLimit); + el->exchange_url = GNUNET_strdup (exchange_url); + /* olc only lowers, so set to the maximum amount we care about */ + el->remaining_refund_limit = *irc->refund; + irc->olc (irc->olc_cls, + exchange_url, + &el->remaining_refund_limit); + GNUNET_CONTAINER_DLL_insert (irc->el_head, + irc->el_tail, + el); + return el; +} + + +/** + * Lower the remaining refund limit in @a el by @a val. + * + * @param[in,out] el exchange limit to lower + * @param val amount to lower limit by + * @return true on success, false on failure + */ +static bool +lower_balance (struct ExchangeLimit *el, + const struct TALER_Amount *val) +{ + if (NULL == el) + return true; + return 0 <= TALER_amount_subtract (&el->remaining_refund_limit, + &el->remaining_refund_limit, + val); +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure, our `struct FindRefundContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +process_refund_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct FindRefundContext *ictx = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + /* Sum up existing refunds */ + struct TALER_Amount acc; + uint64_t rtransaction_id; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_amount_with_currency ("refund_amount", + &acc), + GNUNET_PQ_result_spec_uint64 ("rtransaction_id", + &rtransaction_id), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ictx->err = true; + return; + } + if (GNUNET_OK != + TALER_amount_cmp_currency (&ictx->refunded_amount, + &acc)) + { + GNUNET_break (0); + ictx->err = true; + return; + } + if (0 > + TALER_amount_add (&ictx->refunded_amount, + &ictx->refunded_amount, + &acc)) + { + GNUNET_break (0); + ictx->err = true; + return; + } + ictx->max_rtransaction_id = GNUNET_MAX (ictx->max_rtransaction_id, + rtransaction_id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found refund of %s\n", + TALER_amount2s (&acc)); + } +} + + +/** + * Helper function to prepare statement to select refunds + * + * @param pg context to prepare statement in + * @return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS on success + */ +static enum GNUNET_DB_QueryStatus +prep_select_refund (struct TALER_MERCHANTDB_PostgresContext *pg) +{ + TMH_PQ_prepare_anon (pg, + "SELECT" + " refund_amount" + ",rtransaction_id" + " FROM merchant_refunds" + " WHERE coin_pub=$1" + " AND order_serial=$2"); + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; +} + + +/** + * Helper function to prepare statement to insert refund + * + * @param pg context to prepare statement in + * @return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS on success + */ +static enum GNUNET_DB_QueryStatus +prep_insert_refund (struct TALER_MERCHANTDB_PostgresContext *pg) +{ + // FIXME: return 'refund_serial' from this INSERT statement for #10577 + TMH_PQ_prepare_anon (pg, + "INSERT INTO merchant_refunds" + "(order_serial" + ",rtransaction_id" + ",refund_timestamp" + ",coin_pub" + ",reason" + ",refund_amount" + ") VALUES" + "($1, $2, $3, $4, $5, $6)"); + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; +} + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure, our `struct InsertRefundContext` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +process_deposits_for_refund_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct InsertRefundContext *ctx = cls; + struct TALER_MERCHANTDB_PostgresContext *pg = ctx->pg; + struct TALER_Amount current_refund; + struct RefundCoinData rcd[GNUNET_NZL (num_results)]; + struct GNUNET_TIME_Timestamp now; + + now = GNUNET_TIME_timestamp_get (); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (ctx->refund->currency, + &current_refund)); + memset (rcd, + 0, + sizeof (rcd)); + /* Pass 1: Collect amount of existing refunds into current_refund. + * Also store existing refunded amount for each deposit in deposit_refund. */ + for (unsigned int i = 0; i<num_results; i++) + { + struct RefundCoinData *rcdi = &rcd[i]; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &rcdi->coin_pub), + GNUNET_PQ_result_spec_uint64 ("order_serial", + &rcdi->order_serial), + GNUNET_PQ_result_spec_string ("exchange_url", + &rcdi->exchange_url), + TALER_PQ_result_spec_amount_with_currency ("amount_with_fee", + &rcdi->deposited_with_fee), + GNUNET_PQ_result_spec_end + }; + struct FindRefundContext ictx = { + .pg = pg, + }; + struct ExchangeLimit *el; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + } + el = setup_exchange (ctx, + rcdi->exchange_url); + if (0 != strcmp (rcdi->deposited_with_fee.currency, + ctx->refund->currency)) + { + GNUNET_break_op (0); + ctx->rs = TALER_MERCHANTDB_RS_BAD_CURRENCY; + goto cleanup; + } + + { + enum GNUNET_DB_QueryStatus ires; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&rcdi->coin_pub), + GNUNET_PQ_query_param_uint64 (&rcdi->order_serial), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero ( + ctx->refund->currency, + &ictx.refunded_amount)); + ires = prep_select_refund (pg); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != ires) + { + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + } + ires = GNUNET_PQ_eval_prepared_multi_select ( + pg->conn, + "", + params, + &process_refund_cb, + &ictx); + if ( (ictx.err) || + (GNUNET_DB_STATUS_HARD_ERROR == ires) ) + { + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + } + if (GNUNET_DB_STATUS_SOFT_ERROR == ires) + { + ctx->rs = TALER_MERCHANTDB_RS_SOFT_ERROR; + goto cleanup; + } + } + if (0 > + TALER_amount_add (&current_refund, + &current_refund, + &ictx.refunded_amount)) + { + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + } + rcdi->refund_amount = ictx.refunded_amount; + rcdi->max_rtransaction_id = ictx.max_rtransaction_id; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Existing refund for coin %s is %s\n", + TALER_B2S (&rcdi->coin_pub), + TALER_amount2s (&ictx.refunded_amount)); + GNUNET_break (lower_balance (el, + &ictx.refunded_amount)); + } /* end for all deposited coins */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Total existing refund is %s\n", + TALER_amount2s (&current_refund)); + + /* stop immediately if we are 'done' === amount already + * refunded. */ + if (0 >= TALER_amount_cmp (ctx->refund, + &current_refund)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Existing refund of %s at or above requested refund. Finished early.\n", + TALER_amount2s (&current_refund)); + ctx->rs = TALER_MERCHANTDB_RS_SUCCESS; + goto cleanup; + } + + /* Phase 2: Try to increase current refund until it matches desired refund */ + for (unsigned int i = 0; i<num_results; i++) + { + struct RefundCoinData *rcdi = &rcd[i]; + const struct TALER_Amount *increment; + struct TALER_Amount left; + struct TALER_Amount remaining_refund; + struct ExchangeLimit *el; + + /* How much of the coin is left after the existing refunds? */ + if (0 > + TALER_amount_subtract (&left, + &rcdi->deposited_with_fee, + &rcdi->refund_amount)) + { + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + } + + if (TALER_amount_is_zero (&left)) + { + /* coin was fully refunded, move to next coin */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Coin %s fully refunded, moving to next coin\n", + TALER_B2S (&rcdi->coin_pub)); + continue; + } + el = find_exchange (ctx, + rcdi->exchange_url); + if ( (NULL != el) && + (TALER_amount_is_zero (&el->remaining_refund_limit)) ) + { + /* legal limit reached, move to next coin */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Exchange %s legal limit reached, moving to next coin\n", + rcdi->exchange_url); + continue; + } + + rcdi->max_rtransaction_id++; + /* How much of the refund is still to be paid back? */ + if (0 > + TALER_amount_subtract (&remaining_refund, + ctx->refund, + &current_refund)) + { + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + } + /* cap by legal limit */ + if (NULL != el) + { + struct TALER_Amount new_limit; + + TALER_amount_min (&new_limit, + &remaining_refund, + &el->remaining_refund_limit); + if (0 != TALER_amount_cmp (&new_limit, + &remaining_refund)) + { + remaining_refund = new_limit; + ctx->legal_capped = true; + } + } + /* By how much will we increase the refund for this coin? */ + if (0 >= TALER_amount_cmp (&remaining_refund, + &left)) + { + /* remaining_refund <= left */ + increment = &remaining_refund; + } + else + { + increment = &left; + } + + if (0 > + TALER_amount_add (&current_refund, + &current_refund, + increment)) + { + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + } + GNUNET_break (lower_balance (el, + increment)); + /* actually run the refund */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Coin %s deposit amount is %s\n", + TALER_B2S (&rcdi->coin_pub), + TALER_amount2s (&rcdi->deposited_with_fee)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Coin %s refund will be incremented by %s\n", + TALER_B2S (&rcdi->coin_pub), + TALER_amount2s (increment)); + { + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&rcdi->order_serial), + GNUNET_PQ_query_param_uint64 (&rcdi->max_rtransaction_id), /* already inc'ed */ + GNUNET_PQ_query_param_timestamp (&now), + GNUNET_PQ_query_param_auto_from_type (&rcdi->coin_pub), + GNUNET_PQ_query_param_string (ctx->reason), + TALER_PQ_query_param_amount_with_currency (pg->conn, + increment), + GNUNET_PQ_query_param_end + }; + + qs = prep_insert_refund (pg); + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) + { + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + } + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "", + params); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; + goto cleanup; + case GNUNET_DB_STATUS_SOFT_ERROR: + ctx->rs = TALER_MERCHANTDB_RS_SOFT_ERROR; + goto cleanup; + default: + ctx->rs = (enum TALER_MERCHANTDB_RefundStatus) qs; + break; + } + } + + /* stop immediately if we are done */ + if (0 == TALER_amount_cmp (ctx->refund, + &current_refund)) + { + ctx->rs = TALER_MERCHANTDB_RS_SUCCESS; + goto cleanup; + } + } + + if (ctx->legal_capped) + { + ctx->rs = TALER_MERCHANTDB_RS_LEGAL_FAILURE; + goto cleanup; + } + /** + * We end up here if not all of the refund has been covered. + * Although this should be checked as the business should never + * issue a refund bigger than the contract's actual price, we cannot + * rely upon the frontend being correct. + */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "The refund of %s is bigger than the order's value\n", + TALER_amount2s (ctx->refund)); + ctx->rs = TALER_MERCHANTDB_RS_TOO_HIGH; +cleanup: + for (unsigned int i = 0; i<num_results; i++) + GNUNET_free (rcd[i].exchange_url); +} + + +enum TALER_MERCHANTDB_RefundStatus +TALER_MERCHANTDB_do_increase_refund ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + const char *order_id, + const struct TALER_Amount *refund, + TALER_MERCHANTDB_OperationLimitCallback olc, + void *olc_cls, + const char *reason) +{ + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (order_id), + GNUNET_PQ_query_param_end + }; + struct InsertRefundContext ctx = { + .pg = pg, + .refund = refund, + .olc = olc, + .olc_cls = olc_cls, + .reason = reason, + }; + + GNUNET_assert (NULL != pg->current_merchant_id); + GNUNET_assert (0 == strcmp (instance_id, + pg->current_merchant_id)); + TMH_PQ_prepare_anon (pg, + "SELECT" + " dep.coin_pub" + ",dco.order_serial" + ",dep.amount_with_fee" + ",dco.exchange_url" + " FROM merchant_deposits dep" + " JOIN merchant_deposit_confirmations dco" + " USING (deposit_confirmation_serial)" + " WHERE order_serial=" + " (SELECT order_serial" + " FROM merchant_contract_terms" + " WHERE order_id=$1" + " AND paid)"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Asked to refund %s on order %s\n", + TALER_amount2s (refund), + order_id); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "", + params, + &process_deposits_for_refund_cb, + &ctx); + { + struct ExchangeLimit *el; + + while (NULL != (el = ctx.el_head)) + { + GNUNET_CONTAINER_DLL_remove (ctx.el_head, + ctx.el_tail, + el); + GNUNET_free (el->exchange_url); + GNUNET_free (el); + } + } + switch (qs) + { + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* never paid, means we clearly cannot refund anything */ + return TALER_MERCHANTDB_RS_NO_SUCH_ORDER; + case GNUNET_DB_STATUS_SOFT_ERROR: + return TALER_MERCHANTDB_RS_SOFT_ERROR; + case GNUNET_DB_STATUS_HARD_ERROR: + return TALER_MERCHANTDB_RS_HARD_ERROR; + default: + /* Got one or more deposits */ + return ctx.rs; + } +} diff --git a/src/backenddb/do_insert_account.c b/src/backenddb/do_insert_account.c @@ -0,0 +1,80 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/do_insert_account.c + * @brief Implementation of the do_insert_account function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/do_insert_account.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_do_insert_account ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const struct TALER_MERCHANTDB_AccountDetails *account_details, + struct TALER_MerchantWireHashP *h_wire, + struct TALER_WireSaltP *salt, + bool *not_found, + bool *conflict) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&account_details->h_wire), + GNUNET_PQ_query_param_auto_from_type (&account_details->salt), + GNUNET_PQ_query_param_string (account_details->payto_uri.full_payto), + NULL ==account_details->credit_facade_url + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (account_details->credit_facade_url), + NULL == account_details->credit_facade_credentials + ? GNUNET_PQ_query_param_null () + : TALER_PQ_query_param_json (account_details->credit_facade_credentials), + NULL == account_details->extra_wire_subject_metadata + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string ( + account_details->extra_wire_subject_metadata), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("not_found", + not_found), + GNUNET_PQ_result_spec_bool ("conflict", + conflict), + GNUNET_PQ_result_spec_auto_from_type ("h_wire", + h_wire), + GNUNET_PQ_result_spec_auto_from_type ("salt", + salt), + GNUNET_PQ_result_spec_end + }; + + GNUNET_assert (account_details->active); + GNUNET_assert (NULL != pg->current_merchant_id); + GNUNET_assert (0 == strcmp (account_details->instance_id, + pg->current_merchant_id)); + TMH_PQ_prepare_anon (pg, + "SELECT " + " out_h_wire AS h_wire" + " ,out_salt AS salt" + " ,out_conflict AS conflict" + " ,out_not_found AS not_found" + " FROM merchant_do_activate_account" + " ($1,$2,$3,$4,$5,$6);"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "", + params, + rs); +} diff --git a/src/backenddb/activate_account.sql b/src/backenddb/do_insert_account.sql diff --git a/src/backenddb/do_solve_mfa_challenge.c b/src/backenddb/do_solve_mfa_challenge.c @@ -0,0 +1,80 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/do_solve_mfa_challenge.c + * @brief Implementation of the do_solve_mfa_challenge function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "taler/taler_merchant_util.h" +#include "merchant-database/do_solve_mfa_challenge.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_do_solve_mfa_challenge ( + struct TALER_MERCHANTDB_PostgresContext *pg, + uint64_t challenge_id, + const struct TALER_MERCHANT_MFA_BodyHash *h_body, + const char *solution, + bool *solved, + uint32_t *retry_counter) +{ + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + bool no_match; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&challenge_id), + GNUNET_PQ_query_param_auto_from_type (h_body), + GNUNET_PQ_query_param_string (solution), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_solved", + solved), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint32 ("out_retry_counter", + retry_counter), + &no_match), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + /* conservatively set security-relevant return values to + safe values, even though these should not be used with qs <= 0 */ + *solved = false; + *retry_counter = 0; + TMH_PQ_prepare_anon (pg, + "SELECT" + " out_solved" + " ,out_retry_counter" + " FROM merchant.merchant_do_solve_mfa_challenge" + " ($1, $2, $3, $4);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "", + params, + rs); + if (qs <= 0) + return qs; + if (no_match) + { + GNUNET_PQ_cleanup_result (rs); + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } + GNUNET_PQ_cleanup_result (rs); + return qs; +} diff --git a/src/backenddb/solve_mfa_challenge.sql b/src/backenddb/do_solve_mfa_challenge.sql diff --git a/src/backenddb/expire_locks.c b/src/backenddb/expire_locks.c @@ -1,60 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/expire_locks.c - * @brief Implementation of the expire_locks function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/expire_locks.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_expire_locks (struct TALER_MERCHANTDB_PostgresContext *pg) -{ - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - uint64_t total; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("expire_locks", - &total), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (pg, - "expire_locks", - "SELECT expire_locks($1) " - " AS expire_locks"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "expire_locks", - params, - rs); - if (qs < 0) - { - GNUNET_break (0); - return qs; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Released %llu locks for the current instance\n", - (unsigned long long) total); - return (enum GNUNET_DB_QueryStatus) total; -} diff --git a/src/backenddb/finalize_transfer_status.c b/src/backenddb/finalize_transfer_status.c @@ -1,76 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/finalize_transfer_status.c - * @brief Implementation of the finalize_transfer_status function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/finalize_transfer_status.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_finalize_transfer_status ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *exchange_url, - const struct TALER_WireTransferIdentifierRawP *wtid, - const struct GNUNET_HashCode *h_details, - const struct TALER_Amount *total_amount, - const struct TALER_Amount *wire_fee, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_ExchangeSignatureP *exchange_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (wtid), - GNUNET_PQ_query_param_string (exchange_url), - TALER_PQ_query_param_amount_with_currency (pg->conn, - total_amount), - TALER_PQ_query_param_amount_with_currency (pg->conn, - wire_fee), - GNUNET_PQ_query_param_auto_from_type (h_details), - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_auto_from_type (exchange_sig), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (NULL != pg->current_merchant_id); - TMH_PQ_prepare_anon (pg, - "WITH subquery AS (" - " SELECT signkey_serial" - " FROM merchant.merchant_exchange_signing_keys" - " WHERE exchange_pub=$6" - ")" - "UPDATE merchant_expected_transfers SET" - " last_http_status=200" - ",last_ec=0" - ",last_detail=NULL" - ",retry_needed=FALSE" - ",retry_time=0" - ",expected_credit_amount=$3" - ",wire_fee=$4" - ",h_details=$5" - ",signkey_serial=subquery.signkey_serial" - ",exchange_sig=$7" - " FROM subquery" - " WHERE wtid=$1" - " AND exchange_url=$2"); - return GNUNET_PQ_eval_prepared_non_select ( - pg->conn, - "", - params); -} diff --git a/src/backenddb/inactivate_account.c b/src/backenddb/inactivate_account.c @@ -1,61 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/inactivate_account.c - * @brief Implementation of the inactivate_account function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/inactivate_account.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_inactivate_account ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *merchant_id, - const struct TALER_MerchantWireHashP *h_wire) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_wire), - GNUNET_PQ_query_param_end - }; - bool found; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("found", - &found), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_assert (NULL != pg->current_merchant_id); - GNUNET_assert (0 == strcmp (merchant_id, - pg->current_merchant_id)); - TMH_PQ_prepare_anon (pg, - "SELECT out_found AS found" - " FROM merchant_do_inactivate_account" - " ($1);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "", - params, - rs); - if (qs < 0) - return qs; - if (! found) - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - return qs; -} diff --git a/src/backenddb/increase_refund.c b/src/backenddb/increase_refund.c @@ -1,740 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022-2024 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/increase_refund.c - * @brief Implementation of the increase_refund function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/increase_refund.h" -#include "helper.h" - - -/** - * Information about refund limits per exchange. - */ -struct ExchangeLimit -{ - /** - * Kept in a DLL. - */ - struct ExchangeLimit *next; - - /** - * Kept in a DLL. - */ - struct ExchangeLimit *prev; - - /** - * Exchange the limit is about. - */ - char *exchange_url; - - /** - * Refund amount remaining at this exchange. - */ - struct TALER_Amount remaining_refund_limit; - -}; - - -/** - * Closure for #process_refund_cb(). - */ -struct FindRefundContext -{ - - /** - * Plugin context. - */ - struct TALER_MERCHANTDB_PostgresContext *pg; - - /** - * Updated to reflect total amount refunded so far. - */ - struct TALER_Amount refunded_amount; - - /** - * Set to the largest refund transaction ID encountered. - */ - uint64_t max_rtransaction_id; - - /** - * Set to true on hard errors. - */ - bool err; -}; - - -/** - * Closure for #process_deposits_for_refund_cb(). - */ -struct InsertRefundContext -{ - /** - * Used to provide a connection to the db - */ - struct TALER_MERCHANTDB_PostgresContext *pg; - - /** - * Head of DLL of per-exchange refund limits. - */ - struct ExchangeLimit *el_head; - - /** - * Tail of DLL of per-exchange refund limits. - */ - struct ExchangeLimit *el_tail; - - /** - * Amount to which increase the refund for this contract - */ - const struct TALER_Amount *refund; - - /** - * Human-readable reason behind this refund - */ - const char *reason; - - /** - * Function to call to determine per-exchange limits. - * NULL for no limits. - */ - TALER_MERCHANTDB_OperationLimitCallback olc; - - /** - * Closure for @e olc. - */ - void *olc_cls; - - /** - * Transaction status code. - */ - enum TALER_MERCHANTDB_RefundStatus rs; - - /** - * Did we have to cap refunds of any coin - * due to legal limits? - */ - bool legal_capped; - -}; - - -/** - * Data extracted per coin. - */ -struct RefundCoinData -{ - - /** - * Public key of a coin. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Amount deposited for this coin. - */ - struct TALER_Amount deposited_with_fee; - - /** - * Amount refunded already for this coin. - */ - struct TALER_Amount refund_amount; - - /** - * Order serial (actually not really per-coin). - */ - uint64_t order_serial; - - /** - * Maximum rtransaction_id for this coin so far. - */ - uint64_t max_rtransaction_id; - - /** - * Exchange this coin was issued by. - */ - char *exchange_url; - -}; - - -/** - * Find an exchange record for the refund limit enforcement. - * - * @param irc refund context - * @param exchange_url base URL of the exchange - */ -static struct ExchangeLimit * -find_exchange (struct InsertRefundContext *irc, - const char *exchange_url) -{ - if (NULL == irc->olc) - return NULL; /* no limits */ - /* Check if entry exists, if so, do nothing */ - for (struct ExchangeLimit *el = irc->el_head; - NULL != el; - el = el->next) - if (0 == strcmp (exchange_url, - el->exchange_url)) - return el; - return NULL; -} - - -/** - * Setup an exchange for the refund limit enforcement and initialize the - * original refund limit for the exchange. - * - * @param irc refund context - * @param exchange_url base URL of the exchange - * @return limiting data structure - */ -static struct ExchangeLimit * -setup_exchange (struct InsertRefundContext *irc, - const char *exchange_url) -{ - struct ExchangeLimit *el; - - if (NULL == irc->olc) - return NULL; /* no limits */ - /* Check if entry exists, if so, do nothing */ - if (NULL != - (el = find_exchange (irc, - exchange_url))) - return el; - el = GNUNET_new (struct ExchangeLimit); - el->exchange_url = GNUNET_strdup (exchange_url); - /* olc only lowers, so set to the maximum amount we care about */ - el->remaining_refund_limit = *irc->refund; - irc->olc (irc->olc_cls, - exchange_url, - &el->remaining_refund_limit); - GNUNET_CONTAINER_DLL_insert (irc->el_head, - irc->el_tail, - el); - return el; -} - - -/** - * Lower the remaining refund limit in @a el by @a val. - * - * @param[in,out] el exchange limit to lower - * @param val amount to lower limit by - * @return true on success, false on failure - */ -static bool -lower_balance (struct ExchangeLimit *el, - const struct TALER_Amount *val) -{ - if (NULL == el) - return true; - return 0 <= TALER_amount_subtract (&el->remaining_refund_limit, - &el->remaining_refund_limit, - val); -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure, our `struct FindRefundContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -process_refund_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct FindRefundContext *ictx = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - /* Sum up existing refunds */ - struct TALER_Amount acc; - uint64_t rtransaction_id; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_amount_with_currency ("refund_amount", - &acc), - GNUNET_PQ_result_spec_uint64 ("rtransaction_id", - &rtransaction_id), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ictx->err = true; - return; - } - if (GNUNET_OK != - TALER_amount_cmp_currency (&ictx->refunded_amount, - &acc)) - { - GNUNET_break (0); - ictx->err = true; - return; - } - if (0 > - TALER_amount_add (&ictx->refunded_amount, - &ictx->refunded_amount, - &acc)) - { - GNUNET_break (0); - ictx->err = true; - return; - } - ictx->max_rtransaction_id = GNUNET_MAX (ictx->max_rtransaction_id, - rtransaction_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Found refund of %s\n", - TALER_amount2s (&acc)); - } -} - - -/** - * Helper function to prepare statement to select refunds - * - * @param pg context to prepare statement in - * @return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS on success - */ -static enum GNUNET_DB_QueryStatus -prep_select_refund (struct TALER_MERCHANTDB_PostgresContext *pg) -{ - TMH_PQ_prepare_anon (pg, - "SELECT" - " refund_amount" - ",rtransaction_id" - " FROM merchant_refunds" - " WHERE coin_pub=$1" - " AND order_serial=$2"); - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; -} - - -/** - * Helper function to prepare statement to insert refund - * - * @param pg context to prepare statement in - * @return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS on success - */ -static enum GNUNET_DB_QueryStatus -prep_insert_refund (struct TALER_MERCHANTDB_PostgresContext *pg) -{ - // FIXME: return 'refund_serial' from this INSERT statement for #10577 - TMH_PQ_prepare_anon (pg, - "INSERT INTO merchant_refunds" - "(order_serial" - ",rtransaction_id" - ",refund_timestamp" - ",coin_pub" - ",reason" - ",refund_amount" - ") VALUES" - "($1, $2, $3, $4, $5, $6)"); - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; -} - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls closure, our `struct InsertRefundContext` - * @param result the postgres result - * @param num_results the number of results in @a result - */ -static void -process_deposits_for_refund_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct InsertRefundContext *ctx = cls; - struct TALER_MERCHANTDB_PostgresContext *pg = ctx->pg; - struct TALER_Amount current_refund; - struct RefundCoinData rcd[GNUNET_NZL (num_results)]; - struct GNUNET_TIME_Timestamp now; - - now = GNUNET_TIME_timestamp_get (); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (ctx->refund->currency, - &current_refund)); - memset (rcd, - 0, - sizeof (rcd)); - /* Pass 1: Collect amount of existing refunds into current_refund. - * Also store existing refunded amount for each deposit in deposit_refund. */ - for (unsigned int i = 0; i<num_results; i++) - { - struct RefundCoinData *rcdi = &rcd[i]; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &rcdi->coin_pub), - GNUNET_PQ_result_spec_uint64 ("order_serial", - &rcdi->order_serial), - GNUNET_PQ_result_spec_string ("exchange_url", - &rcdi->exchange_url), - TALER_PQ_result_spec_amount_with_currency ("amount_with_fee", - &rcdi->deposited_with_fee), - GNUNET_PQ_result_spec_end - }; - struct FindRefundContext ictx = { - .pg = pg, - }; - struct ExchangeLimit *el; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - } - el = setup_exchange (ctx, - rcdi->exchange_url); - if (0 != strcmp (rcdi->deposited_with_fee.currency, - ctx->refund->currency)) - { - GNUNET_break_op (0); - ctx->rs = TALER_MERCHANTDB_RS_BAD_CURRENCY; - goto cleanup; - } - - { - enum GNUNET_DB_QueryStatus ires; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&rcdi->coin_pub), - GNUNET_PQ_query_param_uint64 (&rcdi->order_serial), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero ( - ctx->refund->currency, - &ictx.refunded_amount)); - ires = prep_select_refund (pg); - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != ires) - { - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - } - ires = GNUNET_PQ_eval_prepared_multi_select ( - pg->conn, - "", - params, - &process_refund_cb, - &ictx); - if ( (ictx.err) || - (GNUNET_DB_STATUS_HARD_ERROR == ires) ) - { - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - } - if (GNUNET_DB_STATUS_SOFT_ERROR == ires) - { - ctx->rs = TALER_MERCHANTDB_RS_SOFT_ERROR; - goto cleanup; - } - } - if (0 > - TALER_amount_add (&current_refund, - &current_refund, - &ictx.refunded_amount)) - { - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - } - rcdi->refund_amount = ictx.refunded_amount; - rcdi->max_rtransaction_id = ictx.max_rtransaction_id; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Existing refund for coin %s is %s\n", - TALER_B2S (&rcdi->coin_pub), - TALER_amount2s (&ictx.refunded_amount)); - GNUNET_break (lower_balance (el, - &ictx.refunded_amount)); - } /* end for all deposited coins */ - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Total existing refund is %s\n", - TALER_amount2s (&current_refund)); - - /* stop immediately if we are 'done' === amount already - * refunded. */ - if (0 >= TALER_amount_cmp (ctx->refund, - &current_refund)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Existing refund of %s at or above requested refund. Finished early.\n", - TALER_amount2s (&current_refund)); - ctx->rs = TALER_MERCHANTDB_RS_SUCCESS; - goto cleanup; - } - - /* Phase 2: Try to increase current refund until it matches desired refund */ - for (unsigned int i = 0; i<num_results; i++) - { - struct RefundCoinData *rcdi = &rcd[i]; - const struct TALER_Amount *increment; - struct TALER_Amount left; - struct TALER_Amount remaining_refund; - struct ExchangeLimit *el; - - /* How much of the coin is left after the existing refunds? */ - if (0 > - TALER_amount_subtract (&left, - &rcdi->deposited_with_fee, - &rcdi->refund_amount)) - { - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - } - - if (TALER_amount_is_zero (&left)) - { - /* coin was fully refunded, move to next coin */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Coin %s fully refunded, moving to next coin\n", - TALER_B2S (&rcdi->coin_pub)); - continue; - } - el = find_exchange (ctx, - rcdi->exchange_url); - if ( (NULL != el) && - (TALER_amount_is_zero (&el->remaining_refund_limit)) ) - { - /* legal limit reached, move to next coin */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Exchange %s legal limit reached, moving to next coin\n", - rcdi->exchange_url); - continue; - } - - rcdi->max_rtransaction_id++; - /* How much of the refund is still to be paid back? */ - if (0 > - TALER_amount_subtract (&remaining_refund, - ctx->refund, - &current_refund)) - { - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - } - /* cap by legal limit */ - if (NULL != el) - { - struct TALER_Amount new_limit; - - TALER_amount_min (&new_limit, - &remaining_refund, - &el->remaining_refund_limit); - if (0 != TALER_amount_cmp (&new_limit, - &remaining_refund)) - { - remaining_refund = new_limit; - ctx->legal_capped = true; - } - } - /* By how much will we increase the refund for this coin? */ - if (0 >= TALER_amount_cmp (&remaining_refund, - &left)) - { - /* remaining_refund <= left */ - increment = &remaining_refund; - } - else - { - increment = &left; - } - - if (0 > - TALER_amount_add (&current_refund, - &current_refund, - increment)) - { - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - } - GNUNET_break (lower_balance (el, - increment)); - /* actually run the refund */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Coin %s deposit amount is %s\n", - TALER_B2S (&rcdi->coin_pub), - TALER_amount2s (&rcdi->deposited_with_fee)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Coin %s refund will be incremented by %s\n", - TALER_B2S (&rcdi->coin_pub), - TALER_amount2s (increment)); - { - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&rcdi->order_serial), - GNUNET_PQ_query_param_uint64 (&rcdi->max_rtransaction_id), /* already inc'ed */ - GNUNET_PQ_query_param_timestamp (&now), - GNUNET_PQ_query_param_auto_from_type (&rcdi->coin_pub), - GNUNET_PQ_query_param_string (ctx->reason), - TALER_PQ_query_param_amount_with_currency (pg->conn, - increment), - GNUNET_PQ_query_param_end - }; - - qs = prep_insert_refund (pg); - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) - { - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - } - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "", - params); - switch (qs) - { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - ctx->rs = TALER_MERCHANTDB_RS_HARD_ERROR; - goto cleanup; - case GNUNET_DB_STATUS_SOFT_ERROR: - ctx->rs = TALER_MERCHANTDB_RS_SOFT_ERROR; - goto cleanup; - default: - ctx->rs = (enum TALER_MERCHANTDB_RefundStatus) qs; - break; - } - } - - /* stop immediately if we are done */ - if (0 == TALER_amount_cmp (ctx->refund, - &current_refund)) - { - ctx->rs = TALER_MERCHANTDB_RS_SUCCESS; - goto cleanup; - } - } - - if (ctx->legal_capped) - { - ctx->rs = TALER_MERCHANTDB_RS_LEGAL_FAILURE; - goto cleanup; - } - /** - * We end up here if not all of the refund has been covered. - * Although this should be checked as the business should never - * issue a refund bigger than the contract's actual price, we cannot - * rely upon the frontend being correct. - */ - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "The refund of %s is bigger than the order's value\n", - TALER_amount2s (ctx->refund)); - ctx->rs = TALER_MERCHANTDB_RS_TOO_HIGH; -cleanup: - for (unsigned int i = 0; i<num_results; i++) - GNUNET_free (rcd[i].exchange_url); -} - - -enum TALER_MERCHANTDB_RefundStatus -TALER_MERCHANTDB_increase_refund ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - const char *order_id, - const struct TALER_Amount *refund, - TALER_MERCHANTDB_OperationLimitCallback olc, - void *olc_cls, - const char *reason) -{ - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (order_id), - GNUNET_PQ_query_param_end - }; - struct InsertRefundContext ctx = { - .pg = pg, - .refund = refund, - .olc = olc, - .olc_cls = olc_cls, - .reason = reason, - }; - - GNUNET_assert (NULL != pg->current_merchant_id); - GNUNET_assert (0 == strcmp (instance_id, - pg->current_merchant_id)); - TMH_PQ_prepare_anon (pg, - "SELECT" - " dep.coin_pub" - ",dco.order_serial" - ",dep.amount_with_fee" - ",dco.exchange_url" - " FROM merchant_deposits dep" - " JOIN merchant_deposit_confirmations dco" - " USING (deposit_confirmation_serial)" - " WHERE order_serial=" - " (SELECT order_serial" - " FROM merchant_contract_terms" - " WHERE order_id=$1" - " AND paid)"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Asked to refund %s on order %s\n", - TALER_amount2s (refund), - order_id); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "", - params, - &process_deposits_for_refund_cb, - &ctx); - { - struct ExchangeLimit *el; - - while (NULL != (el = ctx.el_head)) - { - GNUNET_CONTAINER_DLL_remove (ctx.el_head, - ctx.el_tail, - el); - GNUNET_free (el->exchange_url); - GNUNET_free (el); - } - } - switch (qs) - { - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - /* never paid, means we clearly cannot refund anything */ - return TALER_MERCHANTDB_RS_NO_SUCH_ORDER; - case GNUNET_DB_STATUS_SOFT_ERROR: - return TALER_MERCHANTDB_RS_SOFT_ERROR; - case GNUNET_DB_STATUS_HARD_ERROR: - return TALER_MERCHANTDB_RS_HARD_ERROR; - default: - /* Got one or more deposits */ - return ctx.rs; - } -} diff --git a/src/backenddb/increment_money_pots.c b/src/backenddb/increment_money_pots.c @@ -1,76 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/increment_money_pots.c - * @brief Implementation of the increment_money_pots function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "merchant-database/increment_money_pots.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_increment_money_pots ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - size_t money_pots_len, - const uint64_t *money_pot_ids, - const struct TALER_Amount *pot_increments) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_array_uint64 (money_pots_len, - money_pot_ids, - pg->conn), - TALER_PQ_query_param_array_amount_with_currency (money_pots_len, - pot_increments, - "merchant", - pg->conn), - GNUNET_PQ_query_param_end - }; - bool not_found; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("not_found", - &not_found), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_assert (NULL != pg->current_merchant_id); - GNUNET_assert (0 == strcmp (instance_id, - pg->current_merchant_id)); - TMH_PQ_prepare_anon (pg, - "SELECT" - " out_not_found AS not_found" - " FROM merchant_do_increment_money_pots" - "($1,$2);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "", - params, - rs); - GNUNET_PQ_cleanup_query_params_closures (params); - if (qs <= 0) - return qs; - if (not_found) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Some money pots could not be implemented because they no longer exist. This is not a bug and expected to happen if a merchant deletes money pots that were used in orders active at the time.\n"); - } - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -} diff --git a/src/backenddb/insert_donau_keys.c b/src/backenddb/insert_donau_keys.c @@ -0,0 +1,70 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/insert_donau_keys.c + * @brief Implementation of the insert_donau_keys function for Postgres + * @author Bohdan Potuzhnyi + * @author Vlada Svirsh + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "donau/donau_service.h" +#include "merchant-database/insert_donau_keys.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_donau_keys ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const struct DONAU_Keys *keys, + struct GNUNET_TIME_Absolute first_retry) +{ + enum GNUNET_DB_QueryStatus qs; + json_t *jkeys = DONAU_keys_to_json (keys); + + if (NULL == jkeys) + return GNUNET_DB_STATUS_HARD_ERROR; + + { + struct GNUNET_PQ_QueryParam params[] = { + TALER_PQ_query_param_json (jkeys), + GNUNET_PQ_query_param_absolute_time (&first_retry), + GNUNET_PQ_query_param_string (keys->donau_url), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "insert_donau_keys", + "INSERT INTO merchant.merchant_donau_keys" + " (keys_json" + " ,first_retry" + " ,donau_url" + " ) VALUES (" + " $1::TEXT::JSONB" + " ,$2" + " ,$3)" + " ON CONFLICT (donau_url)" + " DO UPDATE SET" + " keys_json=EXCLUDED.keys_json," + " first_retry=EXCLUDED.first_retry;"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_donau_keys", + params); + } + + json_decref (jkeys); + return qs; +} diff --git a/src/backenddb/insert_inventory_lock.c b/src/backenddb/insert_inventory_lock.c @@ -0,0 +1,93 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/insert_inventory_lock.c + * @brief Implementation of the insert_inventory_lock function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/insert_inventory_lock.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_inventory_lock ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + const char *product_id, + const struct GNUNET_Uuid *uuid, + uint64_t quantity, + uint32_t quantity_frac, + struct GNUNET_TIME_Timestamp expiration_time) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (product_id), + GNUNET_PQ_query_param_auto_from_type (uuid), + GNUNET_PQ_query_param_uint64 (&quantity), + GNUNET_PQ_query_param_uint32 (&quantity_frac), + GNUNET_PQ_query_param_timestamp (&expiration_time), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (NULL != pg->current_merchant_id); + GNUNET_assert (0 == strcmp (instance_id, + pg->current_merchant_id)); + TMH_PQ_prepare_anon (pg, + "WITH tmp AS" + " (SELECT" + " mi.product_serial" + " ,mi.total_stock" + " ,mi.total_stock_frac" + " ,mi.total_sold" + " ,mi.total_sold_frac" + " ,mi.total_lost" + " ,mi.total_lost_frac" + " ,mi.allow_fractional_quantity" + " FROM merchant_inventory mi" + " WHERE mi.product_id=$1)" + "INSERT INTO merchant_inventory_locks" + "(product_serial" + ",lock_uuid" + ",total_locked" + ",total_locked_frac" + ",expiration)" + " SELECT tmp.product_serial, $2, $3::INT8, $4::INT4, $5" + " FROM tmp" + " WHERE (tmp.allow_fractional_quantity OR $4 = 0)" + " AND (tmp.total_stock = 9223372036854775807" + " OR (" + " (tmp.total_stock::NUMERIC * 1000000" + " + tmp.total_stock_frac::NUMERIC)" + " - (tmp.total_sold::NUMERIC * 1000000" + " + tmp.total_sold_frac::NUMERIC)" + " - (tmp.total_lost::NUMERIC * 1000000" + " + tmp.total_lost_frac::NUMERIC)" + " >= " + " (($3::NUMERIC * 1000000) + $4::NUMERIC)" + " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000" + " + total_locked_frac::NUMERIC), 0)" + " FROM merchant_inventory_locks mil" + " WHERE mil.product_serial = tmp.product_serial)" + " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000" + " + total_locked_frac::NUMERIC), 0)" + " FROM merchant_order_locks mol" + " WHERE mol.product_serial = tmp.product_serial)" + " ))"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "", + params); +} diff --git a/src/backenddb/insert_mfa_challenge.c b/src/backenddb/insert_mfa_challenge.c @@ -0,0 +1,86 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/insert_mfa_challenge.c + * @brief Implementation of the insert_mfa_challenge function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "taler/taler_merchant_util.h" +#include "merchantdb_lib.h" +#include "merchant-database/insert_mfa_challenge.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_mfa_challenge ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_name, + enum TALER_MERCHANT_MFA_CriticalOperation op, + const struct TALER_MERCHANT_MFA_BodyHash *h_body, + const struct TALER_MERCHANT_MFA_BodySalt *salt, + const char *code, + struct GNUNET_TIME_Absolute expiration_date, + struct GNUNET_TIME_Absolute retransmission_date, + enum TALER_MERCHANT_MFA_Channel tan_channel, + const char *required_address, + uint64_t *challenge_id) +{ + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + const char *op_str = TALER_MERCHANT_MFA_co_to_string (op); + const char *channel_str = TALER_MERCHANT_MFA_channel_to_string (tan_channel); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_body), + GNUNET_PQ_query_param_auto_from_type (salt), + GNUNET_PQ_query_param_string (op_str), + GNUNET_PQ_query_param_string (code), + GNUNET_PQ_query_param_absolute_time (&now), /* $5 */ + GNUNET_PQ_query_param_absolute_time (&expiration_date), + GNUNET_PQ_query_param_absolute_time (&retransmission_date), + GNUNET_PQ_query_param_string (channel_str), + GNUNET_PQ_query_param_string (required_address), /* $9 */ + GNUNET_PQ_query_param_string (instance_name), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("challenge_id", + challenge_id), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "create_mfa_challenge", + "INSERT INTO merchant.tan_challenges" + " (h_body" + " ,salt" + " ,op" + " ,code" + " ,creation_date" + " ,expiration_date" + " ,retransmission_date" + " ,retry_counter" /* always set to 3 */ + " ,tan_channel" + " ,required_address" + " ,instance_name)" + " VALUES" + " ($1, $2, $3, $4, $5, $6, $7, 3, $8, $9, $10)" + " RETURNING challenge_id;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "create_mfa_challenge", + params, + rs); +} diff --git a/src/backenddb/insert_refund_by_coin.c b/src/backenddb/insert_refund_by_coin.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/insert_refund_by_coin.c + * @brief Implementation of the insert_refund_by_coin function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/insert_refund_by_coin.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_refund_by_coin ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp refund_timestamp, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const char *reason) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_timestamp (&refund_timestamp), + GNUNET_PQ_query_param_auto_from_type (coin_pub), + GNUNET_PQ_query_param_string (reason), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (NULL != pg->current_merchant_id); + GNUNET_assert (0 == strcmp (instance_id, + pg->current_merchant_id)); + TMH_PQ_prepare_anon (pg, + "INSERT INTO merchant_refunds" + "(order_serial" + ",rtransaction_id" + ",refund_timestamp" + ",coin_pub" + ",reason" + ",refund_amount" + ") " + "SELECT " + " dcon.order_serial" + ",0" /* rtransaction_id always 0 for /abort */ + ",$2" + ",dep.coin_pub" + ",$4" + ",dep.amount_with_fee" + " FROM merchant_deposits dep" + " JOIN merchant_deposit_confirmations dcon" + " USING (deposit_confirmation_serial)" + " WHERE dep.coin_pub=$3" + " AND dcon.order_serial=" + " (SELECT order_serial" + " FROM merchant_contract_terms" + " WHERE h_contract_terms=$1)"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "", + params); +} diff --git a/src/backenddb/insert_wire_fee.c b/src/backenddb/insert_wire_fee.c @@ -0,0 +1,72 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/insert_wire_fee.c + * @brief Implementation of the insert_wire_fee function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/insert_wire_fee.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_wire_fee ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const struct TALER_MasterPublicKeyP *master_pub, + const struct GNUNET_HashCode *h_wire_method, + const struct TALER_WireFeeSet *fees, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_MasterSignatureP *master_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (master_pub), + GNUNET_PQ_query_param_auto_from_type (h_wire_method), + TALER_PQ_query_param_amount_with_currency (pg->conn, + &fees->wire), + TALER_PQ_query_param_amount_with_currency (pg->conn, + &fees->closing), + GNUNET_PQ_query_param_timestamp (&start_date), + GNUNET_PQ_query_param_timestamp (&end_date), + GNUNET_PQ_query_param_auto_from_type (master_sig), + GNUNET_PQ_query_param_end + }; + + /* no preflight check here, run in its own transaction by the caller */ + PREPARE (pg, + "insert_wire_fee", + "INSERT INTO merchant.merchant_exchange_wire_fees" + "(master_pub" + ",h_wire_method" + ",wire_fee" + ",closing_fee" + ",start_date" + ",end_date" + ",master_sig)" + " VALUES " + "($1, $2, $3, $4, $5, $6, $7)" + " ON CONFLICT DO NOTHING"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Storing wire fee for %s starting at %s of %s\n", + TALER_B2S (master_pub), + GNUNET_TIME_timestamp2s (start_date), + TALER_amount2s (&fees->wire)); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_wire_fee", + params); +} diff --git a/src/backenddb/lock_product.c b/src/backenddb/lock_product.c @@ -1,93 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/lock_product.c - * @brief Implementation of the lock_product function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/lock_product.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_lock_product ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - const char *product_id, - const struct GNUNET_Uuid *uuid, - uint64_t quantity, - uint32_t quantity_frac, - struct GNUNET_TIME_Timestamp expiration_time) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (product_id), - GNUNET_PQ_query_param_auto_from_type (uuid), - GNUNET_PQ_query_param_uint64 (&quantity), - GNUNET_PQ_query_param_uint32 (&quantity_frac), - GNUNET_PQ_query_param_timestamp (&expiration_time), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (NULL != pg->current_merchant_id); - GNUNET_assert (0 == strcmp (instance_id, - pg->current_merchant_id)); - TMH_PQ_prepare_anon (pg, - "WITH tmp AS" - " (SELECT" - " mi.product_serial" - " ,mi.total_stock" - " ,mi.total_stock_frac" - " ,mi.total_sold" - " ,mi.total_sold_frac" - " ,mi.total_lost" - " ,mi.total_lost_frac" - " ,mi.allow_fractional_quantity" - " FROM merchant_inventory mi" - " WHERE mi.product_id=$1)" - "INSERT INTO merchant_inventory_locks" - "(product_serial" - ",lock_uuid" - ",total_locked" - ",total_locked_frac" - ",expiration)" - " SELECT tmp.product_serial, $2, $3::INT8, $4::INT4, $5" - " FROM tmp" - " WHERE (tmp.allow_fractional_quantity OR $4 = 0)" - " AND (tmp.total_stock = 9223372036854775807" - " OR (" - " (tmp.total_stock::NUMERIC * 1000000" - " + tmp.total_stock_frac::NUMERIC)" - " - (tmp.total_sold::NUMERIC * 1000000" - " + tmp.total_sold_frac::NUMERIC)" - " - (tmp.total_lost::NUMERIC * 1000000" - " + tmp.total_lost_frac::NUMERIC)" - " >= " - " (($3::NUMERIC * 1000000) + $4::NUMERIC)" - " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000" - " + total_locked_frac::NUMERIC), 0)" - " FROM merchant_inventory_locks mil" - " WHERE mil.product_serial = tmp.product_serial)" - " + (SELECT COALESCE(SUM(total_locked::NUMERIC * 1000000" - " + total_locked_frac::NUMERIC), 0)" - " FROM merchant_order_locks mol" - " WHERE mol.product_serial = tmp.product_serial)" - " ))"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "", - params); -} diff --git a/src/backenddb/mark_contract_paid.c b/src/backenddb/mark_contract_paid.c @@ -1,107 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/mark_contract_paid.c - * @brief Implementation of the mark_contract_paid function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/mark_contract_paid.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_mark_contract_paid ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - const struct TALER_PrivateContractHashP *h_contract_terms, - const char *session_id, - int16_t choice_index) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_string (session_id), - (choice_index >= 0) - ? GNUNET_PQ_query_param_int16 (&choice_index) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_QueryParam uparams[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - /* Session ID must always be given by the caller. */ - GNUNET_assert (NULL != session_id); - GNUNET_assert (NULL != pg->current_merchant_id); - GNUNET_assert (0 == strcmp (instance_id, - pg->current_merchant_id)); - - /* FIXME: combine the 3 individual statements into a stored procedure! */ - /* no preflight check here, run in transaction by caller! */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Marking h_contract_terms '%s' of %s as paid for session `%s'\n", - GNUNET_h2s (&h_contract_terms->hash), - instance_id, - session_id); - TMH_PQ_prepare_anon (pg, - "UPDATE merchant_contract_terms SET" - " paid=TRUE" - ",session_id=$2" - ",choice_index=$3" - " WHERE h_contract_terms=$1"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "", - params); - if (qs <= 0) - return qs; - TMH_PQ_prepare_anon (pg, - "UPDATE merchant_inventory SET" - " total_sold = total_sold" - " + order_locks.total_locked" - " + ((merchant_inventory.total_sold_frac::BIGINT" - " + order_locks.total_locked_frac::BIGINT) / 1000000)" - " ,total_sold_frac =" - " ((merchant_inventory.total_sold_frac::BIGINT" - " + order_locks.total_locked_frac::BIGINT) % 1000000)::INT4" - " FROM (SELECT total_locked,total_locked_frac,product_serial" - " FROM merchant_order_locks" - " WHERE order_serial=" - " (SELECT order_serial" - " FROM merchant_contract_terms" - " WHERE h_contract_terms=$1)" - " ) AS order_locks" - " WHERE merchant_inventory.product_serial" - " =order_locks.product_serial"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "", - uparams); - if (qs < 0) - return qs; /* 0: no inventory management, that's OK! */ - /* ON DELETE CASCADE deletes from merchant_order_locks */ - TMH_PQ_prepare_anon (pg, - "DELETE" - " FROM merchant_orders" - " WHERE order_serial=" - " (SELECT order_serial" - " FROM merchant_contract_terms" - " WHERE h_contract_terms=$1)"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "", - uparams); -} diff --git a/src/backenddb/mark_order_wired.c b/src/backenddb/mark_order_wired.c @@ -1,45 +0,0 @@ -/* - 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 <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/mark_order_wired.c - * @brief Implementation of the mark_order_wired function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/mark_order_wired.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_mark_order_wired ( - struct TALER_MERCHANTDB_PostgresContext *pg, - uint64_t order_serial) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&order_serial), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (NULL != pg->current_merchant_id); - TMH_PQ_prepare_anon (pg, - "UPDATE merchant_contract_terms SET" - " wired=TRUE" - " WHERE order_serial=$1"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "", - params); -} diff --git a/src/backenddb/meson.build b/src/backenddb/meson.build @@ -19,12 +19,12 @@ libtalermerchantdb = library( 'iterate_kyc_statuses.c', 'insert_kyc_failure.c', 'insert_kyc_status.c', - 'activate_account.c', + 'do_insert_account.c', 'get_exists_transfer.c', 'delete_category.c', 'delete_contract_terms.c', 'delete_exchange_accounts.c', - 'delete_instance_private_key.c', + 'update_to_instance_private_key_deleted.c', 'delete_login_token.c', 'delete_login_token_by_serial.c', 'delete_order.c', @@ -36,13 +36,13 @@ libtalermerchantdb = library( 'delete_tos_accepted_early.c', 'delete_transfer.c', 'delete_webhook.c', - 'expire_locks.c', + 'do_expire_locks.c', 'gc.c', 'get_kyc_limits.c', 'get_kyc_status.c', - 'inactivate_account.c', - 'increase_refund.c', - 'increment_money_pots.c', + 'update_to_account_inactive.c', + 'do_increase_refund.c', + 'update_money_pot_totals.c', 'insert_account.c', 'insert_category.c', 'insert_unit.c', @@ -76,9 +76,9 @@ libtalermerchantdb = library( 'iterate_custom_units_by_names.c', 'get_unit.c', 'get_mfa_challenge.c', - 'solve_mfa_challenge.c', + 'do_solve_mfa_challenge.c', 'update_mfa_challenge.c', - 'create_mfa_challenge.c', + 'insert_mfa_challenge.c', 'insert_report.c', 'delete_report.c', 'update_report.c', @@ -100,7 +100,7 @@ libtalermerchantdb = library( 'get_missing_money_pot.c', 'iterate_money_pots.c', 'get_money_pot.c', - 'lock_product.c', + 'insert_inventory_lock.c', 'get_account_serial.c', 'iterate_all_products.c', 'iterate_categories.c', @@ -150,11 +150,11 @@ libtalermerchantdb = library( 'iterate_all_webhooks.c', 'iterate_webhooks.c', 'get_wire_fee.c', - 'mark_contract_paid.c', - 'mark_order_wired.c', + 'update_to_contract_terms_paid.c', + 'update_to_contract_terms_wired.c', 'iterate_order_blinded_sigs.c', - 'purge_instance.c', - 'refund_coin.c', + 'delete_instance.c', + 'insert_refund_by_coin.c', 'get_account.c', 'get_account_by_uri.c', 'iterate_accounts.c', @@ -169,8 +169,8 @@ libtalermerchantdb = library( 'get_otp.c', 'get_otp_serial.c', 'iterate_wirewatch_accounts.c', - 'store_wire_fee_by_exchange.c', - 'unlock_inventory.c', + 'insert_wire_fee.c', + 'delete_inventory_lock.c', 'update_account.c', 'update_category.c', 'update_contract_session.c', @@ -185,7 +185,7 @@ libtalermerchantdb = library( 'update_template.c', 'update_token_family.c', 'update_transfer_status.c', - 'finalize_transfer_status.c', + 'update_to_transfer_finalized.c', 'delete_donau_instance.c', 'insert_order_blinded_sigs.c', 'update_webhook.c', @@ -203,7 +203,7 @@ libtalermerchantdb = library( 'get_donau_keys.c', 'get_order_charity.c', 'get_tos_accepted_early.c', - 'upsert_donau_keys.c', + 'insert_donau_keys.c', 'update_donau_instance.c', 'merchantdb_helper.c', ], diff --git a/src/backenddb/purge_instance.c b/src/backenddb/purge_instance.c @@ -1,52 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/purge_instance.c - * @brief Implementation of the purge_instance function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/purge_instance.h" -#include "helper.h" - - -/** - * Purge an instance and all associated information from our database. - * Highly likely to cause undesired data loss. Use with caution. - * - * @param pg database context - * @param merchant_id identifier of the instance - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_purge_instance ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *merchant_id) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (merchant_id), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "purge_instance", - "DELETE FROM merchant.merchant_instances" - " WHERE merchant_id = $1"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "purge_instance", - params); -} diff --git a/src/backenddb/refund_coin.c b/src/backenddb/refund_coin.c @@ -1,74 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/refund_coin.c - * @brief Implementation of the refund_coin function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/refund_coin.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_refund_coin ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - const struct TALER_PrivateContractHashP *h_contract_terms, - struct GNUNET_TIME_Timestamp refund_timestamp, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const char *reason) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_timestamp (&refund_timestamp), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_string (reason), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (NULL != pg->current_merchant_id); - GNUNET_assert (0 == strcmp (instance_id, - pg->current_merchant_id)); - TMH_PQ_prepare_anon (pg, - "INSERT INTO merchant_refunds" - "(order_serial" - ",rtransaction_id" - ",refund_timestamp" - ",coin_pub" - ",reason" - ",refund_amount" - ") " - "SELECT " - " dcon.order_serial" - ",0" /* rtransaction_id always 0 for /abort */ - ",$2" - ",dep.coin_pub" - ",$4" - ",dep.amount_with_fee" - " FROM merchant_deposits dep" - " JOIN merchant_deposit_confirmations dcon" - " USING (deposit_confirmation_serial)" - " WHERE dep.coin_pub=$3" - " AND dcon.order_serial=" - " (SELECT order_serial" - " FROM merchant_contract_terms" - " WHERE h_contract_terms=$1)"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "", - params); -} diff --git a/src/backenddb/solve_mfa_challenge.c b/src/backenddb/solve_mfa_challenge.c @@ -1,80 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/solve_mfa_challenge.c - * @brief Implementation of the solve_mfa_challenge function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "taler/taler_merchant_util.h" -#include "merchant-database/solve_mfa_challenge.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_solve_mfa_challenge ( - struct TALER_MERCHANTDB_PostgresContext *pg, - uint64_t challenge_id, - const struct TALER_MERCHANT_MFA_BodyHash *h_body, - const char *solution, - bool *solved, - uint32_t *retry_counter) -{ - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); - bool no_match; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&challenge_id), - GNUNET_PQ_query_param_auto_from_type (h_body), - GNUNET_PQ_query_param_string (solution), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("out_solved", - solved), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint32 ("out_retry_counter", - retry_counter), - &no_match), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - /* conservatively set security-relevant return values to - safe values, even though these should not be used with qs <= 0 */ - *solved = false; - *retry_counter = 0; - TMH_PQ_prepare_anon (pg, - "SELECT" - " out_solved" - " ,out_retry_counter" - " FROM merchant.merchant_do_solve_mfa_challenge" - " ($1, $2, $3, $4);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "", - params, - rs); - if (qs <= 0) - return qs; - if (no_match) - { - GNUNET_PQ_cleanup_result (rs); - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - GNUNET_PQ_cleanup_result (rs); - return qs; -} diff --git a/src/backenddb/sql-schema/meson.build b/src/backenddb/sql-schema/meson.build @@ -14,7 +14,7 @@ sql_global_procedures = [ '../iterate_wirewatch_accounts.sql', '../iterate_open_transfers.sql', '../iterate_all_donau_instances.sql', - '../solve_mfa_challenge.sql', + '../do_solve_mfa_challenge.sql', '../iterate_pending_deposits.sql', '../iterate_reports_pending.sql', '../pg_select_accounts.sql', @@ -51,14 +51,14 @@ sql_instance_procedures = [ '../insert_kyc_failure.sql', '../update_product_group.sql', '../update_money_pot.sql', - '../increment_money_pots.sql', + '../update_money_pot_totals.sql', '../iterate_kyc_statuses.sql', '../insert_transfer.sql', '../insert_unclaim_signature.sql', '../insert_deposit_confirmation.sql', - '../activate_account.sql', - '../inactivate_account.sql', - '../expire_locks.sql', + '../do_insert_account.sql', + '../update_to_account_inactive.sql', + '../do_expire_locks.sql', '../pg_merchant_send_account_notification.sql', '../pg_merchant_account_trigger.sql', '../pg_merchant_send_kyc_notification.sql', diff --git a/src/backenddb/store_wire_fee_by_exchange.c b/src/backenddb/store_wire_fee_by_exchange.c @@ -1,72 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/store_wire_fee_by_exchange.c - * @brief Implementation of the store_wire_fee_by_exchange function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/store_wire_fee_by_exchange.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_store_wire_fee_by_exchange ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const struct TALER_MasterPublicKeyP *master_pub, - const struct GNUNET_HashCode *h_wire_method, - const struct TALER_WireFeeSet *fees, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - const struct TALER_MasterSignatureP *master_sig) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (master_pub), - GNUNET_PQ_query_param_auto_from_type (h_wire_method), - TALER_PQ_query_param_amount_with_currency (pg->conn, - &fees->wire), - TALER_PQ_query_param_amount_with_currency (pg->conn, - &fees->closing), - GNUNET_PQ_query_param_timestamp (&start_date), - GNUNET_PQ_query_param_timestamp (&end_date), - GNUNET_PQ_query_param_auto_from_type (master_sig), - GNUNET_PQ_query_param_end - }; - - /* no preflight check here, run in its own transaction by the caller */ - PREPARE (pg, - "insert_wire_fee", - "INSERT INTO merchant.merchant_exchange_wire_fees" - "(master_pub" - ",h_wire_method" - ",wire_fee" - ",closing_fee" - ",start_date" - ",end_date" - ",master_sig)" - " VALUES " - "($1, $2, $3, $4, $5, $6, $7)" - " ON CONFLICT DO NOTHING"); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Storing wire fee for %s starting at %s of %s\n", - TALER_B2S (master_pub), - GNUNET_TIME_timestamp2s (start_date), - TALER_amount2s (&fees->wire)); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_wire_fee", - params); -} diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c @@ -30,14 +30,14 @@ #include "merchant-database/iterate_kyc_statuses.h" #include "merchant-database/insert_kyc_status.h" #include "merchant-database/delete_contract_terms.h" -#include "merchant-database/delete_instance_private_key.h" +#include "merchant-database/update_to_instance_private_key_deleted.h" #include "merchant-database/delete_order.h" #include "merchant-database/delete_pending_webhook.h" #include "merchant-database/delete_product.h" #include "merchant-database/delete_template.h" #include "merchant-database/delete_webhook.h" -#include "merchant-database/inactivate_account.h" -#include "merchant-database/increase_refund.h" +#include "merchant-database/update_to_account_inactive.h" +#include "merchant-database/do_increase_refund.h" #include "merchant-database/insert_account.h" #include "merchant-database/insert_contract_terms.h" #include "merchant-database/insert_deposit.h" @@ -55,7 +55,7 @@ #include "merchant-database/insert_transfer.h" #include "merchant-database/insert_transfer_details.h" #include "merchant-database/insert_webhook.h" -#include "merchant-database/lock_product.h" +#include "merchant-database/insert_inventory_lock.h" #include "merchant-database/get_account_serial.h" #include "merchant-database/get_contract_terms.h" #include "merchant-database/get_contract_terms_status.h" @@ -84,12 +84,12 @@ #include "merchant-database/iterate_webhooks_by_event.h" #include "merchant-database/iterate_webhooks.h" #include "merchant-database/get_wire_fee.h" -#include "merchant-database/mark_contract_paid.h" -#include "merchant-database/mark_order_wired.h" -#include "merchant-database/refund_coin.h" +#include "merchant-database/update_to_contract_terms_paid.h" +#include "merchant-database/update_to_contract_terms_wired.h" +#include "merchant-database/insert_refund_by_coin.h" #include "merchant-database/set_instance.h" -#include "merchant-database/store_wire_fee_by_exchange.h" -#include "merchant-database/unlock_inventory.h" +#include "merchant-database/insert_wire_fee.h" +#include "merchant-database/delete_inventory_lock.h" #include "merchant-database/update_contract_terms.h" #include "merchant-database/update_instance.h" #include "merchant-database/update_pending_webhook.h" @@ -99,7 +99,7 @@ #include "merchant-database/create_tables.h" #include "merchant-database/drop_tables.h" #include "merchant-database/preflight.h" -#include "merchant-database/purge_instance.h" +#include "merchant-database/delete_instance.h" /** @@ -517,7 +517,7 @@ test_delete_instance_private_key (const struct InstanceData *instance, { TEST_SET_INSTANCE (instance->instance.id, expected_result); TEST_COND_RET_ON_FAIL (expected_result == - TALER_MERCHANTDB_delete_instance_private_key ( + TALER_MERCHANTDB_update_to_instance_private_key_deleted ( pg, instance->instance.id), "Delete instance private key failed\n"); @@ -538,8 +538,8 @@ test_purge_instance (const struct InstanceData *instance, { TEST_SET_INSTANCE (instance->instance.id, expected_result); TEST_COND_RET_ON_FAIL (expected_result == - TALER_MERCHANTDB_purge_instance (pg, - instance->instance.id), + TALER_MERCHANTDB_delete_instance (pg, + instance->instance.id), "Purge instance failed\n"); return 0; } @@ -581,9 +581,9 @@ test_inactivate_account (const struct InstanceData *instance, { TEST_SET_INSTANCE (instance->instance.id, expected_result); TEST_COND_RET_ON_FAIL (expected_result == - TALER_MERCHANTDB_inactivate_account (pg, - instance->instance.id, - &account->h_wire), + TALER_MERCHANTDB_update_to_account_inactive (pg, + instance->instance.id, + &account->h_wire), "Deactivate account failed\n"); return 0; } @@ -1498,25 +1498,25 @@ run_test_products (struct TestProducts_Closure *cls) cls->products)); /* Test locking */ uuid.value[0] = 0x1287346a; - if (0 != TALER_MERCHANTDB_lock_product (pg, - cls->instance.instance.id, - cls->products[0].id, - &uuid, - 256, - 0, - refund_deadline)) + if (0 != TALER_MERCHANTDB_insert_inventory_lock (pg, + cls->instance.instance.id, + cls->products[0].id, + &uuid, + 256, + 0, + refund_deadline)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Lock product failed\n"); return 1; } - if (1 != TALER_MERCHANTDB_lock_product (pg, - cls->instance.instance.id, - cls->products[0].id, - &uuid, - 1, - 0, - refund_deadline)) + if (1 != TALER_MERCHANTDB_insert_inventory_lock (pg, + cls->instance.instance.id, + cls->products[0].id, + &uuid, + 1, + 0, + refund_deadline)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Lock product failed\n"); @@ -1538,28 +1538,28 @@ run_test_products (struct TestProducts_Closure *cls) 1, cls->products)); /* Test unlocking */ - if (1 != TALER_MERCHANTDB_unlock_inventory (pg, - &uuid)) + if (1 != TALER_MERCHANTDB_delete_inventory_lock (pg, + &uuid)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unlock inventory failed\n"); return 1; } - if (0 != TALER_MERCHANTDB_unlock_inventory (pg, - &uuid)) + if (0 != TALER_MERCHANTDB_delete_inventory_lock (pg, + &uuid)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unlock inventory failed\n"); return 1; } /* Re-lock products[0] to exercise deletion of a locked product */ - if (1 != TALER_MERCHANTDB_lock_product (pg, - cls->instance.instance.id, - cls->products[0].id, - &uuid, - 1, - 0, - refund_deadline)) + if (1 != TALER_MERCHANTDB_insert_inventory_lock (pg, + cls->instance.instance.id, + cls->products[0].id, + &uuid, + 1, + 0, + refund_deadline)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Lock product failed\n"); @@ -2137,11 +2137,11 @@ test_mark_contract_paid (const struct InstanceData *instance, &h_contract_terms)); TEST_SET_INSTANCE (instance->instance.id, expected_result); TEST_COND_RET_ON_FAIL (expected_result == - TALER_MERCHANTDB_mark_contract_paid (pg, - instance->instance.id, - &h_contract_terms, - "test_orders_session", - -1), + TALER_MERCHANTDB_update_to_contract_terms_paid (pg, + instance->instance.id, + &h_contract_terms, + "test_orders_session", + -1), "Mark contract paid failed\n"); return 0; } @@ -2309,8 +2309,8 @@ test_mark_order_wired (uint64_t order_id, enum GNUNET_DB_QueryStatus expected_result) { TEST_COND_RET_ON_FAIL (expected_result == - TALER_MERCHANTDB_mark_order_wired (pg, - order_id), + TALER_MERCHANTDB_update_to_contract_terms_wired (pg, + order_id), "Mark order wired failed\n"); return 0; } @@ -4165,7 +4165,7 @@ test_insert_wire_fee (const struct ExchangeSignkeyData *signkey, enum GNUNET_DB_QueryStatus expected_result) { TEST_COND_RET_ON_FAIL (expected_result == - TALER_MERCHANTDB_store_wire_fee_by_exchange ( + TALER_MERCHANTDB_insert_wire_fee ( pg, &signkey->master_pub, &wire_fee->h_wire_method, @@ -5364,26 +5364,26 @@ run_test_refunds (struct TestRefunds_Closure *cls) GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); /* Test refund coin */ TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == - TALER_MERCHANTDB_refund_coin (pg, - cls->instance.instance.id, - &cls->deposits[0].h_contract_terms - , - cls->refunds[0].timestamp, - cls->refunds[0].coin_pub, - cls->refunds[0].reason), + TALER_MERCHANTDB_insert_refund_by_coin (pg, + cls->instance.instance.id, + &cls->deposits[0].h_contract_terms + , + cls->refunds[0].timestamp, + cls->refunds[0].coin_pub, + cls->refunds[0].reason), "Refund coin failed\n"); refund_serial = get_refund_serial (&cls->instance, &cls->deposits[0].h_contract_terms, &cls->refunds[0]); /* Test double refund fails */ TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == - TALER_MERCHANTDB_refund_coin (pg, - cls->instance.instance.id, - &cls->deposits[0].h_contract_terms - , - cls->refunds[0].timestamp, - cls->refunds[0].coin_pub, - cls->refunds[0].reason), + TALER_MERCHANTDB_insert_refund_by_coin (pg, + cls->instance.instance.id, + &cls->deposits[0].h_contract_terms + , + cls->refunds[0].timestamp, + cls->refunds[0].coin_pub, + cls->refunds[0].reason), "Refund coin failed\n"); /* Test lookup refunds */ TEST_RET_ON_FAIL (test_lookup_refunds (&cls->instance, @@ -5420,26 +5420,26 @@ run_test_refunds (struct TestRefunds_Closure *cls) TALER_string_to_amount ("EUR:1000.00", &inc)); TEST_COND_RET_ON_FAIL (TALER_MERCHANTDB_RS_TOO_HIGH == - TALER_MERCHANTDB_increase_refund (pg, - cls->instance.instance.id, - cls->orders[0].id, - &inc, - NULL, - NULL, - "more"), + TALER_MERCHANTDB_do_increase_refund (pg, + cls->instance.instance.id, + cls->orders[0].id, + &inc, + NULL, + NULL, + "more"), "Increase refund failed\n"); /* Test increase refund */ GNUNET_assert (GNUNET_OK == TALER_string_to_amount ("EUR:1.00", &inc)); TEST_COND_RET_ON_FAIL (TALER_MERCHANTDB_RS_SUCCESS == - TALER_MERCHANTDB_increase_refund (pg, - cls->instance.instance.id, - cls->orders[0].id, - &inc, - NULL, - NULL, - "more"), + TALER_MERCHANTDB_do_increase_refund (pg, + cls->instance.instance.id, + cls->orders[0].id, + &inc, + NULL, + NULL, + "more"), "Increase refund failed\n"); /* Test lookup refund proof */ TEST_RET_ON_FAIL (test_lookup_refund_proof (1, @@ -5463,25 +5463,25 @@ run_test_refunds (struct TestRefunds_Closure *cls) TALER_string_to_amount ("EUR:10.00", &inc)); TEST_COND_RET_ON_FAIL (TALER_MERCHANTDB_RS_SUCCESS == - TALER_MERCHANTDB_increase_refund (pg, - cls->instance.instance.id, - cls->orders[1].id, - &inc, - NULL, - NULL, - cls->refunds[1].reason), + TALER_MERCHANTDB_do_increase_refund (pg, + cls->instance.instance.id, + cls->orders[1].id, + &inc, + NULL, + NULL, + cls->refunds[1].reason), "Increase refund failed\n"); GNUNET_assert (GNUNET_OK == TALER_string_to_amount ("EUR:20.00", &inc)); TEST_COND_RET_ON_FAIL (TALER_MERCHANTDB_RS_SUCCESS == - TALER_MERCHANTDB_increase_refund (pg, - cls->instance.instance.id, - cls->orders[1].id, - &inc, - NULL, - NULL, - cls->refunds[2].reason), + TALER_MERCHANTDB_do_increase_refund (pg, + cls->instance.instance.id, + cls->orders[1].id, + &inc, + NULL, + NULL, + cls->refunds[2].reason), "Increase refund failed\n"); TEST_RET_ON_FAIL (test_lookup_refunds_detailed (&cls->instance, &cls->deposits[2]. @@ -5694,13 +5694,13 @@ run_test_lookup_orders_all_filters ( &cls->deposits[i], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == - TALER_MERCHANTDB_refund_coin (pg, - cls->instance.instance.id, - &cls->deposits[i]. - h_contract_terms, - cls->refunds[i].timestamp, - cls->refunds[i].coin_pub, - cls->refunds[i].reason), + TALER_MERCHANTDB_insert_refund_by_coin (pg, + cls->instance.instance.id, + &cls->deposits[i]. + h_contract_terms, + cls->refunds[i].timestamp, + cls->refunds[i].coin_pub, + cls->refunds[i].reason), "Refund coin failed\n"); } diff --git a/src/backenddb/unlock_inventory.c b/src/backenddb/unlock_inventory.c @@ -1,45 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/unlock_inventory.c - * @brief Implementation of the unlock_inventory function for Postgres - * @author Iván Ávalos - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "merchant-database/unlock_inventory.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_unlock_inventory ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const struct GNUNET_Uuid *uuid) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (uuid), - GNUNET_PQ_query_param_end - }; - - GNUNET_assert (NULL != pg->current_merchant_id); - TMH_PQ_prepare_anon (pg, - "DELETE" - " FROM merchant_inventory_locks" - " WHERE lock_uuid=$1"); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "", - params); -} diff --git a/src/backenddb/update_money_pot_totals.c b/src/backenddb/update_money_pot_totals.c @@ -0,0 +1,76 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/update_money_pot_totals.c + * @brief Implementation of the update_money_pot_totals function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "merchant-database/update_money_pot_totals.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_money_pot_totals ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + size_t money_pots_len, + const uint64_t *money_pot_ids, + const struct TALER_Amount *pot_increments) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_array_uint64 (money_pots_len, + money_pot_ids, + pg->conn), + TALER_PQ_query_param_array_amount_with_currency (money_pots_len, + pot_increments, + "merchant", + pg->conn), + GNUNET_PQ_query_param_end + }; + bool not_found; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("not_found", + &not_found), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_assert (NULL != pg->current_merchant_id); + GNUNET_assert (0 == strcmp (instance_id, + pg->current_merchant_id)); + TMH_PQ_prepare_anon (pg, + "SELECT" + " out_not_found AS not_found" + " FROM merchant_do_increment_money_pots" + "($1,$2);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "", + params, + rs); + GNUNET_PQ_cleanup_query_params_closures (params); + if (qs <= 0) + return qs; + if (not_found) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Some money pots could not be implemented because they no longer exist. This is not a bug and expected to happen if a merchant deletes money pots that were used in orders active at the time.\n"); + } + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; +} diff --git a/src/backenddb/increment_money_pots.sql b/src/backenddb/update_money_pot_totals.sql diff --git a/src/backenddb/update_to_account_inactive.c b/src/backenddb/update_to_account_inactive.c @@ -0,0 +1,61 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/update_to_account_inactive.c + * @brief Implementation of the update_to_account_inactive function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/update_to_account_inactive.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_account_inactive ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *merchant_id, + const struct TALER_MerchantWireHashP *h_wire) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_wire), + GNUNET_PQ_query_param_end + }; + bool found; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("found", + &found), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_assert (NULL != pg->current_merchant_id); + GNUNET_assert (0 == strcmp (merchant_id, + pg->current_merchant_id)); + TMH_PQ_prepare_anon (pg, + "SELECT out_found AS found" + " FROM merchant_do_inactivate_account" + " ($1);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "", + params, + rs); + if (qs < 0) + return qs; + if (! found) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return qs; +} diff --git a/src/backenddb/inactivate_account.sql b/src/backenddb/update_to_account_inactive.sql diff --git a/src/backenddb/update_to_contract_terms_paid.c b/src/backenddb/update_to_contract_terms_paid.c @@ -0,0 +1,107 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/update_to_contract_terms_paid.c + * @brief Implementation of the update_to_contract_terms_paid function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/update_to_contract_terms_paid.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_contract_terms_paid ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + const struct TALER_PrivateContractHashP *h_contract_terms, + const char *session_id, + int16_t choice_index) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_string (session_id), + (choice_index >= 0) + ? GNUNET_PQ_query_param_int16 (&choice_index) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_QueryParam uparams[] = { + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + /* Session ID must always be given by the caller. */ + GNUNET_assert (NULL != session_id); + GNUNET_assert (NULL != pg->current_merchant_id); + GNUNET_assert (0 == strcmp (instance_id, + pg->current_merchant_id)); + + /* FIXME: combine the 3 individual statements into a stored procedure! */ + /* no preflight check here, run in transaction by caller! */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Marking h_contract_terms '%s' of %s as paid for session `%s'\n", + GNUNET_h2s (&h_contract_terms->hash), + instance_id, + session_id); + TMH_PQ_prepare_anon (pg, + "UPDATE merchant_contract_terms SET" + " paid=TRUE" + ",session_id=$2" + ",choice_index=$3" + " WHERE h_contract_terms=$1"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "", + params); + if (qs <= 0) + return qs; + TMH_PQ_prepare_anon (pg, + "UPDATE merchant_inventory SET" + " total_sold = total_sold" + " + order_locks.total_locked" + " + ((merchant_inventory.total_sold_frac::BIGINT" + " + order_locks.total_locked_frac::BIGINT) / 1000000)" + " ,total_sold_frac =" + " ((merchant_inventory.total_sold_frac::BIGINT" + " + order_locks.total_locked_frac::BIGINT) % 1000000)::INT4" + " FROM (SELECT total_locked,total_locked_frac,product_serial" + " FROM merchant_order_locks" + " WHERE order_serial=" + " (SELECT order_serial" + " FROM merchant_contract_terms" + " WHERE h_contract_terms=$1)" + " ) AS order_locks" + " WHERE merchant_inventory.product_serial" + " =order_locks.product_serial"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "", + uparams); + if (qs < 0) + return qs; /* 0: no inventory management, that's OK! */ + /* ON DELETE CASCADE deletes from merchant_order_locks */ + TMH_PQ_prepare_anon (pg, + "DELETE" + " FROM merchant_orders" + " WHERE order_serial=" + " (SELECT order_serial" + " FROM merchant_contract_terms" + " WHERE h_contract_terms=$1)"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "", + uparams); +} diff --git a/src/backenddb/update_to_contract_terms_wired.c b/src/backenddb/update_to_contract_terms_wired.c @@ -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 <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/update_to_contract_terms_wired.c + * @brief Implementation of the update_to_contract_terms_wired function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/update_to_contract_terms_wired.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_contract_terms_wired ( + struct TALER_MERCHANTDB_PostgresContext *pg, + uint64_t order_serial) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&order_serial), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (NULL != pg->current_merchant_id); + TMH_PQ_prepare_anon (pg, + "UPDATE merchant_contract_terms SET" + " wired=TRUE" + " WHERE order_serial=$1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "", + params); +} diff --git a/src/backenddb/update_to_instance_private_key_deleted.c b/src/backenddb/update_to_instance_private_key_deleted.c @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/update_to_instance_private_key_deleted.c + * @brief Implementation of the update_to_instance_private_key_deleted function for Postgres + * @author Iván Ávalos + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/update_to_instance_private_key_deleted.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_instance_private_key_deleted ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *merchant_id) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (merchant_id), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "delete_instance_private_key", + "UPDATE merchant.merchant_instances" + " SET merchant_priv = NULL" + " WHERE merchant_id = $1"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "delete_instance_private_key", + params); +} diff --git a/src/backenddb/update_to_transfer_finalized.c b/src/backenddb/update_to_transfer_finalized.c @@ -0,0 +1,76 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/backenddb/update_to_transfer_finalized.c + * @brief Implementation of the update_to_transfer_finalized function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_pq_lib.h> +#include "merchant-database/update_to_transfer_finalized.h" +#include "helper.h" + + +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_transfer_finalized ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *exchange_url, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct GNUNET_HashCode *h_details, + const struct TALER_Amount *total_amount, + const struct TALER_Amount *wire_fee, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_ExchangeSignatureP *exchange_sig) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (wtid), + GNUNET_PQ_query_param_string (exchange_url), + TALER_PQ_query_param_amount_with_currency (pg->conn, + total_amount), + TALER_PQ_query_param_amount_with_currency (pg->conn, + wire_fee), + GNUNET_PQ_query_param_auto_from_type (h_details), + GNUNET_PQ_query_param_auto_from_type (exchange_pub), + GNUNET_PQ_query_param_auto_from_type (exchange_sig), + GNUNET_PQ_query_param_end + }; + + GNUNET_assert (NULL != pg->current_merchant_id); + TMH_PQ_prepare_anon (pg, + "WITH subquery AS (" + " SELECT signkey_serial" + " FROM merchant.merchant_exchange_signing_keys" + " WHERE exchange_pub=$6" + ")" + "UPDATE merchant_expected_transfers SET" + " last_http_status=200" + ",last_ec=0" + ",last_detail=NULL" + ",retry_needed=FALSE" + ",retry_time=0" + ",expected_credit_amount=$3" + ",wire_fee=$4" + ",h_details=$5" + ",signkey_serial=subquery.signkey_serial" + ",exchange_sig=$7" + " FROM subquery" + " WHERE wtid=$1" + " AND exchange_url=$2"); + return GNUNET_PQ_eval_prepared_non_select ( + pg->conn, + "", + params); +} diff --git a/src/backenddb/upsert_donau_keys.c b/src/backenddb/upsert_donau_keys.c @@ -1,70 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/backenddb/upsert_donau_keys.c - * @brief Implementation of the upsert_donau_keys function for Postgres - * @author Bohdan Potuzhnyi - * @author Vlada Svirsh - */ -#include "platform.h" -#include <taler/taler_pq_lib.h> -#include "donau/donau_service.h" -#include "merchant-database/upsert_donau_keys.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_upsert_donau_keys ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const struct DONAU_Keys *keys, - struct GNUNET_TIME_Absolute first_retry) -{ - enum GNUNET_DB_QueryStatus qs; - json_t *jkeys = DONAU_keys_to_json (keys); - - if (NULL == jkeys) - return GNUNET_DB_STATUS_HARD_ERROR; - - { - struct GNUNET_PQ_QueryParam params[] = { - TALER_PQ_query_param_json (jkeys), - GNUNET_PQ_query_param_absolute_time (&first_retry), - GNUNET_PQ_query_param_string (keys->donau_url), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "insert_donau_keys", - "INSERT INTO merchant.merchant_donau_keys" - " (keys_json" - " ,first_retry" - " ,donau_url" - " ) VALUES (" - " $1::TEXT::JSONB" - " ,$2" - " ,$3)" - " ON CONFLICT (donau_url)" - " DO UPDATE SET" - " keys_json=EXCLUDED.keys_json," - " first_retry=EXCLUDED.first_retry;"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_donau_keys", - params); - } - - json_decref (jkeys); - return qs; -} diff --git a/src/include/merchant-database/activate_account.h b/src/include/merchant-database/activate_account.h @@ -1,50 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/activate_account.h - * @brief implementation of the activate_account function for Postgres - * @author Iván Ávalos - */ -#ifndef MERCHANT_DATABASE_ACTIVATE_ACCOUNT_H -#define MERCHANT_DATABASE_ACTIVATE_ACCOUNT_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Insert account or set an instance's - * existing account in our database to "active". - * - * @param pg database context - * @param account_details details of the account to actiate - * @param[out] h_wire set to the hash of the salted payto URI - * @param[out] salt set to salt used for computing @a h_wire - * @param[out] not_found set to true if the instance was not found - * @param[out] conflict set to true if a conflicting account is active - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_activate_account (struct TALER_MERCHANTDB_PostgresContext *pg, - const struct TALER_MERCHANTDB_AccountDetails *account_details, - struct TALER_MerchantWireHashP *h_wire, - struct TALER_WireSaltP *salt, - bool *not_found, - bool *conflict); - -#endif diff --git a/src/include/merchant-database/all.h b/src/include/merchant-database/all.h @@ -8,18 +8,18 @@ #include "merchant-database/iterate_kyc_statuses.h" #include "merchant-database/insert_kyc_failure.h" #include "merchant-database/insert_kyc_status.h" -#include "merchant-database/activate_account.h" +#include "merchant-database/do_insert_account.h" #include "merchant-database/get_exists_donau_instance.h" #include "merchant-database/get_missing_money_pot.h" #include "merchant-database/get_report_by_token.h" #include "merchant-database/get_exists_transfer.h" -#include "merchant-database/create_mfa_challenge.h" +#include "merchant-database/insert_mfa_challenge.h" #include "merchant-database/create_tables.h" #include "merchant-database/delete_category.h" #include "merchant-database/delete_contract_terms.h" #include "merchant-database/delete_donau_instance.h" #include "merchant-database/delete_exchange_accounts.h" -#include "merchant-database/delete_instance_private_key.h" +#include "merchant-database/update_to_instance_private_key_deleted.h" #include "merchant-database/delete_login_token.h" #include "merchant-database/delete_login_token_by_serial.h" #include "merchant-database/delete_money_pot.h" @@ -38,14 +38,14 @@ #include "merchant-database/drop_tables.h" #include "merchant-database/event_listen.h" #include "merchant-database/event_notify.h" -#include "merchant-database/expire_locks.h" -#include "merchant-database/finalize_transfer_status.h" +#include "merchant-database/do_expire_locks.h" +#include "merchant-database/update_to_transfer_finalized.h" #include "merchant-database/gc.h" #include "merchant-database/get_kyc_limits.h" #include "merchant-database/get_kyc_status.h" -#include "merchant-database/inactivate_account.h" -#include "merchant-database/increase_refund.h" -#include "merchant-database/increment_money_pots.h" +#include "merchant-database/update_to_account_inactive.h" +#include "merchant-database/do_increase_refund.h" +#include "merchant-database/update_money_pot_totals.h" #include "merchant-database/insert_account.h" #include "merchant-database/insert_category.h" #include "merchant-database/insert_contract_terms.h" @@ -79,7 +79,7 @@ #include "merchant-database/insert_unclaim_signature.h" #include "merchant-database/insert_unit.h" #include "merchant-database/insert_webhook.h" -#include "merchant-database/lock_product.h" +#include "merchant-database/insert_inventory_lock.h" #include "merchant-database/get_account_serial.h" #include "merchant-database/iterate_all_products.h" #include "merchant-database/iterate_all_webhooks.h" @@ -142,11 +142,11 @@ #include "merchant-database/iterate_webhooks_by_event.h" #include "merchant-database/iterate_webhooks.h" #include "merchant-database/get_wire_fee.h" -#include "merchant-database/mark_contract_paid.h" -#include "merchant-database/mark_order_wired.h" +#include "merchant-database/update_to_contract_terms_paid.h" +#include "merchant-database/update_to_contract_terms_wired.h" #include "merchant-database/preflight.h" -#include "merchant-database/purge_instance.h" -#include "merchant-database/refund_coin.h" +#include "merchant-database/delete_instance.h" +#include "merchant-database/insert_refund_by_coin.h" #include "merchant-database/get_account.h" #include "merchant-database/get_account_by_uri.h" #include "merchant-database/iterate_accounts.h" @@ -173,10 +173,10 @@ #include "merchant-database/get_unit.h" #include "merchant-database/iterate_wirewatch_accounts.h" #include "merchant-database/set_instance.h" -#include "merchant-database/solve_mfa_challenge.h" +#include "merchant-database/do_solve_mfa_challenge.h" #include "merchant-database/start.h" -#include "merchant-database/store_wire_fee_by_exchange.h" -#include "merchant-database/unlock_inventory.h" +#include "merchant-database/insert_wire_fee.h" +#include "merchant-database/delete_inventory_lock.h" #include "merchant-database/update_account.h" #include "merchant-database/update_category.h" #include "merchant-database/update_contract_session.h" @@ -200,6 +200,6 @@ #include "merchant-database/update_unit.h" #include "merchant-database/update_webhook.h" #include "merchant-database/update_wirewatch_progress.h" -#include "merchant-database/upsert_donau_keys.h" +#include "merchant-database/insert_donau_keys.h" #endif diff --git a/src/include/merchant-database/create_mfa_challenge.h b/src/include/merchant-database/create_mfa_challenge.h @@ -1,63 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/create_mfa_challenge.h - * @brief implementation of the create_mfa_challenge function for Postgres - * @author Christian Grothoff - */ -#ifndef MERCHANT_DATABASE_CREATE_MFA_CHALLENGE_H -#define MERCHANT_DATABASE_CREATE_MFA_CHALLENGE_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -/** - * Create new multi-factor authorization (MFA) challenge in the database. - * - * @param pg database context - * @param instance_name name of the instance impacted by the challenge; - * used when communicating with the user; instance does not yet - * need to exist (as it might be we are creating it!) - * @param op operation that triggered the MFA request - * @param h_body hash of the request body - * @param salt salt used to compute @a h_body - * @param code challenge code sent to the user - * @param expiration_date when should the challenge expire - * @param retransmission_date when do we next allow retransmission - * of the challenge - * @param tan_channel which channel was used - * @param required_address address - * where the challenge is to be sent - * @param[out] challenge_id set to the ID of the new challenge - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_create_mfa_challenge ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_name, - enum TALER_MERCHANT_MFA_CriticalOperation op, - const struct TALER_MERCHANT_MFA_BodyHash *h_body, - const struct TALER_MERCHANT_MFA_BodySalt *salt, - const char *code, - struct GNUNET_TIME_Absolute expiration_date, - struct GNUNET_TIME_Absolute retransmission_date, - enum TALER_MERCHANT_MFA_Channel tan_channel, - const char *required_address, - uint64_t *challenge_id); - -#endif diff --git a/src/include/merchant-database/delete_instance.h b/src/include/merchant-database/delete_instance.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/delete_instance.h + * @brief implementation of the delete_instance function for Postgres + * @author Christian Grothoff + */ +#ifndef MERCHANT_DATABASE_DELETE_INSTANCE_H +#define MERCHANT_DATABASE_DELETE_INSTANCE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +/** + * Purge an instance and all associated information from our database. + * Highly likely to cause undesired data loss. Use with caution. + * + * @param pg database context + * @param merchant_id identifier of the instance + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_delete_instance ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *merchant_id); + +#endif diff --git a/src/include/merchant-database/delete_instance_private_key.h b/src/include/merchant-database/delete_instance_private_key.h @@ -1,41 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/delete_instance_private_key.h - * @brief implementation of the delete_instance_private_key function for Postgres - * @author Christian Grothoff - */ -#ifndef MERCHANT_DATABASE_DELETE_INSTANCE_PRIVATE_KEY_H -#define MERCHANT_DATABASE_DELETE_INSTANCE_PRIVATE_KEY_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Delete private key of an instance from our database. - * - * @param pg database context - * @param merchant_id identifier of the instance - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_delete_instance_private_key (struct TALER_MERCHANTDB_PostgresContext *pg, - const char *merchant_id); - -#endif diff --git a/src/include/merchant-database/delete_inventory_lock.h b/src/include/merchant-database/delete_inventory_lock.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/delete_inventory_lock.h + * @brief implementation of the delete_inventory_lock function for Postgres + * @author Iván Ávalos + */ +#ifndef MERCHANT_DATABASE_DELETE_INVENTORY_LOCK_H +#define MERCHANT_DATABASE_DELETE_INVENTORY_LOCK_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Release an inventory lock by UUID. Releases ALL stocks locked under + * the given UUID. + * + * @param pg database context + * @param uuid the UUID to release locks for + * @return transaction status, + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS means there are no locks under @a uuid + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT indicates success + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_delete_inventory_lock (struct TALER_MERCHANTDB_PostgresContext *pg, + const struct GNUNET_Uuid *uuid); + +#endif diff --git a/src/include/merchant-database/do_expire_locks.h b/src/include/merchant-database/do_expire_locks.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/do_do_expire_locks.h + * @brief implementation of the do_expire_locks function for Postgres + * @author Iván Ávalos + */ +#ifndef MERCHANT_DATABASE_DO_EXPIRE_LOCKS_H +#define MERCHANT_DATABASE_DO_EXPIRE_LOCKS_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Release all expired product locks, including + * those from expired offers -- across all + * instances. + * + * @param pg database context + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_do_expire_locks (struct TALER_MERCHANTDB_PostgresContext *pg); + +#endif diff --git a/src/include/merchant-database/do_increase_refund.h b/src/include/merchant-database/do_increase_refund.h @@ -0,0 +1,79 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/do_do_increase_refund.h + * @brief implementation of the do_increase_refund function for Postgres + * @author Christian Grothoff + */ +#ifndef MERCHANT_DATABASE_DO_INCREASE_REFUND_H +#define MERCHANT_DATABASE_DO_INCREASE_REFUND_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/* Callback typedefs */ +/** + * Determines the maximum @a amount for a particular + * type of operation for a given @a exchange_url. + * + * @param cls closure + * @param exchange_url base URL of the exchange to get + * the limit for + * @param[in,out] amount lowered to the maximum amount + * allowed at the exchange + */ +typedef void +(*TALER_MERCHANTDB_OperationLimitCallback)( + void *cls, + const char *exchange_url, + struct TALER_Amount *amount); + +/** + * Function called when some backoffice staff decides to award or + * increase the refund on an existing contract. This function + * MUST be called from within a transaction scope setup by the + * caller as it executes mulrewardle SQL statements. + * + * @param pg database context + * @param instance_id instance identifier + * @param order_id the order to increase the refund for + * @param refund maximum refund to return to the customer for this contract + * @param olc function to call to obtain legal refund + * limits per exchange, NULL for no limits + * @param olc_cls closure for @a olc + * @param reason 0-terminated UTF-8 string giving the reason why the customer + * got a refund (free form, business-specific) + * @return transaction status + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a refund is ABOVE the amount we + * were originally paid and thus the transaction failed; + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the request is valid, + * regardless of whether it actually increased the refund beyond + * what was already refunded (idempotency!) + */ +enum TALER_MERCHANTDB_RefundStatus +TALER_MERCHANTDB_do_increase_refund (struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + const char *order_id, + const struct TALER_Amount *refund, + TALER_MERCHANTDB_OperationLimitCallback olc, + void *olc_cls, + const char *reason); + + +#endif diff --git a/src/include/merchant-database/do_insert_account.h b/src/include/merchant-database/do_insert_account.h @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/do_insert_account.h + * @brief implementation of the do_insert_account function for Postgres + * @author Iván Ávalos + */ +#ifndef MERCHANT_DATABASE_DO_INSERT_ACCOUNT_H +#define MERCHANT_DATABASE_DO_INSERT_ACCOUNT_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Insert account or set an instance's + * existing account in our database to "active". + * + * @param pg database context + * @param account_details details of the account to actiate + * @param[out] h_wire set to the hash of the salted payto URI + * @param[out] salt set to salt used for computing @a h_wire + * @param[out] not_found set to true if the instance was not found + * @param[out] conflict set to true if a conflicting account is active + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_do_insert_account (struct TALER_MERCHANTDB_PostgresContext *pg, + const struct TALER_MERCHANTDB_AccountDetails *account_details, + struct TALER_MerchantWireHashP *h_wire, + struct TALER_WireSaltP *salt, + bool *not_found, + bool *conflict); + +#endif diff --git a/src/include/merchant-database/do_solve_mfa_challenge.h b/src/include/merchant-database/do_solve_mfa_challenge.h @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/do_do_solve_mfa_challenge.h + * @brief implementation of the do_solve_mfa_challenge function for Postgres + * @author Christian Grothoff + */ +#ifndef MERCHANT_DATABASE_DO_SOLVE_MFA_CHALLENGE_H +#define MERCHANT_DATABASE_DO_SOLVE_MFA_CHALLENGE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Attempt to solve new multi-factor authorization (MFA) challenge. + * Checks the solution against the code in the database and updates + * the solution state and (on failure) retry counter depending on + * the result. + * + * @param pg database context + * @param challenge_id challenge ID to be solved + * @param h_body body of the operation the challenge authorizes + * @param solution proposed solution to be checked against the actual code + * @param[out] solved set to true if the challenge was solved by + * @a solution + * @param[out] retry_counter set to the number of attempts that remain + * for solving the challenge (after this time) + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_do_solve_mfa_challenge (struct TALER_MERCHANTDB_PostgresContext *pg, + uint64_t challenge_id, + const struct TALER_MERCHANT_MFA_BodyHash *h_body, + const char *solution, + bool *solved, + uint32_t *retry_counter); + +#endif diff --git a/src/include/merchant-database/expire_locks.h b/src/include/merchant-database/expire_locks.h @@ -1,41 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/expire_locks.h - * @brief implementation of the expire_locks function for Postgres - * @author Iván Ávalos - */ -#ifndef MERCHANT_DATABASE_EXPIRE_LOCKS_H -#define MERCHANT_DATABASE_EXPIRE_LOCKS_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Release all expired product locks, including - * those from expired offers -- across all - * instances. - * - * @param pg database context - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_expire_locks (struct TALER_MERCHANTDB_PostgresContext *pg); - -#endif diff --git a/src/include/merchant-database/finalize_transfer_status.h b/src/include/merchant-database/finalize_transfer_status.h @@ -1,54 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/finalize_transfer_status.h - * @brief implementation of the finalize_transfer_status function for Postgres - * @author Christian Grothoff - */ -#ifndef MERCHANT_DATABASE_FINALIZE_TRANSFER_STATUS_H -#define MERCHANT_DATABASE_FINALIZE_TRANSFER_STATUS_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Finalize transfer status. - * - * @param pg database context - * @param exchange_url the exchange that made the transfer - * @param wtid wire transfer subject - * @param h_details hash over all of the aggregated deposits - * @param total_amount total amount exchange claimed to have transferred - * @param wire_fee wire fee charged by the exchange - * @param exchange_pub key used to make @e exchange_sig - * @param exchange_sig signature of the exchange over reconciliation data - * @return database transaction status - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_finalize_transfer_status (struct TALER_MERCHANTDB_PostgresContext *pg, - const char *exchange_url, - const struct TALER_WireTransferIdentifierRawP *wtid, - const struct GNUNET_HashCode *h_details, - const struct TALER_Amount *total_amount, - const struct TALER_Amount *wire_fee, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_ExchangeSignatureP *exchange_sig); - - -#endif diff --git a/src/include/merchant-database/inactivate_account.h b/src/include/merchant-database/inactivate_account.h @@ -1,44 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/inactivate_account.h - * @brief implementation of the inactivate_account function for Postgres - * @author Iván Ávalos - */ -#ifndef MERCHANT_DATABASE_INACTIVATE_ACCOUNT_H -#define MERCHANT_DATABASE_INACTIVATE_ACCOUNT_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Set an instance's account in our database to "inactive". - * - * @param pg database context - * @param merchant_id merchant backend instance ID - * @param h_wire hash of the wire account to set to inactive - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_inactivate_account (struct TALER_MERCHANTDB_PostgresContext *pg, - const char *merchant_id, - const struct TALER_MerchantWireHashP *h_wire); - - -#endif diff --git a/src/include/merchant-database/increase_refund.h b/src/include/merchant-database/increase_refund.h @@ -1,79 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/increase_refund.h - * @brief implementation of the increase_refund function for Postgres - * @author Christian Grothoff - */ -#ifndef MERCHANT_DATABASE_INCREASE_REFUND_H -#define MERCHANT_DATABASE_INCREASE_REFUND_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/* Callback typedefs */ -/** - * Determines the maximum @a amount for a particular - * type of operation for a given @a exchange_url. - * - * @param cls closure - * @param exchange_url base URL of the exchange to get - * the limit for - * @param[in,out] amount lowered to the maximum amount - * allowed at the exchange - */ -typedef void -(*TALER_MERCHANTDB_OperationLimitCallback)( - void *cls, - const char *exchange_url, - struct TALER_Amount *amount); - -/** - * Function called when some backoffice staff decides to award or - * increase the refund on an existing contract. This function - * MUST be called from within a transaction scope setup by the - * caller as it executes mulrewardle SQL statements. - * - * @param pg database context - * @param instance_id instance identifier - * @param order_id the order to increase the refund for - * @param refund maximum refund to return to the customer for this contract - * @param olc function to call to obtain legal refund - * limits per exchange, NULL for no limits - * @param olc_cls closure for @a olc - * @param reason 0-terminated UTF-8 string giving the reason why the customer - * got a refund (free form, business-specific) - * @return transaction status - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a refund is ABOVE the amount we - * were originally paid and thus the transaction failed; - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the request is valid, - * regardless of whether it actually increased the refund beyond - * what was already refunded (idempotency!) - */ -enum TALER_MERCHANTDB_RefundStatus -TALER_MERCHANTDB_increase_refund (struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - const char *order_id, - const struct TALER_Amount *refund, - TALER_MERCHANTDB_OperationLimitCallback olc, - void *olc_cls, - const char *reason); - - -#endif diff --git a/src/include/merchant-database/increment_money_pots.h b/src/include/merchant-database/increment_money_pots.h @@ -1,50 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/increment_money_pots.h - * @brief implementation of the increment_money_pots function for Postgres - * @author Christian Grothoff - */ -#ifndef MERCHANT_DATABASE_INCREMENT_MONEY_POTS_H -#define MERCHANT_DATABASE_INCREMENT_MONEY_POTS_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Increment amounts in money pots. If a money pot does not exist, - * it is simply skipped (without causing an error!). - * - * @param pg database context - * @param instance_id instance to update money pot for - * @param money_pots_len length of the @a money_pots_ids - * and @a pot_increments arrays - * @param money_pot_ids serial numbers of the pots to increment - * @param pot_increments new amounts to add to the respective pot - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_increment_money_pots (struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - size_t money_pots_len, - const uint64_t *money_pot_ids, - const struct TALER_Amount *pot_increments); - - -#endif diff --git a/src/include/merchant-database/insert_donau_keys.h b/src/include/merchant-database/insert_donau_keys.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/insert_donau_keys.h + * @brief implementation of the insert_donau_keys function for Postgres + * @author Bohdan Potuzhnyi + * @author Vlada Svirsh + */ +#ifndef MERCHANT_DATABASE_INSERT_DONAU_KEYS_H +#define MERCHANT_DATABASE_INSERT_DONAU_KEYS_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" +#include "donau/donau_service.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Function to insert or update Donau keys in the merchant_donau_keys table. + * + * @param pg database context + * @param keys the DONAU_Keys object + * @param first_retry time when we make retry to update keys + * @return GNUNET_DB_QueryStatus transaction status + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_donau_keys (struct TALER_MERCHANTDB_PostgresContext *pg, + const struct DONAU_Keys *keys, + struct GNUNET_TIME_Absolute first_retry); + + +#endif diff --git a/src/include/merchant-database/insert_inventory_lock.h b/src/include/merchant-database/insert_inventory_lock.h @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/insert_inventory_lock.h + * @brief implementation of the insert_inventory_lock function for Postgres + * @author Iván Ávalos + */ +#ifndef MERCHANT_DATABASE_INSERT_INVENTORY_LOCK_H +#define MERCHANT_DATABASE_INSERT_INVENTORY_LOCK_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Lock stocks of a particular product. Note that the transaction must + * enforce that the "stocked-sold-lost >= locked" constraint holds. + * + * @param pg database context + * @param instance_id instance to lookup products for + * @param product_id product to lookup + * @param uuid the UUID that holds the lock + * @param quantity how many units should be locked + * @param quantity_frac fractional component of quantity in units of + * 1/1000000 of the base value + * @param expiration_time when should the lock expire + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the + * product is unknown OR if there insufficient stocks remaining + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_inventory_lock (struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + const char *product_id, + const struct GNUNET_Uuid *uuid, + uint64_t quantity, + uint32_t quantity_frac, + struct GNUNET_TIME_Timestamp expiration_time); + +#endif diff --git a/src/include/merchant-database/insert_mfa_challenge.h b/src/include/merchant-database/insert_mfa_challenge.h @@ -0,0 +1,63 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/insert_mfa_challenge.h + * @brief implementation of the insert_mfa_challenge function for Postgres + * @author Christian Grothoff + */ +#ifndef MERCHANT_DATABASE_INSERT_MFA_CHALLENGE_H +#define MERCHANT_DATABASE_INSERT_MFA_CHALLENGE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +/** + * Create new multi-factor authorization (MFA) challenge in the database. + * + * @param pg database context + * @param instance_name name of the instance impacted by the challenge; + * used when communicating with the user; instance does not yet + * need to exist (as it might be we are creating it!) + * @param op operation that triggered the MFA request + * @param h_body hash of the request body + * @param salt salt used to compute @a h_body + * @param code challenge code sent to the user + * @param expiration_date when should the challenge expire + * @param retransmission_date when do we next allow retransmission + * of the challenge + * @param tan_channel which channel was used + * @param required_address address + * where the challenge is to be sent + * @param[out] challenge_id set to the ID of the new challenge + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_mfa_challenge ( + struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_name, + enum TALER_MERCHANT_MFA_CriticalOperation op, + const struct TALER_MERCHANT_MFA_BodyHash *h_body, + const struct TALER_MERCHANT_MFA_BodySalt *salt, + const char *code, + struct GNUNET_TIME_Absolute expiration_date, + struct GNUNET_TIME_Absolute retransmission_date, + enum TALER_MERCHANT_MFA_Channel tan_channel, + const char *required_address, + uint64_t *challenge_id); + +#endif diff --git a/src/include/merchant-database/insert_refund_by_coin.h b/src/include/merchant-database/insert_refund_by_coin.h @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/insert_refund_by_coin.h + * @brief implementation of the insert_refund_by_coin function for Postgres + * @author Iván Ávalos + */ +#ifndef MERCHANT_DATABASE_INSERT_REFUND_BY_COIN_H +#define MERCHANT_DATABASE_INSERT_REFUND_BY_COIN_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Function called during aborts to refund a coin. Marks the + * respective coin as refunded. + * + * @param pg database context + * @param instance_id instance to refund payment for + * @param h_contract_terms hash of the contract to refund coin for + * @param refund_timestamp timestamp of the refund + * @param coin_pub public key of the coin to refund (fully) + * @param reason text justifying the refund + * @return transaction status + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a coin_pub is unknown to us; + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the request is valid, + * regardless of whether it actually increased the refund + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_refund_by_coin (struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp refund_timestamp, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const char *reason); + +#endif diff --git a/src/include/merchant-database/insert_wire_fee.h b/src/include/merchant-database/insert_wire_fee.h @@ -0,0 +1,52 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/insert_wire_fee.h + * @brief implementation of the postgres_store_wire_fee_by_exchange function for Postgres + * @author Christian Grothoff + */ +#ifndef MERCHANT_DATABASE_INSERT_WIRE_FEE_H +#define MERCHANT_DATABASE_INSERT_WIRE_FEE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Store information about wire fees charged by an exchange, + * including signature (so we have proof). + * + * @param pg database context + * @param master_pub public key of the exchange + * @param h_wire_method hash of wire method + * @param fees the fee charged + * @param start_date start of fee being used + * @param end_date end of fee being used + * @param master_sig signature of exchange over fee structure + * @return transaction status code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_insert_wire_fee (struct TALER_MERCHANTDB_PostgresContext *pg, + const struct TALER_MasterPublicKeyP *master_pub, + const struct GNUNET_HashCode *h_wire_method, + const struct TALER_WireFeeSet *fees, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_MasterSignatureP *master_sig); + +#endif diff --git a/src/include/merchant-database/lock_product.h b/src/include/merchant-database/lock_product.h @@ -1,54 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/lock_product.h - * @brief implementation of the lock_product function for Postgres - * @author Iván Ávalos - */ -#ifndef MERCHANT_DATABASE_LOCK_PRODUCT_H -#define MERCHANT_DATABASE_LOCK_PRODUCT_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Lock stocks of a particular product. Note that the transaction must - * enforce that the "stocked-sold-lost >= locked" constraint holds. - * - * @param pg database context - * @param instance_id instance to lookup products for - * @param product_id product to lookup - * @param uuid the UUID that holds the lock - * @param quantity how many units should be locked - * @param quantity_frac fractional component of quantity in units of - * 1/1000000 of the base value - * @param expiration_time when should the lock expire - * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the - * product is unknown OR if there insufficient stocks remaining - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_lock_product (struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - const char *product_id, - const struct GNUNET_Uuid *uuid, - uint64_t quantity, - uint32_t quantity_frac, - struct GNUNET_TIME_Timestamp expiration_time); - -#endif diff --git a/src/include/merchant-database/mark_contract_paid.h b/src/include/merchant-database/mark_contract_paid.h @@ -1,50 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/mark_contract_paid.h - * @brief implementation of the mark_contract_paid function for Postgres - * @author Iván Ávalos - */ -#ifndef MERCHANT_DATABASE_MARK_CONTRACT_PAID_H -#define MERCHANT_DATABASE_MARK_CONTRACT_PAID_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Mark contract as paid and store the current @a session_id - * for which the contract was paid. Deletes the underlying order - * and marks the locked stocks of the order as sold. - * - * @param pg database context - * @param instance_id instance to mark contract as paid for - * @param h_contract_terms hash of the contract that is now paid - * @param session_id the session that paid the contract - * @param choice_index the contract v1 choice index to select, -1 for v0 - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_mark_contract_paid (struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - const struct - TALER_PrivateContractHashP *h_contract_terms, - const char *session_id, - int16_t choice_index); - -#endif diff --git a/src/include/merchant-database/mark_order_wired.h b/src/include/merchant-database/mark_order_wired.h @@ -1,41 +0,0 @@ -/* - 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 <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/mark_order_wired.h - * @brief implementation of the mark_order_wired function for Postgres - * @author Iván Ávalos - */ -#ifndef MERCHANT_DATABASE_MARK_ORDER_WIRED_H -#define MERCHANT_DATABASE_MARK_ORDER_WIRED_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Set 'wired' status for an order to 'true'. - * - * @param pg database context - * @param order_serial serial number of the order - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_mark_order_wired (struct TALER_MERCHANTDB_PostgresContext *pg, - uint64_t order_serial); - -#endif diff --git a/src/include/merchant-database/purge_instance.h b/src/include/merchant-database/purge_instance.h @@ -1,42 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/purge_instance.h - * @brief implementation of the purge_instance function for Postgres - * @author Christian Grothoff - */ -#ifndef MERCHANT_DATABASE_PURGE_INSTANCE_H -#define MERCHANT_DATABASE_PURGE_INSTANCE_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -/** - * Purge an instance and all associated information from our database. - * Highly likely to cause undesired data loss. Use with caution. - * - * @param pg database context - * @param merchant_id identifier of the instance - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_purge_instance ( - struct TALER_MERCHANTDB_PostgresContext *pg, - const char *merchant_id); - -#endif diff --git a/src/include/merchant-database/refund_coin.h b/src/include/merchant-database/refund_coin.h @@ -1,53 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/refund_coin.h - * @brief implementation of the refund_coin function for Postgres - * @author Iván Ávalos - */ -#ifndef MERCHANT_DATABASE_REFUND_COIN_H -#define MERCHANT_DATABASE_REFUND_COIN_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Function called during aborts to refund a coin. Marks the - * respective coin as refunded. - * - * @param pg database context - * @param instance_id instance to refund payment for - * @param h_contract_terms hash of the contract to refund coin for - * @param refund_timestamp timestamp of the refund - * @param coin_pub public key of the coin to refund (fully) - * @param reason text justifying the refund - * @return transaction status - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a coin_pub is unknown to us; - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the request is valid, - * regardless of whether it actually increased the refund - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_refund_coin (struct TALER_MERCHANTDB_PostgresContext *pg, - const char *instance_id, - const struct TALER_PrivateContractHashP *h_contract_terms, - struct GNUNET_TIME_Timestamp refund_timestamp, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const char *reason); - -#endif diff --git a/src/include/merchant-database/solve_mfa_challenge.h b/src/include/merchant-database/solve_mfa_challenge.h @@ -1,54 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2025 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/solve_mfa_challenge.h - * @brief implementation of the solve_mfa_challenge function for Postgres - * @author Christian Grothoff - */ -#ifndef MERCHANT_DATABASE_SOLVE_MFA_CHALLENGE_H -#define MERCHANT_DATABASE_SOLVE_MFA_CHALLENGE_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Attempt to solve new multi-factor authorization (MFA) challenge. - * Checks the solution against the code in the database and updates - * the solution state and (on failure) retry counter depending on - * the result. - * - * @param pg database context - * @param challenge_id challenge ID to be solved - * @param h_body body of the operation the challenge authorizes - * @param solution proposed solution to be checked against the actual code - * @param[out] solved set to true if the challenge was solved by - * @a solution - * @param[out] retry_counter set to the number of attempts that remain - * for solving the challenge (after this time) - * @return database result code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_solve_mfa_challenge (struct TALER_MERCHANTDB_PostgresContext *pg, - uint64_t challenge_id, - const struct TALER_MERCHANT_MFA_BodyHash *h_body, - const char *solution, - bool *solved, - uint32_t *retry_counter); - -#endif diff --git a/src/include/merchant-database/store_wire_fee_by_exchange.h b/src/include/merchant-database/store_wire_fee_by_exchange.h @@ -1,52 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/store_wire_fee_by_exchange.h - * @brief implementation of the postgres_store_wire_fee_by_exchange function for Postgres - * @author Christian Grothoff - */ -#ifndef MERCHANT_DATABASE_STORE_WIRE_FEE_BY_EXCHANGE_H -#define MERCHANT_DATABASE_STORE_WIRE_FEE_BY_EXCHANGE_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Store information about wire fees charged by an exchange, - * including signature (so we have proof). - * - * @param pg database context - * @param master_pub public key of the exchange - * @param h_wire_method hash of wire method - * @param fees the fee charged - * @param start_date start of fee being used - * @param end_date end of fee being used - * @param master_sig signature of exchange over fee structure - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_store_wire_fee_by_exchange (struct TALER_MERCHANTDB_PostgresContext *pg, - const struct TALER_MasterPublicKeyP *master_pub, - const struct GNUNET_HashCode *h_wire_method, - const struct TALER_WireFeeSet *fees, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - const struct TALER_MasterSignatureP *master_sig); - -#endif diff --git a/src/include/merchant-database/unlock_inventory.h b/src/include/merchant-database/unlock_inventory.h @@ -1,44 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/unlock_inventory.h - * @brief implementation of the unlock_inventory function for Postgres - * @author Iván Ávalos - */ -#ifndef MERCHANT_DATABASE_UNLOCK_INVENTORY_H -#define MERCHANT_DATABASE_UNLOCK_INVENTORY_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Release an inventory lock by UUID. Releases ALL stocks locked under - * the given UUID. - * - * @param pg database context - * @param uuid the UUID to release locks for - * @return transaction status, - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS means there are no locks under @a uuid - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT indicates success - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_unlock_inventory (struct TALER_MERCHANTDB_PostgresContext *pg, - const struct GNUNET_Uuid *uuid); - -#endif diff --git a/src/include/merchant-database/update_money_pot_totals.h b/src/include/merchant-database/update_money_pot_totals.h @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/update_money_pot_totals.h + * @brief implementation of the update_money_pot_totals function for Postgres + * @author Christian Grothoff + */ +#ifndef MERCHANT_DATABASE_UPDATE_MONEY_POT_TOTALS_H +#define MERCHANT_DATABASE_UPDATE_MONEY_POT_TOTALS_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Increment amounts in money pots. If a money pot does not exist, + * it is simply skipped (without causing an error!). + * + * @param pg database context + * @param instance_id instance to update money pot for + * @param money_pots_len length of the @a money_pots_ids + * and @a pot_increments arrays + * @param money_pot_ids serial numbers of the pots to increment + * @param pot_increments new amounts to add to the respective pot + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_money_pot_totals (struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + size_t money_pots_len, + const uint64_t *money_pot_ids, + const struct TALER_Amount *pot_increments); + + +#endif diff --git a/src/include/merchant-database/update_to_account_inactive.h b/src/include/merchant-database/update_to_account_inactive.h @@ -0,0 +1,44 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/update_to_account_inactive.h + * @brief implementation of the update_to_account_inactive function for Postgres + * @author Iván Ávalos + */ +#ifndef MERCHANT_DATABASE_UPDATE_TO_ACCOUNT_INACTIVE_H +#define MERCHANT_DATABASE_UPDATE_TO_ACCOUNT_INACTIVE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Set an instance's account in our database to "inactive". + * + * @param pg database context + * @param merchant_id merchant backend instance ID + * @param h_wire hash of the wire account to set to inactive + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_account_inactive (struct TALER_MERCHANTDB_PostgresContext *pg, + const char *merchant_id, + const struct TALER_MerchantWireHashP *h_wire); + + +#endif diff --git a/src/include/merchant-database/update_to_contract_terms_paid.h b/src/include/merchant-database/update_to_contract_terms_paid.h @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/update_to_contract_terms_paid.h + * @brief implementation of the update_to_contract_terms_paid function for Postgres + * @author Iván Ávalos + */ +#ifndef MERCHANT_DATABASE_UPDATE_TO_CONTRACT_TERMS_PAID_H +#define MERCHANT_DATABASE_UPDATE_TO_CONTRACT_TERMS_PAID_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Mark contract as paid and store the current @a session_id + * for which the contract was paid. Deletes the underlying order + * and marks the locked stocks of the order as sold. + * + * @param pg database context + * @param instance_id instance to mark contract as paid for + * @param h_contract_terms hash of the contract that is now paid + * @param session_id the session that paid the contract + * @param choice_index the contract v1 choice index to select, -1 for v0 + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_contract_terms_paid (struct TALER_MERCHANTDB_PostgresContext *pg, + const char *instance_id, + const struct + TALER_PrivateContractHashP *h_contract_terms, + const char *session_id, + int16_t choice_index); + +#endif diff --git a/src/include/merchant-database/update_to_contract_terms_wired.h b/src/include/merchant-database/update_to_contract_terms_wired.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 <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/update_to_contract_terms_wired.h + * @brief implementation of the update_to_contract_terms_wired function for Postgres + * @author Iván Ávalos + */ +#ifndef MERCHANT_DATABASE_UPDATE_TO_CONTRACT_TERMS_WIRED_H +#define MERCHANT_DATABASE_UPDATE_TO_CONTRACT_TERMS_WIRED_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Set 'wired' status for an order to 'true'. + * + * @param pg database context + * @param order_serial serial number of the order + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_contract_terms_wired (struct TALER_MERCHANTDB_PostgresContext *pg, + uint64_t order_serial); + +#endif diff --git a/src/include/merchant-database/update_to_instance_private_key_deleted.h b/src/include/merchant-database/update_to_instance_private_key_deleted.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/update_to_instance_private_key_deleted.h + * @brief implementation of the update_to_instance_private_key_deleted function for Postgres + * @author Christian Grothoff + */ +#ifndef MERCHANT_DATABASE_UPDATE_TO_INSTANCE_PRIVATE_KEY_DELETED_H +#define MERCHANT_DATABASE_UPDATE_TO_INSTANCE_PRIVATE_KEY_DELETED_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Delete private key of an instance from our database. + * + * @param pg database context + * @param merchant_id identifier of the instance + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_instance_private_key_deleted (struct TALER_MERCHANTDB_PostgresContext *pg + , + const char *merchant_id); + +#endif diff --git a/src/include/merchant-database/update_to_transfer_finalized.h b/src/include/merchant-database/update_to_transfer_finalized.h @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/merchant-database/update_to_transfer_finalized.h + * @brief implementation of the update_to_transfer_finalized function for Postgres + * @author Christian Grothoff + */ +#ifndef MERCHANT_DATABASE_UPDATE_TO_TRANSFER_FINALIZED_H +#define MERCHANT_DATABASE_UPDATE_TO_TRANSFER_FINALIZED_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "merchantdb_lib.h" + + +struct TALER_MERCHANTDB_PostgresContext; +/** + * Finalize transfer status. + * + * @param pg database context + * @param exchange_url the exchange that made the transfer + * @param wtid wire transfer subject + * @param h_details hash over all of the aggregated deposits + * @param total_amount total amount exchange claimed to have transferred + * @param wire_fee wire fee charged by the exchange + * @param exchange_pub key used to make @e exchange_sig + * @param exchange_sig signature of the exchange over reconciliation data + * @return database transaction status + */ +enum GNUNET_DB_QueryStatus +TALER_MERCHANTDB_update_to_transfer_finalized (struct TALER_MERCHANTDB_PostgresContext *pg, + const char *exchange_url, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct GNUNET_HashCode *h_details, + const struct TALER_Amount *total_amount, + const struct TALER_Amount *wire_fee, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_ExchangeSignatureP *exchange_sig); + + +#endif diff --git a/src/include/merchant-database/upsert_donau_keys.h b/src/include/merchant-database/upsert_donau_keys.h @@ -1,46 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/merchant-database/upsert_donau_keys.h - * @brief implementation of the upsert_donau_keys function for Postgres - * @author Bohdan Potuzhnyi - * @author Vlada Svirsh - */ -#ifndef MERCHANT_DATABASE_UPSERT_DONAU_KEYS_H -#define MERCHANT_DATABASE_UPSERT_DONAU_KEYS_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "merchantdb_lib.h" -#include "donau/donau_service.h" - - -struct TALER_MERCHANTDB_PostgresContext; -/** - * Function to insert or update Donau keys in the merchant_donau_keys table. - * - * @param pg database context - * @param keys the DONAU_Keys object - * @param first_retry time when we make retry to update keys - * @return GNUNET_DB_QueryStatus transaction status - */ -enum GNUNET_DB_QueryStatus -TALER_MERCHANTDB_upsert_donau_keys (struct TALER_MERCHANTDB_PostgresContext *pg, - const struct DONAU_Keys *keys, - struct GNUNET_TIME_Absolute first_retry); - - -#endif