add tests for new AML logic, plus related bugfixes

This commit is contained in:
Christian Grothoff 2023-02-04 16:01:46 +01:00
parent c3243aa39f
commit 19da4bd638
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
17 changed files with 178 additions and 141 deletions

@ -1 +1 @@
Subproject commit 14cb23ef0e31d3470a0671fe165a1557eddc0590 Subproject commit 3a616a04f1cd946bf0641b54cd71f1b858174f74

View File

@ -488,13 +488,55 @@ handle_get_aml (struct TEH_RequestContext *rc,
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS, TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
"AML GET operations must specify an operation identifier"); "AML GET operations must specify an operation identifier");
} }
if (1) // FIXME: check AML officer GET signature!
{ {
GNUNET_break_op (0); const char *sig_hdr;
return TALER_MHD_reply_with_error (rc->connection, struct TALER_AmlOfficerSignatureP officer_sig;
MHD_HTTP_FORBIDDEN,
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID, sig_hdr = MHD_lookup_connection_value (rc->connection,
NULL); MHD_HEADER_KIND,
TALER_AML_OFFICER_SIGNATURE_HEADER);
if ( (NULL == sig_hdr) ||
(GNUNET_OK !=
GNUNET_STRINGS_string_to_data (sig_hdr,
strlen (sig_hdr),
&officer_sig,
sizeof (officer_sig))) ||
(GNUNET_OK !=
TALER_officer_aml_query_verify (&officer_pub,
&officer_sig)) )
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID,
sig_hdr);
}
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
}
{
enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->test_aml_officer (TEH_plugin->cls,
&officer_pub);
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
case GNUNET_DB_STATUS_SOFT_ERROR:
GNUNET_break (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_FETCH_FAILED,
NULL);
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_FORBIDDEN,
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED,
NULL);
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
break;
}
} }
for (unsigned int i = 0; NULL != h[i].op; i++) for (unsigned int i = 0; NULL != h[i].op; i++)
if (0 == strcmp (h[i].op, if (0 == strcmp (h[i].op,

View File

@ -101,7 +101,7 @@ static void
aml_history_cb ( aml_history_cb (
void *cls, void *cls,
const struct TALER_Amount *new_threshold, const struct TALER_Amount *new_threshold,
enum TALER_AmlDecisionState new_status, enum TALER_AmlDecisionState new_state,
struct GNUNET_TIME_Timestamp decision_time, struct GNUNET_TIME_Timestamp decision_time,
const char *justification, const char *justification,
const struct TALER_AmlOfficerPublicKeyP *decider_pub, const struct TALER_AmlOfficerPublicKeyP *decider_pub,
@ -120,8 +120,8 @@ aml_history_cb (
justification), justification),
TALER_JSON_pack_amount ("new_threshold", TALER_JSON_pack_amount ("new_threshold",
new_threshold), new_threshold),
GNUNET_JSON_pack_int64 ("new_status", GNUNET_JSON_pack_int64 ("new_state",
new_status), new_state),
GNUNET_JSON_pack_timestamp ("decision_time", GNUNET_JSON_pack_timestamp ("decision_time",
decision_time) decision_time)
))); )));
@ -134,7 +134,6 @@ TEH_handler_aml_decision_get (
const struct TALER_AmlOfficerPublicKeyP *officer_pub, const struct TALER_AmlOfficerPublicKeyP *officer_pub,
const char *const args[]) const char *const args[])
{ {
struct TALER_AmlOfficerSignatureP officer_sig;
struct TALER_PaytoHashP h_payto; struct TALER_PaytoHashP h_payto;
if ( (NULL == args[0]) || if ( (NULL == args[0]) ||
@ -159,30 +158,6 @@ TEH_handler_aml_decision_get (
TALER_EC_GENERIC_ENDPOINT_UNKNOWN, TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
args[1]); args[1]);
} }
{
const char *sig_hdr;
sig_hdr = MHD_lookup_connection_value (rc->connection,
MHD_HEADER_KIND,
TALER_AML_OFFICER_SIGNATURE_HEADER);
if ( (NULL == sig_hdr) ||
(GNUNET_OK !=
GNUNET_STRINGS_string_to_data (sig_hdr,
strlen (sig_hdr),
&officer_sig,
sizeof (officer_sig))) ||
(GNUNET_OK !=
TALER_officer_aml_query_verify (officer_pub,
&officer_sig)) )
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID,
sig_hdr);
}
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
}
{ {
json_t *aml_history; json_t *aml_history;

View File

@ -76,7 +76,10 @@ TEH_handler_post_aml_decision (
if (GNUNET_SYSERR == res) if (GNUNET_SYSERR == res)
return MHD_NO; /* hard failure */ return MHD_NO; /* hard failure */
if (GNUNET_NO == res) if (GNUNET_NO == res)
{
GNUNET_break_op (0);
return MHD_YES; /* failure */ return MHD_YES; /* failure */
}
} }
new_state = (enum TALER_AmlDecisionState) new_state32; new_state = (enum TALER_AmlDecisionState) new_state32;
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;

View File

@ -79,7 +79,6 @@ TEH_handler_aml_decisions_get (
const struct TALER_AmlOfficerPublicKeyP *officer_pub, const struct TALER_AmlOfficerPublicKeyP *officer_pub,
const char *const args[]) const char *const args[])
{ {
struct TALER_AmlOfficerSignatureP officer_sig;
enum TALER_AmlDecisionState decision; enum TALER_AmlDecisionState decision;
int delta = -20; int delta = -20;
unsigned long long start = INT64_MAX; unsigned long long start = INT64_MAX;
@ -118,30 +117,6 @@ TEH_handler_aml_decisions_get (
TALER_EC_GENERIC_ENDPOINT_UNKNOWN, TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
args[1]); args[1]);
} }
{
const char *sig_hdr;
sig_hdr = MHD_lookup_connection_value (rc->connection,
MHD_HEADER_KIND,
TALER_AML_OFFICER_SIGNATURE_HEADER);
if ( (NULL == sig_hdr) ||
(GNUNET_OK !=
GNUNET_STRINGS_string_to_data (sig_hdr,
strlen (sig_hdr),
&officer_sig,
sizeof (officer_sig))) ||
(GNUNET_OK !=
TALER_officer_aml_query_verify (officer_pub,
&officer_sig)) )
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID,
sig_hdr);
}
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
}
{ {
const char *p; const char *p;

View File

@ -136,7 +136,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
pg_select_similar_kyc_attributes.h pg_select_similar_kyc_attributes.c \ pg_select_similar_kyc_attributes.h pg_select_similar_kyc_attributes.c \
pg_select_kyc_attributes.h pg_select_kyc_attributes.c \ pg_select_kyc_attributes.h pg_select_kyc_attributes.c \
pg_insert_aml_officer.h pg_insert_aml_officer.c \ pg_insert_aml_officer.h pg_insert_aml_officer.c \
pg_update_aml_officer.h pg_update_aml_officer.c \ pg_test_aml_officer.h pg_test_aml_officer.c \
pg_lookup_aml_officer.h pg_lookup_aml_officer.c \ pg_lookup_aml_officer.h pg_lookup_aml_officer.c \
pg_trigger_aml_process.h pg_trigger_aml_process.c \ pg_trigger_aml_process.h pg_trigger_aml_process.c \
pg_select_aml_process.h pg_select_aml_process.c \ pg_select_aml_process.h pg_select_aml_process.c \

View File

@ -56,8 +56,8 @@ THEN
RETURN; RETURN;
END IF; END IF;
UPDATE exchange.aml_status UPDATE exchange.aml_status
SET threshold_val=in_threshold_val SET threshold_val=in_new_threshold_val
,threshold_frac=in_threshold_frac ,threshold_frac=in_new_threshold_frac
,status=in_new_status ,status=in_new_status
WHERE h_payto=in_h_payto; WHERE h_payto=in_h_payto;
ASSERT FOUND, 'cannot have AML decision history but no AML status'; ASSERT FOUND, 'cannot have AML decision history but no AML status';
@ -70,8 +70,8 @@ ELSE
,status) ,status)
VALUES VALUES
(in_h_payto (in_h_payto
,in_threshold_val ,in_new_threshold_val
,in_threshold_frac ,in_new_threshold_frac
,in_new_status); ,in_new_status);
END IF; END IF;

View File

@ -138,18 +138,13 @@ TEH_PG_select_aml_history (
PREPARE (pg, PREPARE (pg,
"lookup_aml_history", "lookup_aml_history",
"SELECT" "SELECT"
" aggregation_serial_id" " new_threshold_val"
",deposits.h_contract_terms" ",new_threshold_frac"
",payto_uri" ",new_status"
",wire_targets.wire_target_h_payto" ",decision_time"
",kc.coin_pub" ",justification"
",deposits.merchant_pub" ",decider_pub"
",wire_out.execution_date" ",decider_sig"
",deposits.amount_with_fee_val"
",deposits.amount_with_fee_frac"
",denom.fee_deposit_val"
",denom.fee_deposit_frac"
",denom.denom_pub"
" FROM aml_history" " FROM aml_history"
" WHERE h_payto=$1;"); " WHERE h_payto=$1;");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,

View File

@ -14,49 +14,35 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/ */
/** /**
* @file exchangedb/pg_update_aml_officer.c * @file exchangedb/pg_test_aml_officer.c
* @brief Implementation of the update_aml_officer function for Postgres * @brief Implementation of the test_aml_officer function for Postgres
* @author Christian Grothoff * @author Christian Grothoff
*/ */
#include "platform.h" #include "platform.h"
#include "taler_error_codes.h" #include "taler_error_codes.h"
#include "taler_dbevents.h" #include "taler_dbevents.h"
#include "taler_pq_lib.h" #include "taler_pq_lib.h"
#include "pg_update_aml_officer.h" #include "pg_test_aml_officer.h"
#include "pg_helper.h" #include "pg_helper.h"
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
TEH_PG_update_aml_officer ( TEH_PG_test_aml_officer (
void *cls, void *cls,
const struct TALER_AmlOfficerPublicKeyP *decider_pub, const struct TALER_AmlOfficerPublicKeyP *decider_pub)
const struct TALER_MasterSignatureP *master_sig,
const char *decider_name,
bool is_active,
bool read_only,
struct GNUNET_TIME_Absolute last_change)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (decider_pub), GNUNET_PQ_query_param_auto_from_type (decider_pub),
GNUNET_PQ_query_param_auto_from_type (master_sig),
GNUNET_PQ_query_param_string (decider_name),
GNUNET_PQ_query_param_bool (is_active),
GNUNET_PQ_query_param_bool (read_only),
GNUNET_PQ_query_param_absolute_time (&last_change),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
PREPARE (pg, PREPARE (pg,
"update_aml_staff", "test_aml_staff",
"UPDATE aml_staff SET " "SELECT 1 FROM aml_staff"
" master_sig=$2" " WHERE decider_pub=$1"
",decider_name=$3" " AND is_active;");
",is_active=$4"
",read_only=$5"
",last_change=$6"
" WHERE decider_pub=$1 AND last_change < $6;");
return GNUNET_PQ_eval_prepared_non_select (pg->conn, return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"update_aml_staff", "test_aml_staff",
params); params);
} }

View File

@ -27,25 +27,17 @@
/** /**
* Update AML staff record. * Test if the given AML staff member is active
* (at least read-only).
* *
* @param cls closure * @param cls closure
* @param decider_pub public key of the staff member * @param decider_pub public key of the staff member
* @param master_sig offline signature affirming the AML officer * @return database transaction status, if member is unknown or not active, 1 if member is active
* @param decider_name full name of the staff member
* @param is_active true to enable, false to set as inactive
* @param read_only true to set read-only access
* @param last_change when was the change made effective
* @return database transaction status
*/ */
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
TEH_PG_update_aml_officer ( TEH_PG_test_aml_officer (
void *cls, void *cls,
const struct TALER_AmlOfficerPublicKeyP *decider_pub, const struct TALER_AmlOfficerPublicKeyP *decider_pub);
const struct TALER_MasterSignatureP *master_sig,
const char *decider_name,
bool is_active,
bool read_only,
struct GNUNET_TIME_Absolute last_change);
#endif #endif

View File

@ -210,7 +210,7 @@
#include "pg_select_similar_kyc_attributes.h" #include "pg_select_similar_kyc_attributes.h"
#include "pg_select_kyc_attributes.h" #include "pg_select_kyc_attributes.h"
#include "pg_insert_aml_officer.h" #include "pg_insert_aml_officer.h"
#include "pg_update_aml_officer.h" #include "pg_test_aml_officer.h"
#include "pg_lookup_aml_officer.h" #include "pg_lookup_aml_officer.h"
#include "pg_trigger_aml_process.h" #include "pg_trigger_aml_process.h"
#include "pg_select_aml_process.h" #include "pg_select_aml_process.h"
@ -761,8 +761,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_select_kyc_attributes; = &TEH_PG_select_kyc_attributes;
plugin->insert_aml_officer plugin->insert_aml_officer
= &TEH_PG_insert_aml_officer; = &TEH_PG_insert_aml_officer;
plugin->update_aml_officer plugin->test_aml_officer
= &TEH_PG_update_aml_officer; = &TEH_PG_test_aml_officer;
plugin->lookup_aml_officer plugin->lookup_aml_officer
= &TEH_PG_lookup_aml_officer; = &TEH_PG_lookup_aml_officer;
plugin->trigger_aml_process plugin->trigger_aml_process

View File

@ -6616,26 +6616,17 @@ struct TALER_EXCHANGEDB_Plugin
/** /**
* Update AML staff record. * Test if the given AML staff member is active
* (at least read-only).
* *
* @param cls closure * @param cls closure
* @param decider_pub public key of the staff member * @param decider_pub public key of the staff member
* @param master_sig offline signature affirming the AML officer * @return database transaction status, if member is unknown or not active, 1 if member is active
* @param decider_name full name of the staff member
* @param is_active true to enable, false to set as inactive
* @param read_only true to set read-only access
* @param last_change when was the change made effective
* @return database transaction status
*/ */
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
(*update_aml_officer)( (*test_aml_officer)(
void *cls, void *cls,
const struct TALER_AmlOfficerPublicKeyP *decider_pub, const struct TALER_AmlOfficerPublicKeyP *decider_pub);
const struct TALER_MasterSignatureP *master_sig,
const char *decider_name,
bool is_active,
bool read_only,
struct GNUNET_TIME_Absolute last_change);
/** /**

View File

@ -188,7 +188,7 @@ TALER_EXCHANGE_add_aml_decision (
&officer_sig), &officer_sig),
GNUNET_JSON_pack_data_auto ("h_payto", GNUNET_JSON_pack_data_auto ("h_payto",
h_payto), h_payto),
GNUNET_JSON_pack_uint64 ("state", GNUNET_JSON_pack_uint64 ("new_state",
(uint32_t) new_state), (uint32_t) new_state),
TALER_JSON_pack_amount ("new_threshold", TALER_JSON_pack_amount ("new_threshold",
new_threshold), new_threshold),

View File

@ -262,6 +262,12 @@ handle_lookup_finished (void *cls,
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
break; break;
case MHD_HTTP_FORBIDDEN:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, exchange says this coin was not melted; we
should pass the JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
lr.hr.ec = TALER_JSON_get_error_code (j); lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j); lr.hr.hint = TALER_JSON_get_error_hint (j);
@ -280,7 +286,7 @@ handle_lookup_finished (void *cls,
lr.hr.ec = TALER_JSON_get_error_code (j); lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j); lr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange link\n", "Unexpected response code %u/%d for exchange lookup AML decision\n",
(unsigned int) response_code, (unsigned int) response_code,
(int) lr.hr.ec); (int) lr.hr.ec);
break; break;
@ -332,7 +338,7 @@ TALER_EXCHANGE_lookup_aml_decision (
*end = '\0'; *end = '\0';
GNUNET_snprintf (arg_str, GNUNET_snprintf (arg_str,
sizeof (arg_str), sizeof (arg_str),
"/aml/%s/decision/%s", "aml/%s/decision/%s",
pub_str, pub_str,
pt_str); pt_str);
} }

View File

@ -202,6 +202,12 @@ handle_lookup_finished (void *cls,
/* This should never happen, either us or the exchange is buggy /* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */ (or API version conflict); just pass JSON reply to the application */
break; break;
case MHD_HTTP_FORBIDDEN:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, exchange says this coin was not melted; we
should pass the JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND: case MHD_HTTP_NOT_FOUND:
lr.hr.ec = TALER_JSON_get_error_code (j); lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j); lr.hr.hint = TALER_JSON_get_error_hint (j);
@ -220,7 +226,7 @@ handle_lookup_finished (void *cls,
lr.hr.ec = TALER_JSON_get_error_code (j); lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j); lr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange link\n", "Unexpected response code %u/%d for lookup AML decisions\n",
(unsigned int) response_code, (unsigned int) response_code,
(int) lr.hr.ec); (int) lr.hr.ec);
break; break;
@ -279,7 +285,7 @@ TALER_EXCHANGE_lookup_aml_decisions (
*end = '\0'; *end = '\0';
GNUNET_snprintf (arg_str, GNUNET_snprintf (arg_str,
sizeof (arg_str), sizeof (arg_str),
"/aml/%s/decisions/%s", "aml/%s/decisions/%s",
pub_str, pub_str,
state_str); state_str);
} }

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA Copyright (C) 2014-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as it under the terms of the GNU General Public License as
@ -410,7 +410,72 @@ run (void *cls,
MHD_HTTP_OK), MHD_HTTP_OK),
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };
struct TALER_TESTING_Command aml[] = {
/* Trigger something upon which an AML officer could act */
TALER_TESTING_cmd_wallet_kyc_get ("wallet-trigger-kyc-for-aml",
NULL,
"EUR:1000",
MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS),
TALER_TESTING_cmd_set_officer ("create-aml-officer-1",
NULL,
"Peter Falk",
true,
false),
TALER_TESTING_cmd_sleep ("sleep-1a",
1),
TALER_TESTING_cmd_set_officer ("create-aml-officer-1-disable",
"create-aml-officer-1",
"Peter Falk",
true,
true),
/* Test that we are not allowed to take AML decisions as our
AML staff account is on read-only */
TALER_TESTING_cmd_take_aml_decision ("aml-decide-while-disabled",
"create-aml-officer-1",
"wallet-trigger-kyc-for-aml",
"EUR:10000",
"party time",
TALER_AML_NORMAL,
MHD_HTTP_FORBIDDEN),
/* Check that no decision was taken, but that we are allowed
to read this information */
TALER_TESTING_cmd_check_aml_decision ("check-aml-decision-empty",
"create-aml-officer-1",
"aml-decide-while-disabled",
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_sleep ("sleep-1b",
1),
TALER_TESTING_cmd_set_officer ("create-aml-officer-1-enable",
"create-aml-officer-1",
"Peter Falk",
true,
false),
TALER_TESTING_cmd_take_aml_decision ("aml-decide",
"create-aml-officer-1",
"wallet-trigger-kyc-for-aml",
"EUR:10000",
"party time",
TALER_AML_NORMAL,
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_check_aml_decision ("check-aml-decision",
"create-aml-officer-1",
"aml-decide",
MHD_HTTP_OK),
TALER_TESTING_cmd_sleep ("sleep-1c",
1),
TALER_TESTING_cmd_set_officer ("create-aml-officer-1-disable",
"create-aml-officer-1",
"Peter Falk",
false,
true),
/* Test that we are NOT allowed to read AML decisions now that
our AML staff account is disabled */
TALER_TESTING_cmd_check_aml_decision ("check-aml-decision-disabled",
"create-aml-officer-1",
"aml-decide",
MHD_HTTP_FORBIDDEN),
TALER_TESTING_cmd_end ()
};
struct TALER_TESTING_Command commands[] = { struct TALER_TESTING_Command commands[] = {
TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
@ -452,6 +517,8 @@ run (void *cls,
push), push),
TALER_TESTING_cmd_batch ("pull", TALER_TESTING_cmd_batch ("pull",
pull), pull),
TALER_TESTING_cmd_batch ("aml",
aml),
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };

View File

@ -107,7 +107,6 @@ check_aml_decision_cb (void *cls,
TALER_TESTING_interpreter_fail (ds->is); TALER_TESTING_interpreter_fail (ds->is);
return; return;
} }
// FIXME: check returned details...
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_aml_justification (ref, TALER_TESTING_get_trait_aml_justification (ref,
&justification)); &justification));
@ -117,7 +116,7 @@ check_aml_decision_cb (void *cls,
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_amount (ref, TALER_TESTING_get_trait_amount (ref,
&amount)); &amount));
for (unsigned int i = 1; i<adr->details.success.aml_history_length; i++) for (unsigned int i = 0; i<adr->details.success.aml_history_length; i++)
{ {
const struct TALER_EXCHANGE_AmlDecisionDetail *aml_history const struct TALER_EXCHANGE_AmlDecisionDetail *aml_history
= &adr->details.success.aml_history[i]; = &adr->details.success.aml_history[i];