aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2024-08-09 20:26:26 +0200
committerChristian Grothoff <christian@grothoff.org>2024-08-09 20:26:26 +0200
commitf5334f0e37784a1ba8a230e3b2186d645347e5b6 (patch)
tree690cd9c8e5e65f6d085af6286b24f8b391dc0216
parent79ab45c895a8b15a19fcaf2561a5fdbf9e51d24a (diff)
implement #9049, needs test
-rw-r--r--src/bank-lib/Makefile.am2
-rw-r--r--src/bank-lib/fakebank_twg.c18
-rw-r--r--src/bank-lib/fakebank_twg_get_transfers.c232
-rw-r--r--src/bank-lib/fakebank_twg_get_transfers.h68
-rw-r--r--src/bank-lib/fakebank_twg_get_transfers_id.c129
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);
+}