taler-exchange-httpd_aml-decisions-get.c (6622B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024, 2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file taler-exchange-httpd_aml-decisions-get.c 18 * @brief Return summary information about AML decisions 19 * @author Christian Grothoff 20 */ 21 #include "taler/platform.h" 22 #include <gnunet/gnunet_util_lib.h> 23 #include <jansson.h> 24 #include <microhttpd.h> 25 #include <pthread.h> 26 #include "taler/taler_json_lib.h" 27 #include "taler/taler_mhd_lib.h" 28 #include "taler/taler_signatures.h" 29 #include "taler-exchange-httpd.h" 30 #include "taler/taler_exchangedb_plugin.h" 31 #include "taler-exchange-httpd_aml-decision.h" 32 #include "taler-exchange-httpd_metrics.h" 33 34 /** 35 * Maximum number of records we return in one request. 36 */ 37 #define MAX_RECORDS 1024 38 39 /** 40 * Return AML status. 41 * 42 * @param cls closure 43 * @param row_id current row in AML status table 44 * @param justification human-readable reason for the decision 45 * @param h_payto account for which the attribute data is stored 46 * @param decision_time when was the decision taken 47 * @param expiration_time when will the rules expire 48 * @param jproperties properties set for the account, 49 * NULL if no properties were set 50 * @param to_investigate true if AML staff should look at the account 51 * @param is_active true if this is the currently active decision about the account 52 * @param is_wallet true if the @a h_payto is for a wallet 53 * @param payto the payto URI of the account affected by the decision 54 * @param account_rules current active rules for the account 55 */ 56 static void 57 record_cb ( 58 void *cls, 59 uint64_t row_id, 60 const char *justification, 61 const struct TALER_NormalizedPaytoHashP *h_payto, 62 struct GNUNET_TIME_Timestamp decision_time, 63 struct GNUNET_TIME_Absolute expiration_time, 64 const json_t *jproperties, 65 bool to_investigate, 66 bool is_active, 67 bool is_wallet, 68 struct TALER_FullPayto payto, 69 const json_t *account_rules) 70 { 71 json_t *records = cls; 72 73 GNUNET_assert ( 74 0 == 75 json_array_append_new ( 76 records, 77 GNUNET_JSON_PACK ( 78 GNUNET_JSON_pack_data_auto ("h_payto", 79 h_payto), 80 TALER_JSON_pack_full_payto ("full_payto", 81 payto), 82 GNUNET_JSON_pack_bool ("is_wallet", 83 is_wallet), 84 GNUNET_JSON_pack_int64 ("rowid", 85 row_id), 86 GNUNET_JSON_pack_allow_null ( 87 GNUNET_JSON_pack_string ("justification", 88 justification)), 89 GNUNET_JSON_pack_timestamp ("decision_time", 90 decision_time), 91 GNUNET_JSON_pack_allow_null ( 92 GNUNET_JSON_pack_object_incref ("properties", 93 (json_t *) jproperties)), 94 GNUNET_JSON_pack_object_incref ("limits", 95 (json_t *) account_rules), 96 GNUNET_JSON_pack_bool ("to_investigate", 97 to_investigate), 98 GNUNET_JSON_pack_bool ("is_active", 99 is_active) 100 ))); 101 } 102 103 104 MHD_RESULT 105 TEH_handler_aml_decisions_get ( 106 struct TEH_RequestContext *rc, 107 const struct TALER_AmlOfficerPublicKeyP *officer_pub, 108 const char *const args[]) 109 { 110 int64_t limit = -20; 111 uint64_t offset; 112 struct TALER_NormalizedPaytoHashP h_payto; 113 bool have_payto = false; 114 enum TALER_EXCHANGE_YesNoAll active_filter; 115 enum TALER_EXCHANGE_YesNoAll investigation_filter; 116 117 if (NULL != args[0]) 118 { 119 GNUNET_break_op (0); 120 return TALER_MHD_reply_with_error ( 121 rc->connection, 122 MHD_HTTP_NOT_FOUND, 123 TALER_EC_GENERIC_ENDPOINT_UNKNOWN, 124 args[0]); 125 } 126 TALER_MHD_parse_request_snumber (rc->connection, 127 "limit", 128 &limit); 129 if (limit > 0) 130 offset = 0; 131 else 132 offset = INT64_MAX; 133 TALER_MHD_parse_request_number (rc->connection, 134 "offset", 135 &offset); 136 if (offset > INT64_MAX) 137 { 138 GNUNET_break_op (0); /* broken client */ 139 offset = INT64_MAX; 140 } 141 TALER_MHD_parse_request_arg_auto (rc->connection, 142 "h_payto", 143 &h_payto, 144 have_payto); 145 TALER_MHD_parse_request_yna (rc->connection, 146 "active", 147 TALER_EXCHANGE_YNA_ALL, 148 &active_filter); 149 TALER_MHD_parse_request_yna (rc->connection, 150 "investigation", 151 TALER_EXCHANGE_YNA_ALL, 152 &investigation_filter); 153 { 154 json_t *records; 155 enum GNUNET_DB_QueryStatus qs; 156 157 records = json_array (); 158 GNUNET_assert (NULL != records); 159 if (limit > MAX_RECORDS) 160 limit = MAX_RECORDS; 161 if (limit < -MAX_RECORDS) 162 limit = -MAX_RECORDS; 163 qs = TEH_plugin->select_aml_decisions ( 164 TEH_plugin->cls, 165 have_payto 166 ? &h_payto 167 : NULL, 168 investigation_filter, 169 active_filter, 170 offset, 171 limit, 172 &record_cb, 173 records); 174 switch (qs) 175 { 176 case GNUNET_DB_STATUS_HARD_ERROR: 177 case GNUNET_DB_STATUS_SOFT_ERROR: 178 json_decref (records); 179 GNUNET_break (0); 180 return TALER_MHD_reply_with_error ( 181 rc->connection, 182 MHD_HTTP_INTERNAL_SERVER_ERROR, 183 TALER_EC_GENERIC_DB_FETCH_FAILED, 184 "select_aml_decisions"); 185 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 186 json_decref (records); 187 return TALER_MHD_reply_static ( 188 rc->connection, 189 MHD_HTTP_NO_CONTENT, 190 NULL, 191 NULL, 192 0); 193 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 194 break; 195 } 196 return TALER_MHD_REPLY_JSON_PACK ( 197 rc->connection, 198 MHD_HTTP_OK, 199 GNUNET_JSON_pack_array_steal ("records", 200 records)); 201 } 202 } 203 204 205 /* end of taler-exchange-httpd_aml-decisions_get.c */