summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-02-17 18:24:20 +0100
committerChristian Grothoff <christian@grothoff.org>2023-02-17 18:24:20 +0100
commitaa5e7d2ad5e712434f32ab41b63d53bb897c6105 (patch)
tree63eca83e563d69d5d689f4e9c3c218be0950e854
parent86e0f2c70d07c7c5e1656667bd818498ea55d0a4 (diff)
downloadexchange-aa5e7d2ad5e712434f32ab41b63d53bb897c6105.tar.gz
exchange-aa5e7d2ad5e712434f32ab41b63d53bb897c6105.tar.bz2
exchange-aa5e7d2ad5e712434f32ab41b63d53bb897c6105.zip
more towards actually allowing AML decisions to trigger KYC
-rw-r--r--src/exchange/taler-exchange-httpd_aml-decision.c85
-rw-r--r--src/exchange/taler-exchange-httpd_batch-withdraw.c15
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-check.c13
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-wallet.c2
-rw-r--r--src/exchangedb/0003-aml_history.sql7
-rw-r--r--src/exchangedb/exchange_do_insert_aml_decision.sql5
-rw-r--r--src/exchangedb/pg_insert_aml_decision.c4
-rw-r--r--src/exchangedb/pg_insert_aml_decision.h2
-rw-r--r--src/include/taler_exchangedb_plugin.h3
-rw-r--r--src/include/taler_kyclogic_lib.h5
-rw-r--r--src/kyclogic/kyclogic_api.c31
11 files changed, 157 insertions, 15 deletions
diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c b/src/exchange/taler-exchange-httpd_aml-decision.c
index 0fd58b9ec..2830e54ed 100644
--- a/src/exchange/taler-exchange-httpd_aml-decision.c
+++ b/src/exchange/taler-exchange-httpd_aml-decision.c
@@ -103,6 +103,85 @@ make_aml_decision (void *cls,
enum GNUNET_DB_QueryStatus qs;
struct GNUNET_TIME_Timestamp last_date;
bool invalid_officer;
+ uint64_t requirement_row = 0;
+
+ if ( (NULL != dc->kyc_requirements) &&
+ (0 != json_array_size (dc->kyc_requirements)) )
+ {
+ char *res = NULL;
+ size_t idx;
+ json_t *req;
+ bool satisfied;
+
+ json_array_foreach (dc->kyc_requirements, idx, req)
+ {
+ const char *r = json_string_value (req);
+
+ if (NULL == res)
+ {
+ res = GNUNET_strdup (r);
+ }
+ else
+ {
+ char *tmp;
+
+ GNUNET_asprintf (&tmp,
+ "%s %s",
+ res,
+ r);
+ GNUNET_free (res);
+ res = tmp;
+ }
+ }
+
+ {
+ json_t *kyc_details = NULL;
+
+ qs = TALER_KYCLOGIC_check_satisfied (
+ &res,
+ &dc->h_payto,
+ &kyc_details,
+ TEH_plugin->select_satisfied_kyc_processes,
+ TEH_plugin->cls,
+ &satisfied);
+ json_decref (kyc_details);
+ }
+ if (qs < 0)
+ {
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ {
+ GNUNET_break (0);
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "select_satisfied_kyc_processes");
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return qs;
+ }
+ if (! satisfied)
+ {
+ qs = TEH_plugin->insert_kyc_requirement_for_account (
+ TEH_plugin->cls,
+ res,
+ &dc->h_payto,
+ &requirement_row);
+ if (qs < 0)
+ {
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ {
+ GNUNET_break (0);
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_kyc_requirement_for_account");
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return qs;
+ }
+ }
+ GNUNET_free (res);
+ }
qs = TEH_plugin->insert_aml_decision (TEH_plugin->cls,
&dc->h_payto,
@@ -111,6 +190,7 @@ make_aml_decision (void *cls,
dc->decision_time,
dc->justification,
dc->kyc_requirements,
+ requirement_row,
dc->officer_pub,
&dc->officer_sig,
&invalid_officer,
@@ -151,11 +231,6 @@ make_aml_decision (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR;
}
- if (NULL != dc->kyc_requirements)
- {
- // FIXME: act on these!
- }
-
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
diff --git a/src/exchange/taler-exchange-httpd_batch-withdraw.c b/src/exchange/taler-exchange-httpd_batch-withdraw.c
index e6be54a58..493a2bc70 100644
--- a/src/exchange/taler-exchange-httpd_batch-withdraw.c
+++ b/src/exchange/taler-exchange-httpd_batch-withdraw.c
@@ -210,7 +210,7 @@ batch_withdraw_transaction (void *cls,
enum GNUNET_DB_QueryStatus qs;
bool balance_ok = false;
bool found = false;
- const char *kyc_required;
+ char *kyc_required;
struct TALER_PaytoHashP reserve_h_payto;
wc->now = GNUNET_TIME_timestamp_get ();
@@ -349,11 +349,22 @@ batch_withdraw_transaction (void *cls,
{
/* insert KYC requirement into DB! */
wc->kyc.ok = false;
- return TEH_plugin->insert_kyc_requirement_for_account (
+ qs = TEH_plugin->insert_kyc_requirement_for_account (
TEH_plugin->cls,
kyc_required,
&wc->h_payto,
&wc->kyc.requirement_row);
+ GNUNET_free (kyc_required);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_kyc_requirement_for_account");
+ }
+ return qs;
}
wc->kyc.ok = true;
qs = TEH_plugin->do_batch_withdraw (TEH_plugin->cls,
diff --git a/src/exchange/taler-exchange-httpd_kyc-check.c b/src/exchange/taler-exchange-httpd_kyc-check.c
index 07b8dc661..57ac8389d 100644
--- a/src/exchange/taler-exchange-httpd_kyc-check.c
+++ b/src/exchange/taler-exchange-httpd_kyc-check.c
@@ -332,7 +332,7 @@ kyc_check (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR;
}
qs = TALER_KYCLOGIC_check_satisfied (
- requirements,
+ &requirements,
&h_payto,
&kyp->kyc_details,
TEH_plugin->select_satisfied_kyc_processes,
@@ -389,6 +389,17 @@ kyc_check (void *cls,
NULL,
NULL,
&kyp->process_row);
+ if (qs < 0)
+ {
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ return qs;
+ GNUNET_break (0);
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_kyc_requirement_process");
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Initiating KYC check with logic %s\n",
kyp->ih_logic->name);
diff --git a/src/exchange/taler-exchange-httpd_kyc-wallet.c b/src/exchange/taler-exchange-httpd_kyc-wallet.c
index e56204ef5..77f2dea78 100644
--- a/src/exchange/taler-exchange-httpd_kyc-wallet.c
+++ b/src/exchange/taler-exchange-httpd_kyc-wallet.c
@@ -237,7 +237,7 @@ TEH_handler_kyc_wallet (
NULL,
0);
}
- GNUNET_free (kyc.required);
+ GNUNET_free (krc.required);
return TEH_RESPONSE_reply_kyc_required (rc->connection,
&krc.h_payto,
&krc.kyc);
diff --git a/src/exchangedb/0003-aml_history.sql b/src/exchangedb/0003-aml_history.sql
index b411a6fb1..e57a2313f 100644
--- a/src/exchangedb/0003-aml_history.sql
+++ b/src/exchangedb/0003-aml_history.sql
@@ -33,6 +33,7 @@ BEGIN
',decision_time INT8 NOT NULL DEFAULT(0)'
',justification VARCHAR NOT NULL'
',kyc_requirements VARCHAR'
+ ',kyc_req_row INT8 NOT NULL DEFAULT(0)'
',decider_pub BYTEA CHECK (LENGTH(decider_pub)=32)'
',decider_sig BYTEA CHECK (LENGTH(decider_sig)=64)'
') %s ;'
@@ -88,6 +89,12 @@ BEGIN
,partition_suffix
);
PERFORM comment_partitioned_column(
+ 'Row in the KYC table for this KYC requirement, 0 for none.'
+ ,'kyc_req_row'
+ ,table_name
+ ,partition_suffix
+ );
+ PERFORM comment_partitioned_column(
'Signature key of the staff member affirming the AML decision; of type AML_DECISION'
,'decider_sig'
,table_name
diff --git a/src/exchangedb/exchange_do_insert_aml_decision.sql b/src/exchangedb/exchange_do_insert_aml_decision.sql
index 8e22c57f8..00f803752 100644
--- a/src/exchangedb/exchange_do_insert_aml_decision.sql
+++ b/src/exchangedb/exchange_do_insert_aml_decision.sql
@@ -25,6 +25,7 @@ CREATE OR REPLACE FUNCTION exchange_do_insert_aml_decision(
IN in_decider_sig BYTEA,
IN in_notify_s VARCHAR,
IN in_kyc_requirements VARCHAR,
+ IN in_requirement_row INT8,
OUT out_invalid_officer BOOLEAN,
OUT out_last_date INT8)
LANGUAGE plpgsql
@@ -86,6 +87,7 @@ INSERT INTO exchange.aml_history
,decision_time
,justification
,kyc_requirements
+ ,kyc_req_row
,decider_pub
,decider_sig
) VALUES
@@ -96,6 +98,7 @@ INSERT INTO exchange.aml_history
,in_decision_time
,in_justification
,in_kyc_requirements
+ ,in_requirement_row
,in_decider_pub
,in_decider_sig);
@@ -119,5 +122,5 @@ END IF;
END $$;
-COMMENT ON FUNCTION exchange_do_insert_aml_decision(BYTEA, INT8, INT4, INT4, INT8, VARCHAR, BYTEA, BYTEA, VARCHAR, VARCHAR)
+COMMENT ON FUNCTION exchange_do_insert_aml_decision(BYTEA, INT8, INT4, INT4, INT8, VARCHAR, BYTEA, BYTEA, VARCHAR, VARCHAR, INT8)
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
index 5a1b71235..62645c2a2 100644
--- a/src/exchangedb/pg_insert_aml_decision.c
+++ b/src/exchangedb/pg_insert_aml_decision.c
@@ -36,6 +36,7 @@ TEH_PG_insert_aml_decision (
struct GNUNET_TIME_Timestamp decision_time,
const char *justification,
const json_t *kyc_requirements,
+ uint64_t requirements_row,
const struct TALER_AmlOfficerPublicKeyP *decider_pub,
const struct TALER_AmlOfficerSignatureP *decider_sig,
bool *invalid_officer,
@@ -64,6 +65,7 @@ TEH_PG_insert_aml_decision (
NULL != kyc_requirements
? GNUNET_PQ_query_param_string (kyc_s)
: GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_uint64 (&requirements_row),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
@@ -81,7 +83,7 @@ TEH_PG_insert_aml_decision (
" out_invalid_officer"
",out_last_date"
" FROM exchange_do_insert_aml_decision"
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);");
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
index 4d4ca6e54..073a2f50a 100644
--- a/src/exchangedb/pg_insert_aml_decision.h
+++ b/src/exchangedb/pg_insert_aml_decision.h
@@ -37,6 +37,7 @@
* @param decision_time when was the decision made
* @param justification human-readable text justifying the decision
* @param kyc_requirements JSON array with KYC requirements
+ * @param requirements_row row in the KYC table for this process, 0 for none
* @param decider_pub public key of the staff member
* @param decider_sig signature of the staff member
* @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now
@@ -53,6 +54,7 @@ TEH_PG_insert_aml_decision (
struct GNUNET_TIME_Timestamp decision_time,
const char *justification,
const json_t *kyc_requirements,
+ uint64_t requirements_row,
const struct TALER_AmlOfficerPublicKeyP *decider_pub,
const struct TALER_AmlOfficerSignatureP *decider_sig,
bool *invalid_officer,
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index f4397e296..44dd912f8 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -6689,6 +6689,8 @@ struct TALER_EXCHANGEDB_Plugin
* @param new_status AML decision status
* @param decision_time when was the decision made
* @param justification human-readable text justifying the decision
+ * @param kyc_requirements specific KYC requiremnts being imposed
+ * @param requirements_row row in the KYC table for this process, 0 for none
* @param decider_pub public key of the staff member
* @param decider_sig signature of the staff member
* @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now
@@ -6705,6 +6707,7 @@ struct TALER_EXCHANGEDB_Plugin
struct GNUNET_TIME_Timestamp decision_time,
const char *justification,
const json_t *kyc_requirements,
+ uint64_t requirements_row,
const struct TALER_AmlOfficerPublicKeyP *decider_pub,
const struct TALER_AmlOfficerSignatureP *decider_sig,
bool *invalid_officer,
diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h
index 98233b359..34a429121 100644
--- a/src/include/taler_kyclogic_lib.h
+++ b/src/include/taler_kyclogic_lib.h
@@ -232,7 +232,8 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
* Check if the @a requirements are now satsified for
* @a h_payto account.
*
- * @param requirements space-spearated list of requirements
+ * @param[in,out] requirements space-spearated list of requirements,
+ * already satisfied requirements are removed from the list
* @param h_payto hash over the account
* @param[out] kyc_details if satisfied, set to what kind of
* KYC information was collected
@@ -242,7 +243,7 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
* @return transaction status (from @a ki)
*/
enum GNUNET_DB_QueryStatus
-TALER_KYCLOGIC_check_satisfied (const char *requirements,
+TALER_KYCLOGIC_check_satisfied (char **requirements,
const struct TALER_PaytoHashP *h_payto,
json_t **kyc_details,
TALER_KYCLOGIC_KycSatisfiedIterator ki,
diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c
index e1aff0204..9f35743cd 100644
--- a/src/kyclogic/kyclogic_api.c
+++ b/src/kyclogic/kyclogic_api.c
@@ -1228,7 +1228,7 @@ TALER_KYCLOGIC_kyc_get_details (
enum GNUNET_DB_QueryStatus
-TALER_KYCLOGIC_check_satisfied (const char *requirements,
+TALER_KYCLOGIC_check_satisfied (char **requirements,
const struct TALER_PaytoHashP *h_payto,
json_t **kyc_details,
TALER_KYCLOGIC_KycSatisfiedIterator ki,
@@ -1244,13 +1244,14 @@ TALER_KYCLOGIC_check_satisfied (const char *requirements,
return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
{
- char *req = GNUNET_strdup (requirements);
+ char *req = *requirements;
for (const char *tok = strtok (req, " ");
NULL != tok;
tok = strtok (NULL, " "))
needed[needed_cnt++] = add_check (tok);
GNUNET_free (req);
+ *requirements = NULL;
}
{
@@ -1286,6 +1287,32 @@ TALER_KYCLOGIC_check_satisfied (const char *requirements,
}
}
*satisfied = (0 == needed_cnt);
+
+ {
+ char *res = NULL;
+
+ for (unsigned int i = 0; i<needed_cnt; i++)
+ {
+ const struct TALER_KYCLOGIC_KycCheck *need = needed[i];
+
+ if (NULL == res)
+ {
+ res = GNUNET_strdup (need->name);
+ }
+ else
+ {
+ char *tmp;
+
+ GNUNET_asprintf (&tmp,
+ "%s %s",
+ res,
+ need->name);
+ GNUNET_free (res);
+ res = tmp;
+ }
+ }
+ *requirements = res;
+ }
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}