-fix AML decision update logic and history fetch logic

This commit is contained in:
Christian Grothoff 2023-02-04 21:54:47 +01:00
parent 47b9ef598d
commit 5a18e955eb
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
9 changed files with 105 additions and 21 deletions

View File

@ -119,7 +119,7 @@ TEH_handler_post_aml_decision (
if (0 == --retries_left) if (0 == --retries_left)
break; break;
} while (GNUNET_DB_STATUS_SOFT_ERROR == qs); } while (GNUNET_DB_STATUS_SOFT_ERROR == qs);
if (qs < 0) if (qs <= 0)
{ {
GNUNET_break (0); GNUNET_break (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (connection,
@ -129,6 +129,7 @@ TEH_handler_post_aml_decision (
} }
if (invalid_officer) if (invalid_officer)
{ {
GNUNET_break_op (0);
return TALER_MHD_reply_with_error ( return TALER_MHD_reply_with_error (
connection, connection,
MHD_HTTP_FORBIDDEN, MHD_HTTP_FORBIDDEN,
@ -136,7 +137,7 @@ TEH_handler_post_aml_decision (
NULL); NULL);
} }
if (GNUNET_TIME_timestamp_cmp (last_date, if (GNUNET_TIME_timestamp_cmp (last_date,
>, >=,
decision_time)) decision_time))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);

View File

@ -63,10 +63,10 @@ record_cb (
GNUNET_JSON_PACK ( GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("h_payto", GNUNET_JSON_pack_data_auto ("h_payto",
h_payto), h_payto),
TALER_JSON_pack_amount ("threshold",
threshold),
GNUNET_JSON_pack_int64 ("current_state", GNUNET_JSON_pack_int64 ("current_state",
status), status),
TALER_JSON_pack_amount ("threshold",
threshold),
GNUNET_JSON_pack_int64 ("rowid", GNUNET_JSON_pack_int64 ("rowid",
row_id) row_id)
))); )));
@ -98,8 +98,8 @@ TEH_handler_aml_decisions_get (
else if (0 == strcmp (state_str, else if (0 == strcmp (state_str,
"frozen")) "frozen"))
decision = TALER_AML_FROZEN; decision = TALER_AML_FROZEN;
if (0 == strcmp (state_str, else if (0 == strcmp (state_str,
"normal")) "normal"))
decision = TALER_AML_NORMAL; decision = TALER_AML_NORMAL;
else else
{ {
@ -172,10 +172,11 @@ TEH_handler_aml_decisions_get (
qs = TEH_plugin->select_aml_process (TEH_plugin->cls, qs = TEH_plugin->select_aml_process (TEH_plugin->cls,
decision, decision,
start, start,
delta > 0,
GNUNET_MIN (MAX_RECORDS, GNUNET_MIN (MAX_RECORDS,
delta > 0 ? delta : delta > 0
-delta), ? delta
: -delta),
delta > 0,
&record_cb, &record_cb,
records); records);
switch (qs) switch (qs)

View File

@ -26,7 +26,7 @@ BEGIN
PERFORM create_partitioned_table( PERFORM create_partitioned_table(
'CREATE TABLE IF NOT EXISTS %I' 'CREATE TABLE IF NOT EXISTS %I'
'(aml_history_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' '(aml_history_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY'
',h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=32)' ',h_payto BYTEA CHECK (LENGTH(h_payto)=32)'
',new_threshold_val INT8 NOT NULL DEFAULT(0)' ',new_threshold_val INT8 NOT NULL DEFAULT(0)'
',new_threshold_frac INT4 NOT NULL DEFAULT(0)' ',new_threshold_frac INT4 NOT NULL DEFAULT(0)'
',new_status INT4 NOT NULL DEFAULT(0)' ',new_status INT4 NOT NULL DEFAULT(0)'

View File

@ -140,25 +140,25 @@ TEH_PG_select_aml_process (
"SELECT" "SELECT"
" aml_status_serial_id" " aml_status_serial_id"
",h_payto" ",h_payto"
",threshold_var" ",threshold_val"
",threshold_frac" ",threshold_frac"
",status" ",status"
" FROM aml_status" " FROM aml_status"
" WHERE aml_status_serial_id > $2" " WHERE aml_status_serial_id > $2"
" AND status = $1" " AND status = $1"
" ORDER BY aml_status_serial_id INC" " ORDER BY aml_status_serial_id ASC"
" LIMIT $3"); " LIMIT $3");
PREPARE (pg, PREPARE (pg,
"select_aml_process_dec", "select_aml_process_dec",
"SELECT" "SELECT"
" aml_status_serial_id" " aml_status_serial_id"
",h_payto" ",h_payto"
",threshold_var" ",threshold_val"
",threshold_frac" ",threshold_frac"
",status" ",status"
" FROM aml_status" " FROM aml_status"
" WHERE aml_status_serial_id < $2" " WHERE aml_status_serial_id < $2"
" AND $1 = status & $1" " AND status = $1"
" ORDER BY aml_status_serial_id DESC" " ORDER BY aml_status_serial_id DESC"
" LIMIT $3"); " LIMIT $3");
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,

View File

@ -4305,15 +4305,20 @@ TALER_EXCHANGE_management_update_aml_officer_cancel (
struct TALER_EXCHANGE_AmlDecisionSummary struct TALER_EXCHANGE_AmlDecisionSummary
{ {
/** /**
* When was the last decision made. * What is the current monthly threshold.
*/ */
struct GNUNET_TIME_Timestamp last_decision_time; struct TALER_Amount threshold;
/** /**
* Account the decision was made for. * Account the decision was made for.
*/ */
struct TALER_PaytoHashP h_payto; struct TALER_PaytoHashP h_payto;
/**
* RowID of this decision.
*/
uint64_t rowid;
/** /**
* Current decision state. * Current decision state.
*/ */

View File

@ -2774,6 +2774,24 @@ TALER_TESTING_cmd_check_aml_decision (
unsigned int expected_http_status); unsigned int expected_http_status);
/**
* Fetch AML decisions.
*
* @param label command label
* @param ref_officer command that previously created an
* officer
* @param filter AML state to filter by
* @param expected_http_status expected HTTP response status
* @return the command
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_check_aml_decisions (
const char *label,
const char *ref_officer,
enum TALER_AmlDecisionState filter,
unsigned int expected_http_status);
/* *** Generic trait logic for implementing traits ********* */ /* *** Generic trait logic for implementing traits ********* */

View File

@ -82,12 +82,14 @@ parse_aml_decisions (const json_t *decisions,
struct TALER_EXCHANGE_AmlDecisionSummary *decision = &decision_ar[idx]; struct TALER_EXCHANGE_AmlDecisionSummary *decision = &decision_ar[idx];
uint32_t state32; uint32_t state32;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_timestamp ("last_decision_time",
&decision->last_decision_time),
GNUNET_JSON_spec_fixed_auto ("h_payto", GNUNET_JSON_spec_fixed_auto ("h_payto",
&decision->h_payto), &decision->h_payto),
GNUNET_JSON_spec_uint32 ("current_state", GNUNET_JSON_spec_uint32 ("current_state",
&state32), &state32),
TALER_JSON_spec_amount_any ("threshold",
&decision->threshold),
GNUNET_JSON_spec_uint64 ("rowid",
&decision->rowid),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
@ -196,6 +198,8 @@ handle_lookup_finished (void *cls,
GNUNET_assert (NULL == lh->decisions_cb); GNUNET_assert (NULL == lh->decisions_cb);
TALER_EXCHANGE_lookup_aml_decisions_cancel (lh); TALER_EXCHANGE_lookup_aml_decisions_cancel (lh);
return; return;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_BAD_REQUEST: case MHD_HTTP_BAD_REQUEST:
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);
@ -292,9 +296,26 @@ TALER_EXCHANGE_lookup_aml_decisions (
lh = GNUNET_new (struct TALER_EXCHANGE_LookupAmlDecisions); lh = GNUNET_new (struct TALER_EXCHANGE_LookupAmlDecisions);
lh->decisions_cb = cb; lh->decisions_cb = cb;
lh->decisions_cb_cls = cb_cls; lh->decisions_cb_cls = cb_cls;
lh->url = TALER_url_join (exchange_url, {
arg_str, char delta_s[24];
NULL); char start_s[24];
GNUNET_snprintf (delta_s,
sizeof (delta_s),
"%d",
delta);
GNUNET_snprintf (start_s,
sizeof (start_s),
"%llu",
(unsigned long long) start);
lh->url = TALER_url_join (exchange_url,
arg_str,
"delta",
delta_s,
"start",
start_s,
NULL);
}
if (NULL == lh->url) if (NULL == lh->url)
{ {
GNUNET_free (lh); GNUNET_free (lh);

View File

@ -56,6 +56,7 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_batch_withdraw.c \ testing_api_cmd_batch_withdraw.c \
testing_api_cmd_change_auth.c \ testing_api_cmd_change_auth.c \
testing_api_cmd_check_aml_decision.c \ testing_api_cmd_check_aml_decision.c \
testing_api_cmd_check_aml_decisions.c \
testing_api_cmd_check_keys.c \ testing_api_cmd_check_keys.c \
testing_api_cmd_common.c \ testing_api_cmd_common.c \
testing_api_cmd_contract_get.c \ testing_api_cmd_contract_get.c \

View File

@ -421,6 +421,18 @@ run (void *cls,
"Peter Falk", "Peter Falk",
true, true,
false), false),
TALER_TESTING_cmd_check_aml_decisions ("check-decisions-none-normal",
"create-aml-officer-1",
TALER_AML_NORMAL,
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_check_aml_decisions ("check-decisions-none-pending",
"create-aml-officer-1",
TALER_AML_PENDING,
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_check_aml_decisions ("check-decisions-none-frozen",
"create-aml-officer-1",
TALER_AML_FROZEN,
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_sleep ("sleep-1a", TALER_TESTING_cmd_sleep ("sleep-1a",
1), 1),
TALER_TESTING_cmd_set_officer ("create-aml-officer-1-disable", TALER_TESTING_cmd_set_officer ("create-aml-officer-1-disable",
@ -457,12 +469,37 @@ run (void *cls,
"party time", "party time",
TALER_AML_NORMAL, TALER_AML_NORMAL,
MHD_HTTP_NO_CONTENT), MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_check_aml_decisions ("check-decisions-one-normal",
"create-aml-officer-1",
TALER_AML_NORMAL,
MHD_HTTP_OK),
TALER_TESTING_cmd_check_aml_decisions ("check-decisions-zero-frozen",
"create-aml-officer-1",
TALER_AML_FROZEN,
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_check_aml_decision ("check-aml-decision", TALER_TESTING_cmd_check_aml_decision ("check-aml-decision",
"create-aml-officer-1", "create-aml-officer-1",
"aml-decide", "aml-decide",
MHD_HTTP_OK), MHD_HTTP_OK),
TALER_TESTING_cmd_sleep ("sleep-1c", TALER_TESTING_cmd_sleep ("sleep-1c",
1), 1),
TALER_TESTING_cmd_take_aml_decision ("aml-decide-freeze",
"create-aml-officer-1",
"wallet-trigger-kyc-for-aml",
"EUR:1000",
"party over",
TALER_AML_FROZEN,
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_check_aml_decisions ("check-decisions-one-frozen",
"create-aml-officer-1",
TALER_AML_FROZEN,
MHD_HTTP_OK),
TALER_TESTING_cmd_check_aml_decisions ("check-decisions-zero-normal",
"create-aml-officer-1",
TALER_AML_NORMAL,
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_sleep ("sleep-1d",
1),
TALER_TESTING_cmd_set_officer ("create-aml-officer-1-disable", TALER_TESTING_cmd_set_officer ("create-aml-officer-1-disable",
"create-aml-officer-1", "create-aml-officer-1",
"Peter Falk", "Peter Falk",