exchange

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

commit bb908991f54efa10a4d371c6d0a90b5187fef80c
parent 8b24c2a8c392eafb7356a2d5f290b28bcb5875b9
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon, 13 May 2024 21:12:39 +0200

fix testing FTBFS

Diffstat:
Msrc/exchange/taler-exchange-httpd_aml-decisions-get.c | 10+++++++---
Msrc/include/taler_crypto_lib.h | 19+++++++++++++++++++
Msrc/include/taler_exchange_service.h | 7++++++-
Msrc/include/taler_exchangedb_plugin.h | 2++
Msrc/include/taler_testing_lib.h | 118+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/lib/exchange_api_kyc_check.c | 3++-
Msrc/lib/exchange_api_lookup_aml_decisions.c | 2++
Msrc/testing/Makefile.am | 1-
Dsrc/testing/testing_api_cmd_check_aml_decision.c | 270-------------------------------------------------------------------------------
Msrc/testing/testing_api_cmd_check_aml_decisions.c | 102++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/testing/testing_api_cmd_kyc_check_get.c | 20+++++++++-----------
Msrc/testing/testing_api_cmd_take_aml_decision.c | 151+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
12 files changed, 293 insertions(+), 412 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_aml-decisions-get.c b/src/exchange/taler-exchange-httpd_aml-decisions-get.c @@ -37,6 +37,7 @@ * * @param cls closure * @param row_id current row in AML status table + * @param justification human-readable reason for the decision * @param h_payto account for which the attribute data is stored * @param decision_time when was the decision taken * @param expiration_time when will the rules expire @@ -50,6 +51,7 @@ static void record_cb ( void *cls, uint64_t row_id, + const char *justification, const struct TALER_PaytoHashP *h_payto, struct GNUNET_TIME_Absolute decision_time, struct GNUNET_TIME_Absolute expiration_time, @@ -67,6 +69,8 @@ record_cb ( GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("h_payto", h_payto), + GNUNET_JSON_pack_string ("justification", + justification), // FIXME: pack other data! GNUNET_JSON_pack_int64 ("rowid", row_id) @@ -147,9 +151,9 @@ TEH_handler_aml_decisions_get ( GNUNET_assert (NULL != records); qs = TEH_plugin->select_aml_decisions ( TEH_plugin->cls, - NULL /* FIXME! */, - 0, /* FIXME */ - 0, /* FIXME */ + NULL /* FIXME: h_payto */, + 0, /* FIXME: investigation_only */ + 0, /* FIXME: active_only */ offset, limit, &record_cb, diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h @@ -246,6 +246,25 @@ struct TALER_MerchantPrivateKeyP /** + * @brief Type of private keys to for KYC authorizations. + * Either a merchant's private key or a reserve private + * key will do. + */ +union TALER_AccountPrivateKeyP +{ + /** + * Private key of merchants. + */ + struct TALER_MerchantPrivateKeyP merchant_priv; + + /** + * Private key of reserves. + */ + struct TALER_ReservePrivateKeyP reserve_priv; +}; + + +/** * @brief Type of signatures made by merchants. */ struct TALER_MerchantSignatureP diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h @@ -4360,7 +4360,7 @@ TALER_EXCHANGE_kyc_check ( struct GNUNET_CURL_Context *ctx, const char *url, uint64_t requirement_row, - const struct GNUNET_CRYPTO_EddsaPrivateKey *pk, + const union TALER_AccountPrivateKeyP *pk, struct GNUNET_TIME_Relative timeout, TALER_EXCHANGE_KycStatusCallback cb, void *cb_cls); @@ -5967,6 +5967,11 @@ struct TALER_EXCHANGE_AmlDecision struct TALER_EXCHANGE_LegitimizationRuleSet limits; /** + * Justification given for the decision. + */ + const char *justification; + + /** * Properties set for the account. */ const json_t *jproperties; diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h @@ -3514,6 +3514,7 @@ typedef void * * @param cls closure * @param row_id current row in legitimization outcomes table + * @param justification human-readable reason for the decision * @param h_payto account for which the attribute data is stored * @param decision_time when was the decision taken * @param expiration_time when will the rules expire @@ -3527,6 +3528,7 @@ typedef void (*TALER_EXCHANGEDB_AmlDecisionCallback)( void *cls, uint64_t row_id, + const char *justification, const struct TALER_PaytoHashP *h_payto, struct GNUNET_TIME_Absolute decision_time, struct GNUNET_TIME_Absolute expiration_time, diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h @@ -2415,10 +2415,12 @@ TALER_TESTING_cmd_set_officer ( * officer * @param ref_operation command that previously created an * h_payto which to make an AML decision about - * @param new_threshold new threshold to set + * @param keep_investigating true to keep investigating + * @param expiration_delay how long should the @a new_rules apply + * @param successor_measure measure to trigger on @a expiration_delay + * @param new_rules JSON with new rules for the account + * @param properties properties to set for the account * @param justification justification given for the decision - * @param new_state new AML state for the account - * @param kyc_requirement KYC requirement to impose * @param expected_response expected HTTP return status * @return the command */ @@ -2427,9 +2429,12 @@ TALER_TESTING_cmd_take_aml_decision ( const char *label, const char *ref_officer, const char *ref_operation, - const char *new_threshold, + bool keep_investigating, + struct GNUNET_TIME_Relative expiration_delay, + const char *successor_measure, + const char *new_rules, + const char *properties, const char *justification, - const char *kyc_requirement, unsigned int expected_response); @@ -2652,56 +2657,55 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, op (officer_pub, const struct TALER_AmlOfficerPublicKeyP) \ op (officer_priv, const struct TALER_AmlOfficerPrivateKeyP) \ op (officer_name, const char) \ - << << << < HEAD -op (aml_decision, enum TALER_AmlDecisionState) \ - ====== = - >> >> >> > f54d4f98 (complete exchange_api_lookup_aml_decisions.c logic) - op (aml_justification, const char) \ - op (auditor_priv, const struct TALER_AuditorPrivateKeyP) \ - op (auditor_pub, const struct TALER_AuditorPublicKeyP) \ - op (master_priv, const struct TALER_MasterPrivateKeyP) \ - op (master_pub, const struct TALER_MasterPublicKeyP) \ - op (purse_priv, const struct TALER_PurseContractPrivateKeyP) \ - op (purse_pub, const struct TALER_PurseContractPublicKeyP) \ - op (merge_priv, const struct TALER_PurseMergePrivateKeyP) \ - op (merge_pub, const struct TALER_PurseMergePublicKeyP) \ - op (contract_priv, const struct TALER_ContractDiffiePrivateP) \ - op (reserve_priv, const struct TALER_ReservePrivateKeyP) \ - op (reserve_sig, const struct TALER_ReserveSignatureP) \ - op (h_payto, const struct TALER_PaytoHashP) \ - op (planchet_secret, const struct TALER_PlanchetMasterSecretP) \ - op (refresh_secret, const struct TALER_RefreshMasterSecretP) \ - op (reserve_pub, const struct TALER_ReservePublicKeyP) \ - op (merchant_priv, const struct TALER_MerchantPrivateKeyP) \ - op (merchant_pub, const struct TALER_MerchantPublicKeyP) \ - op (merchant_sig, const struct TALER_MerchantSignatureP) \ - op (wtid, const struct TALER_WireTransferIdentifierRawP) \ - op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \ - op (contract_terms, const json_t) \ - op (wire_details, const json_t) \ - op (exchange_url, const char) \ - op (auditor_url, const char) \ - op (exchange_bank_account_url, const char) \ - op (taler_uri, const char) \ - op (payto_uri, const char) \ - op (kyc_url, const char) \ - op (web_url, const char) \ - op (row, const uint64_t) \ - op (legi_requirement_row, const uint64_t) \ - op (array_length, const unsigned int) \ - op (credit_payto_uri, const char) \ - op (debit_payto_uri, const char) \ - op (order_id, const char) \ - op (amount, const struct TALER_Amount) \ - op (amount_with_fee, const struct TALER_Amount) \ - op (batch_cmds, struct TALER_TESTING_Command) \ - op (uuid, const struct GNUNET_Uuid) \ - op (fresh_coins, const struct TALER_TESTING_FreshCoinData *) \ - op (claim_token, const struct TALER_ClaimTokenP) \ - op (relative_time, const struct GNUNET_TIME_Relative) \ - op (fakebank, struct TALER_FAKEBANK_Handle) \ - op (keys, struct TALER_EXCHANGE_Keys) \ - op (process, struct GNUNET_OS_Process *) + op (aml_justification, const char) \ + op (auditor_priv, const struct TALER_AuditorPrivateKeyP) \ + op (auditor_pub, const struct TALER_AuditorPublicKeyP) \ + op (master_priv, const struct TALER_MasterPrivateKeyP) \ + op (master_pub, const struct TALER_MasterPublicKeyP) \ + op (purse_priv, const struct TALER_PurseContractPrivateKeyP) \ + op (purse_pub, const struct TALER_PurseContractPublicKeyP) \ + op (merge_priv, const struct TALER_PurseMergePrivateKeyP) \ + op (merge_pub, const struct TALER_PurseMergePublicKeyP) \ + op (contract_priv, const struct TALER_ContractDiffiePrivateP) \ + op (reserve_priv, const struct TALER_ReservePrivateKeyP) \ + op (reserve_sig, const struct TALER_ReserveSignatureP) \ + op (h_payto, const struct TALER_PaytoHashP) \ + op (account_access_token, const struct TALER_AccountAccessTokenP) \ + op (account_priv, const union TALER_AccountPrivateKeyP) \ + op (account_pub, const union TALER_AccountPublicKeyP) \ + op (planchet_secret, const struct TALER_PlanchetMasterSecretP) \ + op (refresh_secret, const struct TALER_RefreshMasterSecretP) \ + op (reserve_pub, const struct TALER_ReservePublicKeyP) \ + op (merchant_priv, const struct TALER_MerchantPrivateKeyP) \ + op (merchant_pub, const struct TALER_MerchantPublicKeyP) \ + op (merchant_sig, const struct TALER_MerchantSignatureP) \ + op (wtid, const struct TALER_WireTransferIdentifierRawP) \ + op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \ + op (contract_terms, const json_t) \ + op (wire_details, const json_t) \ + op (exchange_url, const char) \ + op (auditor_url, const char) \ + op (exchange_bank_account_url, const char) \ + op (taler_uri, const char) \ + op (payto_uri, const char) \ + op (kyc_url, const char) \ + op (web_url, const char) \ + op (row, const uint64_t) \ + op (legi_requirement_row, const uint64_t) \ + op (array_length, const unsigned int) \ + op (credit_payto_uri, const char) \ + op (debit_payto_uri, const char) \ + op (order_id, const char) \ + op (amount, const struct TALER_Amount) \ + op (amount_with_fee, const struct TALER_Amount) \ + op (batch_cmds, struct TALER_TESTING_Command) \ + op (uuid, const struct GNUNET_Uuid) \ + op (fresh_coins, const struct TALER_TESTING_FreshCoinData *) \ + op (claim_token, const struct TALER_ClaimTokenP) \ + op (relative_time, const struct GNUNET_TIME_Relative) \ + op (fakebank, struct TALER_FAKEBANK_Handle) \ + op (keys, struct TALER_EXCHANGE_Keys) \ + op (process, struct GNUNET_OS_Process *) /** @@ -2732,9 +2736,9 @@ op (aml_decision, enum TALER_AmlDecisionState) \ op (blinding_key, const union GNUNET_CRYPTO_BlindingSecretP) \ op (h_blinded_coin, const struct TALER_BlindedCoinHashP) - TALER_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT) +TALER_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT) - TALER_TESTING_INDEXED_TRAITS (TALER_TESTING_MAKE_DECL_INDEXED_TRAIT) +TALER_TESTING_INDEXED_TRAITS (TALER_TESTING_MAKE_DECL_INDEXED_TRAIT) #endif diff --git a/src/lib/exchange_api_kyc_check.c b/src/lib/exchange_api_kyc_check.c @@ -229,7 +229,7 @@ TALER_EXCHANGE_kyc_check ( struct GNUNET_CURL_Context *ctx, const char *url, uint64_t requirement_row, - const struct GNUNET_CRYPTO_EddsaPrivateKey *pk, + const union TALER_AccountPrivateKeyP *account_priv, struct GNUNET_TIME_Relative timeout, TALER_EXCHANGE_KycStatusCallback cb, void *cb_cls) @@ -268,6 +268,7 @@ TALER_EXCHANGE_kyc_check ( GNUNET_free (kch); return NULL; } + // FIXME: use account_priv!! kch->job = GNUNET_CURL_job_add_with_ct_json (ctx, eh, &handle_kyc_check_finished, diff --git a/src/lib/exchange_api_lookup_aml_decisions.c b/src/lib/exchange_api_lookup_aml_decisions.c @@ -287,6 +287,8 @@ parse_aml_decisions ( &decision->h_payto), GNUNET_JSON_spec_uint64 ("rowid", &decision->rowid), + GNUNET_JSON_spec_string ("justification", + &decision->justification), GNUNET_JSON_spec_timestamp ("decision_time", &decision->decision_time), GNUNET_JSON_spec_mark_optional ( diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am @@ -57,7 +57,6 @@ libtalertesting_la_SOURCES = \ testing_api_cmd_batch.c \ testing_api_cmd_batch_deposit.c \ testing_api_cmd_batch_withdraw.c \ - testing_api_cmd_check_aml_decision.c \ testing_api_cmd_check_aml_decisions.c \ testing_api_cmd_coin_history.c \ testing_api_cmd_common.c \ diff --git a/src/testing/testing_api_cmd_check_aml_decision.c b/src/testing/testing_api_cmd_check_aml_decision.c @@ -1,270 +0,0 @@ -/* - 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 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 - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, see - <http://www.gnu.org/licenses/> -*/ -/** - * @file testing/testing_api_cmd_check_aml_decision.c - * @brief command for testing /management/XXX - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include <gnunet/gnunet_curl_lib.h> -#include "taler_testing_lib.h" -#include "taler_signatures.h" -#include "backoff.h" - - -/** - * State for a "check_aml_decision" CMD. - */ -struct AmlCheckState -{ - - /** - * Handle while operation is running. - */ - struct TALER_EXCHANGE_LookupAmlDecision *dh; - - /** - * Our interpreter. - */ - struct TALER_TESTING_Interpreter *is; - - /** - * Reference to command to previous set officer. - */ - const char *ref_officer; - - /** - * Reference to command to the previous set AML status operation. - */ - const char *ref_operation; - - /** - * Expected HTTP status. - */ - unsigned int expected_http_status; - -}; - - -/** - * Callback to analyze the /aml/$OFFICER_PUB/$decision/$H_PAYTO response, just used to check - * if the response code is acceptable. - * - * @param cls closure. - * @param adr response details - */ -static void -check_aml_decision_cb (void *cls, - const struct TALER_EXCHANGE_AmlDecisionResponse *adr) -{ - struct AmlCheckState *ds = cls; - - ds->dh = NULL; - if (ds->expected_http_status != adr->hr.http_status) - { - TALER_TESTING_unexpected_status (ds->is, - adr->hr.http_status, - ds->expected_http_status); - return; - } - if (MHD_HTTP_OK == adr->hr.http_status) - { - const struct TALER_TESTING_Command *ref; - const char *justification; - enum TALER_AmlDecisionState *new_state; - const struct TALER_Amount *amount; - const struct TALER_EXCHANGE_AmlDecisionDetail *oldest = NULL; - - ref = TALER_TESTING_interpreter_lookup_command (ds->is, - ds->ref_operation); - if (NULL == ref) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (ds->is); - return; - } - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_aml_justification (ref, - &justification)); - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_aml_decision (ref, - &new_state)); - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_amount (ref, - &amount)); - for (unsigned int i = 0; i<adr->details.ok.aml_history_length; i++) - { - const struct TALER_EXCHANGE_AmlDecisionDetail *aml_history - = &adr->details.ok.aml_history[i]; - - if ( (NULL == oldest) || - (0 != - TALER_amount_cmp (amount, - &oldest->new_threshold)) || - (GNUNET_TIME_timestamp_cmp (oldest->decision_time, - >, - aml_history->decision_time)) ) - oldest = aml_history; - } - if (NULL == oldest) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (ds->is); - return; - } - if ( (oldest->new_state != *new_state) || - (0 != strcmp (oldest->justification, - justification) ) ) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (ds->is); - return; - } - } - TALER_TESTING_interpreter_next (ds->is); -} - - -/** - * Run the command. - * - * @param cls closure. - * @param cmd the command to execute. - * @param is the interpreter state. - */ -static void -check_aml_decision_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is) -{ - struct AmlCheckState *ds = cls; - const struct TALER_PaytoHashP *h_payto; - const struct TALER_AmlOfficerPrivateKeyP *officer_priv; - const struct TALER_TESTING_Command *ref; - const char *exchange_url; - - (void) cmd; - ds->is = is; - { - const struct TALER_TESTING_Command *exchange_cmd; - - exchange_cmd = TALER_TESTING_interpreter_get_command (is, - "exchange"); - if (NULL == exchange_cmd) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; - } - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_exchange_url (exchange_cmd, - &exchange_url)); - } - - ref = TALER_TESTING_interpreter_lookup_command (is, - ds->ref_operation); - if (NULL == ref) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; - } - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_h_payto (ref, - &h_payto)); - ref = TALER_TESTING_interpreter_lookup_command (is, - ds->ref_officer); - if (NULL == ref) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; - } - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_officer_priv (ref, - &officer_priv)); - ds->dh = TALER_EXCHANGE_lookup_aml_decision ( - TALER_TESTING_interpreter_get_context (is), - exchange_url, - h_payto, - officer_priv, - true, /* history */ - &check_aml_decision_cb, - ds); - if (NULL == ds->dh) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; - } -} - - -/** - * Free the state of a "check_aml_decision" CMD, and possibly cancel a - * pending operation thereof. - * - * @param cls closure, must be a `struct AmlCheckState`. - * @param cmd the command which is being cleaned up. - */ -static void -check_aml_decision_cleanup (void *cls, - const struct TALER_TESTING_Command *cmd) -{ - struct AmlCheckState *ds = cls; - - if (NULL != ds->dh) - { - TALER_TESTING_command_incomplete (ds->is, - cmd->label); - TALER_EXCHANGE_lookup_aml_decision_cancel (ds->dh); - ds->dh = NULL; - } - GNUNET_free (ds); -} - - -struct TALER_TESTING_Command -TALER_TESTING_cmd_check_aml_decision ( - const char *label, - const char *ref_officer, - const char *ref_operation, - unsigned int expected_http_status) -{ - struct AmlCheckState *ds; - - ds = GNUNET_new (struct AmlCheckState); - ds->ref_officer = ref_officer; - ds->ref_operation = ref_operation; - ds->expected_http_status = expected_http_status; - { - struct TALER_TESTING_Command cmd = { - .cls = ds, - .label = label, - .run = &check_aml_decision_run, - .cleanup = &check_aml_decision_cleanup - }; - - return cmd; - } -} - - -/* end of testing_api_cmd_check_aml_decision.c */ diff --git a/src/testing/testing_api_cmd_check_aml_decisions.c b/src/testing/testing_api_cmd_check_aml_decisions.c @@ -18,7 +18,7 @@ */ /** * @file testing/testing_api_cmd_check_aml_decisions.c - * @brief command for testing /aml/$OFFICER/decisions/$FILTER + * @brief command for testing GET /aml/$OFFICER_PUB/decisions * @author Christian Grothoff */ #include "platform.h" @@ -51,9 +51,9 @@ struct AmlCheckState const char *ref_officer; /** - * Which states to filter by. + * Reference to command to the previous set AML status operation. */ - enum TALER_AmlDecisionState filter; + const char *ref_operation; /** * Expected HTTP status. @@ -64,15 +64,15 @@ struct AmlCheckState /** - * Callback to analyze the /aml/$OFFICER_PUB/$decisions/$FILTER response, just used to check + * Callback to analyze the /aml/$OFFICER_PUB/$decision/$H_PAYTO response, just used to check * if the response code is acceptable. * * @param cls closure. * @param adr response details */ static void -check_aml_decisions_cb (void *cls, - const struct TALER_EXCHANGE_AmlDecisionsResponse *adr) +check_aml_decision_cb (void *cls, + const struct TALER_EXCHANGE_AmlDecisionsResponse *adr) { struct AmlCheckState *ds = cls; @@ -84,6 +84,49 @@ check_aml_decisions_cb (void *cls, ds->expected_http_status); return; } + if (MHD_HTTP_OK == adr->hr.http_status) + { + const struct TALER_TESTING_Command *ref; + const char *justification; + const struct TALER_EXCHANGE_AmlDecision *oldest = NULL; + + ref = TALER_TESTING_interpreter_lookup_command (ds->is, + ds->ref_operation); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ds->is); + return; + } + GNUNET_assert ( + GNUNET_OK == + TALER_TESTING_get_trait_aml_justification (ref, + &justification)); + for (unsigned int i = 0; i<adr->details.ok.decisions_length; i++) + { + const struct TALER_EXCHANGE_AmlDecision *aml_history + = &adr->details.ok.decisions[i]; + + if ( (NULL == oldest) || + (GNUNET_TIME_timestamp_cmp (oldest->decision_time, + >, + aml_history->decision_time)) ) + oldest = aml_history; + } + if (NULL == oldest) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ds->is); + return; + } + if (0 != strcmp (oldest->justification, + justification) ) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ds->is); + return; + } + } TALER_TESTING_interpreter_next (ds->is); } @@ -96,11 +139,12 @@ check_aml_decisions_cb (void *cls, * @param is the interpreter state. */ static void -check_aml_decisions_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is) +check_aml_decision_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) { struct AmlCheckState *ds = cls; + const struct TALER_PaytoHashP *h_payto; const struct TALER_AmlOfficerPrivateKeyP *officer_priv; const struct TALER_TESTING_Command *ref; const char *exchange_url; @@ -122,6 +166,18 @@ check_aml_decisions_run (void *cls, TALER_TESTING_get_trait_exchange_url (exchange_cmd, &exchange_url)); } + + ref = TALER_TESTING_interpreter_lookup_command (is, + ds->ref_operation); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_h_payto (ref, + &h_payto)); ref = TALER_TESTING_interpreter_lookup_command (is, ds->ref_officer); if (NULL == ref) @@ -136,11 +192,13 @@ check_aml_decisions_run (void *cls, ds->dh = TALER_EXCHANGE_lookup_aml_decisions ( TALER_TESTING_interpreter_get_context (is), exchange_url, - INT64_MAX, - -1, /* return last one for testing */ - ds->filter, + h_payto, + TALER_EXCHANGE_YNA_ALL, + TALER_EXCHANGE_YNA_ALL, + UINT64_MAX, + -1, officer_priv, - &check_aml_decisions_cb, + &check_aml_decision_cb, ds); if (NULL == ds->dh) { @@ -152,15 +210,15 @@ check_aml_decisions_run (void *cls, /** - * Free the state of a "check_aml_decisions" CMD, and possibly cancel a + * Free the state of a "check_aml_decision" CMD, and possibly cancel a * pending operation thereof. * * @param cls closure, must be a `struct AmlCheckState`. * @param cmd the command which is being cleaned up. */ static void -check_aml_decisions_cleanup (void *cls, - const struct TALER_TESTING_Command *cmd) +check_aml_decision_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) { struct AmlCheckState *ds = cls; @@ -176,24 +234,24 @@ check_aml_decisions_cleanup (void *cls, struct TALER_TESTING_Command -TALER_TESTING_cmd_check_aml_decisions ( +TALER_TESTING_cmd_check_aml_decision ( const char *label, const char *ref_officer, - enum TALER_AmlDecisionState filter, + const char *ref_operation, unsigned int expected_http_status) { struct AmlCheckState *ds; ds = GNUNET_new (struct AmlCheckState); ds->ref_officer = ref_officer; - ds->filter = filter; + ds->ref_operation = ref_operation; ds->expected_http_status = expected_http_status; { struct TALER_TESTING_Command cmd = { .cls = ds, .label = label, - .run = &check_aml_decisions_run, - .cleanup = &check_aml_decisions_cleanup + .run = &check_aml_decision_run, + .cleanup = &check_aml_decision_cleanup }; return cmd; @@ -201,4 +259,4 @@ TALER_TESTING_cmd_check_aml_decisions ( } -/* end of testing_api_cmd_check_aml_decisions.c */ +/* end of testing_api_cmd_check_aml_decision.c */ diff --git a/src/testing/testing_api_cmd_kyc_check_get.c b/src/testing/testing_api_cmd_kyc_check_get.c @@ -45,9 +45,9 @@ struct KycCheckGetState /** * Set to the KYC URL *if* the exchange replied with - * a request for KYC (#MHD_HTTP_ACCEPTED). + * a request for KYC (#MHD_HTTP_ACCEPTED or #MHD_HTTP_OK). */ - char *kyc_url; + struct TALER_AccountAccessTokenP access_token; /** * Handle to the "track transaction" pending operation. @@ -85,9 +85,10 @@ check_kyc_cb (void *cls, switch (ks->http_status) { case MHD_HTTP_OK: + kcg->access_token = ks->details.ok.access_token; break; case MHD_HTTP_ACCEPTED: - kcg->kyc_url = GNUNET_strdup (ks->details.accepted.kyc_url); + kcg->access_token = ks->details.accepted.access_token; break; case MHD_HTTP_NO_CONTENT: break; @@ -114,7 +115,7 @@ check_kyc_run (void *cls, struct KycCheckGetState *kcg = cls; const struct TALER_TESTING_Command *res_cmd; const uint64_t *requirement_row; - const struct TALER_PaytoHashP *h_payto; + const union TALER_AccountPrivateKeyP *account_priv; (void) cmd; kcg->is = is; @@ -136,8 +137,8 @@ check_kyc_run (void *cls, return; } if (GNUNET_OK != - TALER_TESTING_get_trait_h_payto (res_cmd, - &h_payto)) + TALER_TESTING_get_trait_account_priv (res_cmd, + &account_priv)) { GNUNET_break (0); TALER_TESTING_interpreter_fail (kcg->is); @@ -152,10 +153,8 @@ check_kyc_run (void *cls, kcg->kwh = TALER_EXCHANGE_kyc_check ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), - TALER_TESTING_get_keys (is), *requirement_row, - h_payto, - TALER_KYCLOGIC_KYC_UT_INDIVIDUAL, + account_priv, GNUNET_TIME_UNIT_SECONDS, &check_kyc_cb, kcg); @@ -183,7 +182,6 @@ check_kyc_cleanup (void *cls, TALER_EXCHANGE_kyc_check_cancel (kcg->kwh); kcg->kwh = NULL; } - GNUNET_free (kcg->kyc_url); GNUNET_free (kcg); } @@ -205,7 +203,7 @@ check_kyc_traits (void *cls, { struct KycCheckGetState *kcg = cls; struct TALER_TESTING_Trait traits[] = { - TALER_TESTING_make_trait_kyc_url (kcg->kyc_url), + TALER_TESTING_make_trait_account_access_token (&kcg->access_token), TALER_TESTING_trait_end () }; diff --git a/src/testing/testing_api_cmd_take_aml_decision.c b/src/testing/testing_api_cmd_take_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 @@ -63,24 +63,35 @@ struct AmlDecisionState struct TALER_PaytoHashP h_payto; /** - * New AML state to use. + * Justification given. */ - enum TALER_AmlDecisionState new_state; + const char *justification; /** - * Justification given. + * Delay to apply to compute the expiration time + * for the rules. */ - const char *justification; + struct GNUNET_TIME_Relative expiration_delay; + + /** + * Successor measure to activate upon expiration. + */ + const char *successor_measure; /** - * KYC requirement to add. + * True to keep AML investigation open. */ - const char *kyc_requirement; + bool keep_investigating; /** - * Threshold transaction amount. + * New rules to enforce. */ - struct TALER_Amount new_threshold; + json_t *new_rules; + + /** + * Account properties to set. + */ + json_t *properties; /** * Expected response code. @@ -133,10 +144,32 @@ take_aml_decision_run (void *cls, const struct TALER_PaytoHashP *h_payto; const struct TALER_AmlOfficerPrivateKeyP *officer_priv; const struct TALER_TESTING_Command *ref; - json_t *kyc_requirements = NULL; const char *exchange_url; + const json_t *jrules; + const json_t *jmeasures; + struct GNUNET_TIME_Timestamp expiration_time + = GNUNET_TIME_relative_to_timestamp (ds->expiration_delay); + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_array_const ("rules", + &jrules), + GNUNET_JSON_spec_object_const ("custom_measures", + &jmeasures), + GNUNET_JSON_spec_end () + }; + unsigned int num_rules; + unsigned int num_measures; (void) cmd; + if (GNUNET_OK != + GNUNET_JSON_parse (ds->new_rules, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + TALER_TESTING_interpreter_fail (is); + return; + } + { const struct TALER_TESTING_Command *exchange_cmd; @@ -187,28 +220,53 @@ take_aml_decision_run (void *cls, return; } ds->h_payto = *h_payto; - if (NULL != ds->kyc_requirement) + + num_rules = json_array_size (jrules); + num_measures = json_object_size (jmeasures); { - kyc_requirements = json_array (); - GNUNET_assert (NULL != kyc_requirements); - GNUNET_assert (0 == - json_array_append (kyc_requirements, - json_string (ds->kyc_requirement))); + struct TALER_EXCHANGE_AccountRule rules[ + GNUNET_NZL (num_rules)]; + struct TALER_EXCHANGE_MeasureInformation measures[ + GNUNET_NZL (num_measures)]; + const json_t *jrule; + size_t i; + const json_t *jmeasure; + const char *mname; + unsigned int off; + + json_array_foreach ((json_t *) jrules, i, jrule) + { + struct TALER_EXCHANGE_AccountRule *rule = &rules[i]; + // FIXME: jrule -> rule + } + off = 0; + json_object_foreach ((json_t *) jrules, mname, jmeasure) + { + struct TALER_EXCHANGE_MeasureInformation *mi = &measures[off++]; + // FIXME: jmeasure + mname -> mi + } + GNUNET_assert (off == num_measures); + + ds->dh = TALER_EXCHANGE_add_aml_decision ( + TALER_TESTING_interpreter_get_context (is), + exchange_url, + h_payto, + now, + ds->successor_measure, + expiration_time, + num_rules, + rules, + num_measures, + measures, + ds->properties, + ds->keep_investigating, + ds->justification, + officer_priv, + &take_aml_decision_cb, + ds); + // FIXME: free rules/measures data! } - ds->dh = TALER_EXCHANGE_add_aml_decision ( - TALER_TESTING_interpreter_get_context (is), - exchange_url, - ds->justification, - now, - &ds->new_threshold, - h_payto, - ds->new_state, - kyc_requirements, - officer_priv, - &take_aml_decision_cb, - ds); - json_decref (kyc_requirements); if (NULL == ds->dh) { GNUNET_break (0); @@ -238,6 +296,7 @@ take_aml_decision_cleanup (void *cls, TALER_EXCHANGE_add_aml_decision_cancel (ds->dh); ds->dh = NULL; } + json_decref (ds->new_rules); GNUNET_free (ds); } @@ -262,8 +321,6 @@ take_aml_decision_traits (void *cls, struct TALER_TESTING_Trait traits[] = { TALER_TESTING_make_trait_h_payto (&ws->h_payto), TALER_TESTING_make_trait_aml_justification (ws->justification), - TALER_TESTING_make_trait_aml_decision (&ws->new_state), - TALER_TESTING_make_trait_amount (&ws->new_threshold), TALER_TESTING_trait_end () }; @@ -279,29 +336,31 @@ TALER_TESTING_cmd_take_aml_decision ( const char *label, const char *ref_officer, const char *ref_operation, - const char *new_threshold, + bool keep_investigating, + struct GNUNET_TIME_Relative expiration_delay, + const char *successor_measure, + const char *new_rules, + const char *properties, const char *justification, - enum TALER_AmlDecisionState new_state, - const char *kyc_requirement, unsigned int expected_response) { struct AmlDecisionState *ds; + json_error_t err; ds = GNUNET_new (struct AmlDecisionState); ds->officer_ref_cmd = ref_officer; ds->account_ref_cmd = ref_operation; - ds->kyc_requirement = kyc_requirement; - if (GNUNET_OK != - TALER_string_to_amount (new_threshold, - &ds->new_threshold)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse amount `%s' at %s\n", - new_threshold, - label); - GNUNET_assert (0); - } - ds->new_state = new_state; + ds->keep_investigating = keep_investigating; + ds->expiration_delay = expiration_delay; + ds->successor_measure = successor_measure; + ds->new_rules = json_loads (new_rules, + JSON_DECODE_ANY, + &err); + GNUNET_assert (NULL != ds->new_rules); + ds->properties = json_loads (properties, + 0, + &err); + GNUNET_assert (NULL != ds->properties); ds->justification = justification; ds->expected_response = expected_response; {