diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-08-09 20:26:26 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-08-09 20:26:26 +0200 |
commit | f5334f0e37784a1ba8a230e3b2186d645347e5b6 (patch) | |
tree | 690cd9c8e5e65f6d085af6286b24f8b391dc0216 | |
parent | 79ab45c895a8b15a19fcaf2561a5fdbf9e51d24a (diff) |
implement #9049, needs test
-rw-r--r-- | src/bank-lib/Makefile.am | 2 | ||||
-rw-r--r-- | src/bank-lib/fakebank_twg.c | 18 | ||||
-rw-r--r-- | src/bank-lib/fakebank_twg_get_transfers.c | 232 | ||||
-rw-r--r-- | src/bank-lib/fakebank_twg_get_transfers.h | 68 | ||||
-rw-r--r-- | src/bank-lib/fakebank_twg_get_transfers_id.c | 129 |
5 files changed, 449 insertions, 0 deletions
diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am index 9631e0fdb..b170d2d5f 100644 --- a/src/bank-lib/Makefile.am +++ b/src/bank-lib/Makefile.am @@ -85,6 +85,8 @@ libtalerfakebank_la_SOURCES = \ fakebank_twg_admin_add_incoming.c fakebank_twg_admin_add_incoming.h \ fakebank_twg_admin_add_kycauth.c fakebank_twg_admin_add_kycauth.h \ fakebank_twg_get_root.c fakebank_twg_get_root.h \ + fakebank_twg_get_transfers.c fakebank_twg_get_transfers.h \ + fakebank_twg_get_transfers_id.c \ fakebank_twg_history.c fakebank_twg_history.h \ fakebank_twg_transfer.c fakebank_twg_transfer.h libtalerfakebank_la_LIBADD = \ diff --git a/src/bank-lib/fakebank_twg.c b/src/bank-lib/fakebank_twg.c index 976d9c2f4..a32028734 100644 --- a/src/bank-lib/fakebank_twg.c +++ b/src/bank-lib/fakebank_twg.c @@ -31,6 +31,7 @@ #include "fakebank_twg_admin_add_incoming.h" #include "fakebank_twg_admin_add_kycauth.h" #include "fakebank_twg_get_root.h" +#include "fakebank_twg_get_transfers.h" #include "fakebank_twg_history.h" #include "fakebank_twg_transfer.h" @@ -89,6 +90,23 @@ TALER_FAKEBANK_twg_main_ ( "/")) return TALER_FAKEBANK_twg_get_root_ (h, connection); + if ( (0 == strcmp (url, + "/transfers")) && + (NULL != account) ) + return TALER_FAKEBANK_twg_get_transfers_ (h, + connection, + account, + con_cls); + if ( (0 == strncmp (url, + "/transfers/", + strlen ("/transfers/"))) && + (NULL != account) ) + return TALER_FAKEBANK_twg_get_transfers_id_ ( + h, + connection, + account, + &url[strlen ("/transfers/")], + con_cls); } else if (0 == strcasecmp (method, MHD_HTTP_METHOD_POST)) diff --git a/src/bank-lib/fakebank_twg_get_transfers.c b/src/bank-lib/fakebank_twg_get_transfers.c new file mode 100644 index 000000000..18b66dd54 --- /dev/null +++ b/src/bank-lib/fakebank_twg_get_transfers.c @@ -0,0 +1,232 @@ +/* + This file is part of TALER + (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 bank-lib/fakebank_twg_get_transfers.c + * @brief routines to return account histories for the Taler Wire Gateway API + * @author Christian Grothoff <christian@grothoff.org> + */ +#include "platform.h" +#include <pthread.h> +#include "taler_fakebank_lib.h" +#include "taler_bank_service.h" +#include "taler_mhd_lib.h" +#include <gnunet/gnunet_mhd_compat.h> +#include "fakebank.h" +#include "fakebank_common_lookup.h" +#include "fakebank_common_lp.h" +#include "fakebank_common_parser.h" +#include "fakebank_twg_get_transfers.h" + + +MHD_RESULT +TALER_FAKEBANK_twg_get_transfers_ ( + struct TALER_FAKEBANK_Handle *h, + struct MHD_Connection *connection, + const char *account, + void **con_cls) +{ + struct Transaction *pos; + const char *acc_payto_uri; + json_t *history; + struct Account *acc; + int64_t limit = -20; + uint64_t offset; + bool have_start; + const char *status; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handling /transfers connection %p\n", + connection); + + TALER_MHD_parse_request_snumber (connection, + "limit", + &limit); + if (limit > 0) + offset = 0; + else + offset = UINT64_MAX; + TALER_MHD_parse_request_number (connection, + "offset", + &offset); + have_start = ((0 != offset) && (UINT64_MAX != offset)); + status = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + "status"); + if ( (NULL != status) && + (0 != strcasecmp (status, + "success")) ) + { + /* we only have successful transactions */ + return TALER_MHD_reply_static (connection, + MHD_HTTP_NO_CONTENT, + NULL, + NULL, + 0); + } + + GNUNET_assert (0 == + pthread_mutex_lock (&h->big_lock)); + if (UINT64_MAX == offset) + offset = h->serial_counter; + acc = TALER_FAKEBANK_lookup_account_ (h, + account, + NULL); + if (NULL == acc) + { + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_BANK_UNKNOWN_ACCOUNT, + account); + } + history = json_array (); + if (NULL == history) + { + GNUNET_break (0); + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return MHD_NO; + } + + if (! have_start) + { + pos = (0 > limit) + ? acc->out_tail + : acc->out_head; + } + else + { + struct Transaction *t = h->transactions[offset % h->ram_limit]; + bool overflow; + uint64_t dir; + bool skip = true; + + dir = (0 > limit) ? (h->ram_limit - 1) : 1; + overflow = (t->row_id != offset); + /* If account does not match, linear scan for + first matching account. */ + while ( (! overflow) && + (NULL != t) && + (t->debit_account != acc) ) + { + skip = false; + t = h->transactions[(t->row_id + dir) % h->ram_limit]; + if ( (NULL != t) && + (t->row_id == offset) ) + overflow = true; /* full circle, give up! */ + } + if (t->debit_account != acc) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Invalid start specified, transaction %llu not with account %s!\n", + (unsigned long long) offset, + account); + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return MHD_NO; + } + if (skip) + { + /* range is exclusive, skip the matching entry */ + if (0 > limit) + pos = t->prev_out; + else + pos = t->next_out; + } + else + { + pos = t; + } + } + if (NULL != pos) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Returning %lld debit transactions starting (inclusive) from %llu\n", + (long long) limit, + (unsigned long long) pos->row_id); + while ( (0 != limit) && + (NULL != pos) ) + { + json_t *trans; + char *credit_payto; + + if (T_DEBIT != pos->type) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Unexpected CREDIT transaction #%llu for account `%s'\n", + (unsigned long long) pos->row_id, + account); + if (0 > limit) + pos = pos->prev_in; + if (0 < limit) + pos = pos->next_in; + continue; + } + GNUNET_asprintf (&credit_payto, + "payto://x-taler-bank/localhost/%s?receiver-name=%s", + pos->credit_account->account_name, + pos->credit_account->receiver_name); + + trans = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_uint64 ("row_id", + pos->row_id), + GNUNET_JSON_pack_timestamp ("timestamp", + pos->date), + TALER_JSON_pack_amount ("amount", + &pos->amount), + GNUNET_JSON_pack_string ("credit_account", + credit_payto), + GNUNET_JSON_pack_string ("status", + "success")); + GNUNET_assert (NULL != trans); + GNUNET_free (credit_payto); + GNUNET_assert (0 == + json_array_append_new (history, + trans)); + if (limit > 0) + limit--; + else + limit++; + if (0 > limit) + pos = pos->prev_out; + if (0 < limit) + pos = pos->next_out; + } + acc_payto_uri = acc->payto_uri; + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + if (0 == json_array_size (history)) + { + json_decref (history); + return TALER_MHD_reply_static (connection, + MHD_HTTP_NO_CONTENT, + NULL, + NULL, + 0); + } + return TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_string ( + "debit_account", + acc_payto_uri), + GNUNET_JSON_pack_array_steal ( + "transfers", + history)); +} diff --git a/src/bank-lib/fakebank_twg_get_transfers.h b/src/bank-lib/fakebank_twg_get_transfers.h new file mode 100644 index 000000000..7a306f631 --- /dev/null +++ b/src/bank-lib/fakebank_twg_get_transfers.h @@ -0,0 +1,68 @@ +/* + This file is part of TALER + (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 bank-lib/fakebank_twg_get_transfers.h + * @brief routines to return outgoing transaction status + * @author Christian Grothoff <christian@grothoff.org> + */ +#ifndef FAKEBANK_TWG_GET_TRANSFERS_H +#define FAKEBANK_TWG_GET_TRANSFERS_H + +#include "taler_fakebank_lib.h" +#include "taler_bank_service.h" +#include "taler_mhd_lib.h" +#include <gnunet/gnunet_mhd_compat.h> +#include "fakebank.h" + + +/** + * Handle incoming HTTP request for /transfers + * + * @param h the fakebank handle + * @param connection the connection + * @param account which account the request is about + * @param con_cls closure for request + */ +MHD_RESULT +TALER_FAKEBANK_twg_get_transfers_ ( + struct TALER_FAKEBANK_Handle *h, + struct MHD_Connection *connection, + const char *account, + void **con_cls); + + +/** + * Handle incoming HTTP request for /transfers/$ID + * + * @param h the fakebank handle + * @param connection the connection + * @param account which account the request is about + * @param id the transfer ID the request is about + * @param con_cls closure for request + */ +MHD_RESULT +TALER_FAKEBANK_twg_get_transfers_id_ ( + struct TALER_FAKEBANK_Handle *h, + struct MHD_Connection *connection, + const char *account, + const char *id, + void **con_cls); + + +#endif diff --git a/src/bank-lib/fakebank_twg_get_transfers_id.c b/src/bank-lib/fakebank_twg_get_transfers_id.c new file mode 100644 index 000000000..5d2667a83 --- /dev/null +++ b/src/bank-lib/fakebank_twg_get_transfers_id.c @@ -0,0 +1,129 @@ +/* + This file is part of TALER + (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 bank-lib/fakebank_twg_get_transfers_id.c + * @brief routines to return outgoing transfer details + * @author Christian Grothoff <christian@grothoff.org> + */ +#include "platform.h" +#include <pthread.h> +#include "taler_fakebank_lib.h" +#include "taler_bank_service.h" +#include "taler_mhd_lib.h" +#include <gnunet/gnunet_mhd_compat.h> +#include "fakebank.h" +#include "fakebank_common_lookup.h" +#include "fakebank_common_lp.h" +#include "fakebank_common_parser.h" +#include "fakebank_twg_get_transfers.h" + + +MHD_RESULT +TALER_FAKEBANK_twg_get_transfers_id_ ( + struct TALER_FAKEBANK_Handle *h, + struct MHD_Connection *connection, + const char *account, + const char *id, + void **con_cls) +{ + struct Account *acc; + unsigned long long row_id; + json_t *trans; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handling /transfers/%s connection %p\n", + id, + connection); + { + char dummy; + + if (1 != + sscanf (id, + "%llu%c", + &row_id, + &dummy)) + { + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + id); + } + } + GNUNET_assert (0 == + pthread_mutex_lock (&h->big_lock)); + acc = TALER_FAKEBANK_lookup_account_ (h, + account, + NULL); + if (NULL == acc) + { + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_BANK_UNKNOWN_ACCOUNT, + account); + } + { + struct Transaction *t = h->transactions[row_id % h->ram_limit]; + char *credit_payto; + + if (t->debit_account != acc) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Invalid ID specified, transaction %llu not with account %s!\n", + (unsigned long long) row_id, + account); + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return MHD_NO; + } + GNUNET_asprintf (&credit_payto, + "payto://x-taler-bank/localhost/%s?receiver-name=%s", + t->credit_account->account_name, + t->credit_account->receiver_name); + trans = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_data_auto ( + "wtid", + &t->subject.debit.wtid), + GNUNET_JSON_pack_string ( + "exchange_base_url", + t->subject.debit.exchange_base_url), + GNUNET_JSON_pack_timestamp ( + "timestamp", + t->date), + TALER_JSON_pack_amount ( + "amount", + &t->amount), + GNUNET_JSON_pack_string ( + "credit_account", + credit_payto), + GNUNET_JSON_pack_string ( + "status", + "success")); + GNUNET_assert (NULL != trans); + GNUNET_free (credit_payto); + } + GNUNET_assert (0 == + pthread_mutex_unlock (&h->big_lock)); + return TALER_MHD_reply_json ( + connection, + trans, + MHD_HTTP_OK); +} |