aboutsummaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_aml-decisions-get.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-02-02 11:40:44 +0100
committerChristian Grothoff <christian@grothoff.org>2023-02-02 11:40:44 +0100
commit915542e69c5a481b8885661171880446d4ef009d (patch)
treecf05a85359ee9074ec81ba5791c399ee3749853d /src/exchange/taler-exchange-httpd_aml-decisions-get.c
parentf8ff9c996f2fbdde9110b473bee39ea173d2b40f (diff)
first draft of implementation of GET AML decisions endpoint
Diffstat (limited to 'src/exchange/taler-exchange-httpd_aml-decisions-get.c')
-rw-r--r--src/exchange/taler-exchange-httpd_aml-decisions-get.c228
1 files changed, 228 insertions, 0 deletions
diff --git a/src/exchange/taler-exchange-httpd_aml-decisions-get.c b/src/exchange/taler-exchange-httpd_aml-decisions-get.c
new file mode 100644
index 00000000..091e7a67
--- /dev/null
+++ b/src/exchange/taler-exchange-httpd_aml-decisions-get.c
@@ -0,0 +1,228 @@
+/*
+ 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 Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-exchange-httpd_aml-decisions-get.c
+ * @brief Return summary information about AML decisions
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <jansson.h>
+#include <microhttpd.h>
+#include <pthread.h>
+#include "taler_json_lib.h"
+#include "taler_mhd_lib.h"
+#include "taler_signatures.h"
+#include "taler-exchange-httpd.h"
+#include "taler_exchangedb_plugin.h"
+#include "taler-exchange-httpd_aml-decision.h"
+#include "taler-exchange-httpd_metrics.h"
+
+
+/**
+ * Maximum number of records we return per request.
+ */
+#define MAX_RECORDS 1024
+
+/**
+ * Return AML status.
+ *
+ * @param cls closure
+ * @param row_id current row in AML status table
+ * @param h_payto account for which the attribute data is stored
+ * @param threshold currently monthly threshold that would trigger an AML check
+ * @param status what is the current AML decision
+ */
+static void
+record_cb (
+ void *cls,
+ uint64_t row_id,
+ const struct TALER_PaytoHashP *h_payto,
+ const struct TALER_Amount *threshold,
+ enum TALER_AmlDecisionState status)
+{
+ json_t *records = cls;
+
+ GNUNET_assert (
+ 0 ==
+ json_array_append (
+ records,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_data_auto ("h_payto",
+ h_payto),
+ TALER_JSON_pack_amount ("threshold",
+ threshold),
+ GNUNET_JSON_pack_int64 ("current_state",
+ status),
+ GNUNET_JSON_pack_int64 ("rowid",
+ row_id)
+ )));
+}
+
+
+MHD_RESULT
+TEH_handler_aml_decisions_get (
+ struct TEH_RequestContext *rc,
+ const struct TALER_AmlOfficerPublicKeyP *officer_pub,
+ const char *const args[])
+{
+ enum GNUNET_GenericReturnValue res;
+ const char *sig_hdr;
+ struct TALER_AmlOfficerSignatureP officer_sig;
+ bool frozen = false;
+ bool pending = false;
+ bool normal = false;
+ int delta = -20;
+ unsigned long long start = INT64_MAX;
+
+ if (NULL != args[0])
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
+ args[0]);
+ }
+ sig_hdr = MHD_lookup_connection_value (rc->connection,
+ MHD_HEADER_KIND,
+ TALER_AML_OFFICER_SIGNATURE_HEADER);
+ if ( (NULL == sig_hdr) ||
+ (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (sig_hdr,
+ strlen (sig_hdr),
+ &officer_sig,
+ sizeof (officer_sig))) ||
+ (GNUNET_OK !=
+ TALER_officer_aml_query_verify (officer_pub,
+ &officer_sig)) )
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID,
+ sig_hdr);
+ }
+ TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
+
+ {
+ const char *p;
+
+ p = MHD_lookup_connection_value (rc->connection,
+ MHD_GET_ARGUMENT_KIND,
+ "frozen");
+ if (NULL != p)
+ frozen = (0 == strcasecmp (p,
+ "yes"));
+ p = MHD_lookup_connection_value (rc->connection,
+ MHD_GET_ARGUMENT_KIND,
+ "pending");
+ if (NULL != p)
+ pending = (0 == strcasecmp (p,
+ "yes"));
+ p = MHD_lookup_connection_value (rc->connection,
+ MHD_GET_ARGUMENT_KIND,
+ "normal");
+ if (NULL != p)
+ normal = (0 == strcasecmp (p,
+ "yes"));
+ p = MHD_lookup_connection_value (rc->connection,
+ MHD_GET_ARGUMENT_KIND,
+ "start");
+ if (NULL != p)
+ {
+ char dummy;
+
+ if (1 != sscanf (p,
+ "%llu%c",
+ &start,
+ &dummy))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "start");
+ }
+ }
+ p = MHD_lookup_connection_value (rc->connection,
+ MHD_GET_ARGUMENT_KIND,
+ "delta");
+ if (NULL != p)
+ {
+ char dummy;
+
+ if (1 != sscanf (p,
+ "%d%c",
+ &delta,
+ &dummy))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "delta");
+ }
+ }
+ }
+
+ {
+ json_t *records;
+ enum GNUNET_DB_QueryStatus qs;
+ enum TALER_AmlDecisionState decision = 42; // FIXME!
+
+ records = json_array ();
+ GNUNET_assert (NULL != records);
+ if (INT_MIN == delta)
+ delta = INT_MIN + 1;
+ qs = TEH_plugin->select_aml_process (TEH_plugin->cls,
+ decision,
+ start,
+ delta > 0,
+ GNUNET_MIN (MAX_RECORDS,
+ delta > 0 ? delta :
+ -delta),
+ &record_cb,
+ records);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ json_decref (records);
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return TALER_MHD_reply_static (
+ rc->connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
+ return TALER_MHD_REPLY_JSON_PACK (
+ rc->connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_array_steal ("records",
+ records));
+ }
+}
+
+
+/* end of taler-exchange-httpd_deposits_get.c */