exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/exchange/taler-exchange-httpd_aml-decision.c | 24++++++++++++++++++++++++
Msrc/exchange/taler-exchange-httpd_config.c | 2+-
Msrc/exchangedb/exchange_do_insert_aml_decision.sql | 15+++++++++++++++
Msrc/exchangedb/exchange_do_insert_kyc_measure_result.sql | 8++++----
Msrc/exchangedb/pg_insert_aml_decision.c | 8+++++++-
Msrc/exchangedb/pg_insert_aml_decision.h | 4++++
Msrc/include/taler_exchange_service.h | 4++++
Msrc/include/taler_exchangedb_plugin.h | 4++++
Msrc/lib/Makefile.am | 2+-
Msrc/lib/exchange_api_add_aml_decision.c | 15+++++++++++++++
Msrc/testing/testing_api_cmd_take_aml_decision.c | 1+
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); }