commit 7dc0f94bdbcfcaf979d9444a2bee6f6030f2747e
parent bfcf8e93707a69bf15c9786153dc73cf3a9d9e82
Author: Christian Grothoff <christian@grothoff.org>
Date: Sat, 4 Jan 2025 15:35:34 +0100
implement #9437: support events being added by AML decisions
Diffstat:
11 files changed, 80 insertions(+), 7 deletions(-)
diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c b/src/exchange/taler-exchange-httpd_aml-decision.c
@@ -178,6 +178,7 @@ TEH_handler_post_aml_decision (
bool to_investigate;
struct GNUNET_TIME_Timestamp decision_time;
const json_t *new_rules;
+ const json_t *events = NULL;
const json_t *properties = NULL;
struct TALER_FullPayto payto_uri = {
.full_payto = NULL
@@ -207,6 +208,10 @@ TEH_handler_post_aml_decision (
GNUNET_JSON_spec_object_const ("properties",
&properties),
NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_object_const ("events",
+ &events),
+ NULL),
GNUNET_JSON_spec_bool ("keep_investigating",
&to_investigate),
GNUNET_JSON_spec_fixed_auto ("officer_sig",
@@ -328,11 +333,28 @@ TEH_handler_post_aml_decision (
}
{
+ size_t num_events = json_array_size (events);
+ const char *sevents[GNUNET_NZL (num_events)];
enum GNUNET_DB_QueryStatus qs;
struct GNUNET_TIME_Timestamp last_date;
bool invalid_officer = true;
bool unknown_account = false;
+ for (size_t i = 0; i<num_events; i++)
+ {
+ sevents[i] = json_string_value (json_array_get (events,
+ i));
+ if (NULL == sevents[i])
+ {
+ GNUNET_break_op (0);
+ ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "events");
+ goto done;
+ }
+ }
/* We keep 'new_measures' around mostly so that
the auditor can later verify officer_sig */
qs = TEH_plugin->insert_aml_decision (TEH_plugin->cls,
@@ -348,6 +370,8 @@ TEH_handler_post_aml_decision (
justification,
officer_pub,
&officer_sig,
+ num_events,
+ sevents,
&invalid_officer,
&unknown_account,
&last_date,
diff --git a/src/exchange/taler-exchange-httpd_config.c b/src/exchange/taler-exchange-httpd_config.c
@@ -66,7 +66,7 @@ TEH_handler_config (struct TEH_RequestContext *rc,
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string ("shopping_url",
TEH_shopping_url)),
- /* Deprecate? */
+ /* Deprecated in v24 */
GNUNET_JSON_pack_array_steal (
"supported_kyc_requirements",
json_array ()),
diff --git a/src/exchangedb/exchange_do_insert_aml_decision.sql b/src/exchangedb/exchange_do_insert_aml_decision.sql
@@ -30,6 +30,7 @@ CREATE FUNCTION exchange_do_insert_aml_decision(
IN in_decider_pub BYTEA,
IN in_decider_sig BYTEA,
IN in_notify_s TEXT,
+ IN ina_events TEXT[],
OUT out_invalid_officer BOOLEAN,
OUT out_account_unknown BOOLEAN,
OUT out_last_date INT8,
@@ -39,6 +40,8 @@ AS $$
DECLARE
my_outcome_serial_id INT8;
my_access_token BYTEA;
+ my_i INT4;
+ ini_event TEXT;
BEGIN
out_account_unknown=FALSE;
@@ -192,6 +195,18 @@ INSERT INTO aml_history
,in_decider_sig
);
+-- Trigger events
+FOR i IN 1..COALESCE(array_length(ina_events,1),0)
+LOOP
+ ini_event = ina_events[i];
+ INSERT INTO kyc_events
+ (event_timestamp
+ ,event_type)
+ VALUES
+ (in_decision_time
+ ,ini_event);
+END LOOP;
+
-- wake up taler-exchange-aggregator
INSERT INTO kyc_alerts
(h_payto
diff --git a/src/exchangedb/exchange_do_insert_kyc_measure_result.sql b/src/exchangedb/exchange_do_insert_kyc_measure_result.sql
@@ -29,10 +29,10 @@ CREATE FUNCTION exchange_do_insert_kyc_measure_result(
LANGUAGE plpgsql
AS $$
DECLARE
- my_trigger_outcome_serial INT8;
- my_lmsi INT8;
- my_i INT4;
- ini_event TEXT;
+ my_trigger_outcome_serial INT8;
+ my_lmsi INT8;
+ my_i INT4;
+ ini_event TEXT;
BEGIN
-- Disactivate all previous outcomes.
diff --git a/src/exchangedb/pg_insert_aml_decision.c b/src/exchangedb/pg_insert_aml_decision.c
@@ -42,6 +42,8 @@ TEH_PG_insert_aml_decision (
const char *justification,
const struct TALER_AmlOfficerPublicKeyP *decider_pub,
const struct TALER_AmlOfficerSignatureP *decider_sig,
+ size_t num_events,
+ const char *events[static num_events],
bool *invalid_officer,
bool *unknown_account,
struct GNUNET_TIME_Timestamp *last_date,
@@ -81,6 +83,9 @@ TEH_PG_insert_aml_decision (
GNUNET_PQ_query_param_auto_from_type (decider_pub),
GNUNET_PQ_query_param_auto_from_type (decider_sig),
GNUNET_PQ_query_param_string (notify_s),
+ GNUNET_PQ_query_param_array_ptrs_string (num_events,
+ events,
+ pg->conn),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
@@ -107,11 +112,12 @@ TEH_PG_insert_aml_decision (
",out_last_date"
",out_legitimization_measure_serial_id"
" FROM exchange_do_insert_aml_decision"
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);");
+ "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15);");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"do_insert_aml_decision",
params,
rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
GNUNET_free (notify_s);
GNUNET_PQ_event_do_poll (pg->conn);
return qs;
diff --git a/src/exchangedb/pg_insert_aml_decision.h b/src/exchangedb/pg_insert_aml_decision.h
@@ -45,6 +45,8 @@
* @param justification human-readable text justifying the decision
* @param decider_pub public key of the staff member
* @param decider_sig signature of the staff member
+ * @param num_events length of the @a events array
+ * @param events array of events to trigger
* @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now
* @param[out] unknown_account set to TRUE if @a h_payto does not refer to a known account and @a jmeasures was given
* @param[out] last_date set to the previous decision time;
@@ -68,6 +70,8 @@ TEH_PG_insert_aml_decision (
const char *justification,
const struct TALER_AmlOfficerPublicKeyP *decider_pub,
const struct TALER_AmlOfficerSignatureP *decider_sig,
+ size_t num_events,
+ const char *events[static num_events],
bool *invalid_officer,
bool *unknown_account,
struct GNUNET_TIME_Timestamp *last_date,
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
@@ -6530,6 +6530,8 @@ struct TALER_EXCHANGE_AccountRule
* @param keep_investigating true to keep the investigation open
* @param justification human-readable justification
* @param officer_priv private key of the deciding AML officer
+ * @param num_events length of the @a events array
+ * @param events array of events to trigger
* @param cb function to call with the exchange's result
* @param cb_cls closure for @a cb
* @return the request handle; NULL upon error
@@ -6552,6 +6554,8 @@ TALER_EXCHANGE_post_aml_decision (
bool keep_investigating,
const char *justification,
const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
+ unsigned int num_events,
+ const char **events,
TALER_EXCHANGE_AddAmlDecisionCallback cb,
void *cb_cls);
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
@@ -7732,6 +7732,8 @@ struct TALER_EXCHANGEDB_Plugin
* @param justification human-readable text justifying the decision
* @param decider_pub public key of the staff member
* @param decider_sig signature of the staff member
+ * @param num_events length of the @a events array
+ * @param events array of events to trigger
* @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now
* @param[out] unknown_account set to TRUE if @a h_payto does not refer to a known account and @a jmeasures was given
* @param[out] last_date set to the previous decision time;
@@ -7755,6 +7757,8 @@ struct TALER_EXCHANGEDB_Plugin
const char *justification,
const struct TALER_AmlOfficerPublicKeyP *decider_pub,
const struct TALER_AmlOfficerSignatureP *decider_sig,
+ size_t num_events,
+ const char *events[static num_events],
bool *invalid_officer,
bool *unknown_account,
struct GNUNET_TIME_Timestamp *last_date,
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
@@ -18,7 +18,7 @@ lib_LTLIBRARIES = \
libtalerexchange.la
libtalerexchange_la_LDFLAGS = \
- -version-info 15:0:1 \
+ -version-info 16:0:0 \
-no-undefined
libtalerexchange_la_SOURCES = \
exchange_api_add_aml_decision.c \
diff --git a/src/lib/exchange_api_add_aml_decision.c b/src/lib/exchange_api_add_aml_decision.c
@@ -141,6 +141,8 @@ TALER_EXCHANGE_post_aml_decision (
bool keep_investigating,
const char *justification,
const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
+ unsigned int num_events,
+ const char **events,
TALER_EXCHANGE_AddAmlDecisionCallback cb,
void *cb_cls)
{
@@ -152,7 +154,17 @@ TALER_EXCHANGE_post_aml_decision (
json_t *new_rules;
json_t *jrules;
json_t *jmeasures;
+ json_t *jevents = NULL;
+ if (0 != num_events)
+ {
+ jevents = json_array ();
+ GNUNET_assert (NULL != jevents);
+ for (unsigned int i = 0; i<num_events; i++)
+ GNUNET_assert (0 ==
+ json_array_append_new (jevents,
+ json_string (events[i])));
+ }
jrules = json_array ();
GNUNET_assert (NULL != jrules);
for (unsigned int i = 0; i<num_rules; i++)
@@ -176,6 +188,9 @@ TALER_EXCHANGE_post_aml_decision (
al->timeframe),
GNUNET_JSON_pack_array_steal ("measures",
ameasures),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_array_steal ("events",
+ jevents)),
GNUNET_JSON_pack_bool ("exposed",
al->exposed),
GNUNET_JSON_pack_bool ("is_and_combinator",
diff --git a/src/testing/testing_api_cmd_take_aml_decision.c b/src/testing/testing_api_cmd_take_aml_decision.c
@@ -372,6 +372,7 @@ take_aml_decision_run (void *cls,
ds->keep_investigating,
ds->justification,
officer_priv,
+ 0, NULL, /* no events */
&take_aml_decision_cb,
ds);
}