/* 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 */ /** * @file taler-exchange-httpd_aml-decisions-get.c * @brief Return summary information about AML decisions * @author Christian Grothoff */ #include "platform.h" #include #include #include #include #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), GNUNET_JSON_pack_int64 ("current_state", status), TALER_JSON_pack_amount ("threshold", threshold), 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 TALER_AmlDecisionState decision; int delta = -20; unsigned long long start; const char *state_str = args[0]; if (NULL == state_str) { GNUNET_break_op (0); return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_ENDPOINT_UNKNOWN, args[0]); } if (0 == strcmp (state_str, "pending")) decision = TALER_AML_PENDING; else if (0 == strcmp (state_str, "frozen")) decision = TALER_AML_FROZEN; else if (0 == strcmp (state_str, "normal")) decision = TALER_AML_NORMAL; else { GNUNET_break_op (0); return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_ENDPOINT_UNKNOWN, state_str); } if (NULL != args[1]) { GNUNET_break_op (0); return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_ENDPOINT_UNKNOWN, args[1]); } { const char *p; 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"); } } if (delta > 0) start = 0; else start = INT64_MAX; 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"); } } } { json_t *records; enum GNUNET_DB_QueryStatus qs; 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, GNUNET_MIN (MAX_RECORDS, delta > 0 ? delta : -delta), delta > 0, &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_aml-decisions_get.c */