exchange

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

commit a666b706247f7e2b152a396999f0c9e787190b30
parent c39040ad2c4939b21d6ad57240a8a47dbc8f68e3
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu,  5 Sep 2024 13:30:04 +0200

exchange-side implementation of #9156

Diffstat:
Msrc/exchange/taler-exchange-httpd_aml-decision.c | 25+++++++++++++++++++++++++
Msrc/exchangedb/exchange_do_insert_aml_decision.sql | 29+++++++++++++++++++++--------
Msrc/exchangedb/pg_insert_aml_decision.c | 6+++++-
Msrc/exchangedb/pg_insert_aml_decision.h | 3+++
Msrc/include/taler_exchange_service.h | 3+++
Msrc/include/taler_exchangedb_plugin.h | 3+++
Msrc/kyclogic/plugin_kyclogic_kycaid.c | 8++++++++
Msrc/kyclogic/plugin_kyclogic_oauth2.c | 8++++++++
Msrc/kyclogic/plugin_kyclogic_persona.c | 9+++++++++
Msrc/kyclogic/plugin_kyclogic_template.c | 8++++++++
Msrc/lib/exchange_api_add_aml_decision.c | 6+++++-
Msrc/testing/testing_api_cmd_take_aml_decision.c | 1+
12 files changed, 99 insertions(+), 10 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c b/src/exchange/taler-exchange-httpd_aml-decision.c @@ -45,6 +45,7 @@ TEH_handler_post_aml_decision ( struct GNUNET_TIME_Timestamp decision_time; const json_t *new_rules; const json_t *properties = NULL; + const char *payto_uri = NULL; struct TALER_PaytoHashP h_payto; struct TALER_AmlOfficerSignatureP officer_sig; struct GNUNET_JSON_Specification spec[] = { @@ -55,6 +56,10 @@ TEH_handler_post_aml_decision ( NULL), GNUNET_JSON_spec_string ("justification", &justification), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("payto_uri", + &payto_uri), + NULL), GNUNET_JSON_spec_fixed_auto ("h_payto", &h_payto), GNUNET_JSON_spec_object_const ("new_rules", @@ -88,6 +93,25 @@ TEH_handler_post_aml_decision ( return MHD_YES; /* failure */ } } + if (NULL != payto_uri) + { + struct TALER_PaytoHashP h_payto2; + + TALER_payto_hash (payto_uri, + &h_payto2); + if (0 != + GNUNET_memcmp (&h_payto, + &h_payto2)) + { + GNUNET_break (0); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "payto_uri"); + } + } + TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; if (GNUNET_OK != TALER_officer_aml_decision_verify ( @@ -152,6 +176,7 @@ TEH_handler_post_aml_decision ( /* We keep 'new_measures' around mostly so that the auditor can later verify officer_sig */ qs = TEH_plugin->insert_aml_decision (TEH_plugin->cls, + payto_uri, &h_payto, decision_time, expiration_time, diff --git a/src/exchangedb/exchange_do_insert_aml_decision.sql b/src/exchangedb/exchange_do_insert_aml_decision.sql @@ -16,14 +16,15 @@ DROP FUNCTION IF EXISTS exchange_do_insert_aml_decision; CREATE FUNCTION exchange_do_insert_aml_decision( + IN in_payto_uri TEXT, -- can be NULL! IN in_h_payto BYTEA, IN in_decision_time INT8, IN in_expiration_time INT8, - IN in_properties TEXT, + IN in_properties TEXT, -- can be NULL IN in_new_rules TEXT, IN in_to_investigate BOOLEAN, - IN in_new_measure_name TEXT, - IN in_jmeasures TEXT, + IN in_new_measure_name TEXT, -- can be NULL + IN in_jmeasures TEXT, -- can be NULL IN in_justification TEXT, IN in_decider_pub BYTEA, IN in_decider_sig BYTEA, @@ -78,17 +79,29 @@ ELSE out_last_date = 0; END IF; --- FIXME-9156: need in_payto_uri *in* case --- in_h_payto is not already in wire_targets! SELECT access_token INTO my_access_token FROM wire_targets WHERE wire_target_h_payto=in_h_payto; --- Very strange, should never happen that we --- take an AML decision on an unknown account! IF NOT FOUND THEN + IF in_payto_uri IS NULL + THEN + -- AML decision on an unknown account without payto_uri => fail. + out_account_unknown=TRUE; + RETURN; + END IF; + + INSERT INTO wire_targets + (wire_target_h_payto + ,payto_uri) + VALUES + (in_h_payto + ,in_payto_uri) + RETURNING access_token + INTO my_access_token; + out_account_unknown=TRUE; RETURN; END IF; @@ -189,5 +202,5 @@ EXECUTE FORMAT ( END $$; -COMMENT ON FUNCTION exchange_do_insert_aml_decision(BYTEA, INT8, INT8, TEXT, TEXT, BOOLEAN, TEXT, TEXT, TEXT, BYTEA, BYTEA, TEXT) +COMMENT ON FUNCTION exchange_do_insert_aml_decision(TEXT, BYTEA, INT8, INT8, TEXT, TEXT, BOOLEAN, TEXT, TEXT, TEXT, BYTEA, BYTEA, TEXT) IS 'Checks whether the AML officer is eligible to make AML decisions and if so inserts the decision into the table'; diff --git a/src/exchangedb/pg_insert_aml_decision.c b/src/exchangedb/pg_insert_aml_decision.c @@ -30,6 +30,7 @@ enum GNUNET_DB_QueryStatus TEH_PG_insert_aml_decision ( void *cls, + const char *payto_uri, const struct TALER_PaytoHashP *h_payto, struct GNUNET_TIME_Timestamp decision_time, struct GNUNET_TIME_Timestamp expiration_time, @@ -54,6 +55,9 @@ TEH_PG_insert_aml_decision ( char *notify_s = GNUNET_PQ_get_event_notify_channel (&rep.header); struct GNUNET_PQ_QueryParam params[] = { + NULL == payto_uri + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (payto_uri), GNUNET_PQ_query_param_auto_from_type (h_payto), GNUNET_PQ_query_param_timestamp (&decision_time), GNUNET_PQ_query_param_timestamp (&expiration_time), @@ -92,7 +96,7 @@ TEH_PG_insert_aml_decision ( ",out_account_unknown" ",out_last_date" " FROM exchange_do_insert_aml_decision" - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);"); + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "do_insert_aml_decision", params, diff --git a/src/exchangedb/pg_insert_aml_decision.h b/src/exchangedb/pg_insert_aml_decision.h @@ -31,6 +31,8 @@ * status. * * @param cls closure + * @param payto_uri full URI of the account, optional, + * can be NULL if the backend already knows the account * @param h_payto account for which the attribute data is stored * @param decision_time when was the decision made * @param expiration_time when does the decision expire @@ -52,6 +54,7 @@ enum GNUNET_DB_QueryStatus TEH_PG_insert_aml_decision ( void *cls, + const char *payto_uri, const struct TALER_PaytoHashP *h_payto, struct GNUNET_TIME_Timestamp decision_time, struct GNUNET_TIME_Timestamp expiration_time, diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h @@ -6393,6 +6393,8 @@ struct TALER_EXCHANGE_AccountRule * @param url HTTP base URL for the exchange * @param h_payto payto URI hash of the account the * decision is about + * @param payto_uri payto URI of the account, can + * be NULL if the exchange already knows the account * @param decision_time when was the decision made * @param successor_measure measure to activate after @a expiration_time if no rule applied * @param new_measures space-separated list of measures @@ -6417,6 +6419,7 @@ TALER_EXCHANGE_post_aml_decision ( struct GNUNET_CURL_Context *ctx, const char *url, const struct TALER_PaytoHashP *h_payto, + const char *payto_uri, struct GNUNET_TIME_Timestamp decision_time, const char *successor_measure, const char *new_measures, diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h @@ -7653,6 +7653,8 @@ struct TALER_EXCHANGEDB_Plugin * status. * * @param cls closure + * @param payto_uri full URI of the account, optional, + * can be NULL if the backend already knows the account * @param h_payto account for which the attribute data is stored * @param decision_time when was the decision made * @param expiration_time when does the decision expire @@ -7674,6 +7676,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*insert_aml_decision)( void *cls, + const char *payto_uri, const struct TALER_PaytoHashP *h_payto, struct GNUNET_TIME_Timestamp decision_time, struct GNUNET_TIME_Timestamp expiration_time, diff --git a/src/kyclogic/plugin_kyclogic_kycaid.c b/src/kyclogic/plugin_kyclogic_kycaid.c @@ -1393,6 +1393,10 @@ kycaid_webhook (void *cls, * @return NULL on error, otherwise a `struct TALER_KYCLOGIC_Plugin` */ void * +libtaler_plugin_kyclogic_kycaid_init (void *cls); + +/* declaration to avoid compiler warning */ +void * libtaler_plugin_kyclogic_kycaid_init (void *cls) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; @@ -1455,6 +1459,10 @@ libtaler_plugin_kyclogic_kycaid_init (void *cls) * @return NULL (always) */ void * +libtaler_plugin_kyclogic_kycaid_done (void *cls); + +/* declaration to avoid compiler warning */ +void * libtaler_plugin_kyclogic_kycaid_done (void *cls) { struct TALER_KYCLOGIC_Plugin *plugin = cls; diff --git a/src/kyclogic/plugin_kyclogic_oauth2.c b/src/kyclogic/plugin_kyclogic_oauth2.c @@ -1696,6 +1696,10 @@ oauth2_webhook_cancel (struct TALER_KYCLOGIC_WebhookHandle *wh) * @return NULL on error, otherwise a `struct TALER_KYCLOGIC_Plugin` */ void * +libtaler_plugin_kyclogic_oauth2_init (void *cls); + +/* declaration to avoid compiler warning */ +void * libtaler_plugin_kyclogic_oauth2_init (void *cls) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; @@ -1757,6 +1761,10 @@ libtaler_plugin_kyclogic_oauth2_init (void *cls) * @return NULL (always) */ void * +libtaler_plugin_kyclogic_oauth2_done (void *cls); + +/* declaration to avoid compiler warning */ +void * libtaler_plugin_kyclogic_oauth2_done (void *cls) { struct TALER_KYCLOGIC_Plugin *plugin = cls; diff --git a/src/kyclogic/plugin_kyclogic_persona.c b/src/kyclogic/plugin_kyclogic_persona.c @@ -2169,6 +2169,10 @@ persona_webhook (void *cls, * @return NULL on error, otherwise a `struct TALER_KYCLOGIC_Plugin` */ void * +libtaler_plugin_kyclogic_persona_init (void *cls); + +/* declaration to avoid compiler warning */ +void * libtaler_plugin_kyclogic_persona_init (void *cls) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; @@ -2240,6 +2244,11 @@ libtaler_plugin_kyclogic_persona_init (void *cls) * @return NULL (always) */ void * +libtaler_plugin_kyclogic_persona_done (void *cls); + +/* declaration to avoid compiler warning */ + +void * libtaler_plugin_kyclogic_persona_done (void *cls) { struct TALER_KYCLOGIC_Plugin *plugin = cls; diff --git a/src/kyclogic/plugin_kyclogic_template.c b/src/kyclogic/plugin_kyclogic_template.c @@ -384,6 +384,10 @@ template_webhook (void *cls, * @return NULL on error, otherwise a `struct TALER_KYCLOGIC_Plugin` */ void * +libtaler_plugin_kyclogic_template_init (void *cls); + +/* declaration to avoid compiler warning */ +void * libtaler_plugin_kyclogic_template_init (void *cls) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; @@ -446,6 +450,10 @@ libtaler_plugin_kyclogic_template_init (void *cls) * @return NULL (always) */ void * +libtaler_plugin_kyclogic_template_done (void *cls); + +/* declaration to avoid compiler warning */ +void * libtaler_plugin_kyclogic_template_done (void *cls) { struct TALER_KYCLOGIC_Plugin *plugin = cls; diff --git a/src/lib/exchange_api_add_aml_decision.c b/src/lib/exchange_api_add_aml_decision.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2023 Taler Systems SA + Copyright (C) 2023, 2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -128,6 +128,7 @@ TALER_EXCHANGE_post_aml_decision ( struct GNUNET_CURL_Context *ctx, const char *url, const struct TALER_PaytoHashP *h_payto, + const char *payto_uri, struct GNUNET_TIME_Timestamp decision_time, const char *successor_measure, const char *new_measures, @@ -269,6 +270,9 @@ TALER_EXCHANGE_post_aml_decision ( justification), GNUNET_JSON_pack_data_auto ("h_payto", h_payto), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("payto_uri", + payto_uri)), GNUNET_JSON_pack_object_steal ("new_rules", new_rules), GNUNET_JSON_pack_object_incref ("properties", diff --git a/src/testing/testing_api_cmd_take_aml_decision.c b/src/testing/testing_api_cmd_take_aml_decision.c @@ -354,6 +354,7 @@ take_aml_decision_run (void *cls, TALER_TESTING_interpreter_get_context (is), exchange_url, h_payto, + NULL, /* payto_uri */ now, ds->successor_measure, new_measures,