summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-10-15 23:34:23 +0200
committerChristian Grothoff <christian@grothoff.org>2021-10-15 23:34:23 +0200
commita48db85013a942d71ecdf98740a469468eb9882f (patch)
tree084e0e80ec32d6101d5cfc13c630bd25326a484e /src
parentca12adced4ab5a54d7ee25b40b49cd034b920cc8 (diff)
downloadexchange-a48db85013a942d71ecdf98740a469468eb9882f.tar.gz
exchange-a48db85013a942d71ecdf98740a469468eb9882f.tar.bz2
exchange-a48db85013a942d71ecdf98740a469468eb9882f.zip
add KYC logic for /deposit handling (DB part incomplete)
Diffstat (limited to 'src')
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c59
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c56
-rw-r--r--src/include/taler_exchangedb_plugin.h14
3 files changed, 121 insertions, 8 deletions
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 9c4cfdc7e..7148b93fc 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2020 Taler Systems SA
+ Copyright (C) 2014-2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -45,6 +45,7 @@
* operation with the given wiring details.
*
* @param connection connection to the client
+ * @param kyc KYC status for the credited account
* @param coin_pub public key of the coin
* @param h_wire hash of wire details
* @param h_contract_terms hash of contract details
@@ -56,6 +57,7 @@
*/
static MHD_RESULT
reply_deposit_success (struct MHD_Connection *connection,
+ const struct TALER_EXCHANGEDB_KycStatus *kyc,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct GNUNET_HashCode *h_wire,
const struct GNUNET_HashCode *h_contract_terms,
@@ -92,6 +94,10 @@ reply_deposit_success (struct MHD_Connection *connection,
return TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_OK,
+ GNUNET_JSON_pack_uint64 ("payment_target_uuid",
+ kyc->payment_target_uuid),
+ GNUNET_JSON_pack_bool ("kyc_ok",
+ kyc->ok),
GNUNET_JSON_pack_time_abs ("exchange_timestamp",
exchange_timestamp),
GNUNET_JSON_pack_data_auto ("exchange_sig",
@@ -121,6 +127,15 @@ struct DepositContext
*/
struct TALER_Amount value;
+ /**
+ * KYC status for the receiving account.
+ */
+ struct TALER_EXCHANGEDB_KycStatus kyc;
+
+ /**
+ * payto:// URI of the credited account.
+ */
+ char *payto_uri;
};
@@ -146,6 +161,21 @@ deposit_precheck (void *cls,
struct TALER_Amount deposit_fee;
enum GNUNET_DB_QueryStatus qs;
+ qs = TEH_plugin->get_kyc_status (TEH_plugin->cls,
+ dc->payto_uri,
+ &dc->kyc);
+ if (qs < 0)
+ {
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ {
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "get_kyc_status");
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return qs;
+ }
qs = TEH_plugin->have_deposit (TEH_plugin->cls,
deposit,
GNUNET_YES /* check refund deadline */,
@@ -158,7 +188,7 @@ deposit_precheck (void *cls,
*mhd_ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
+ "have_deposit");
return GNUNET_DB_STATUS_HARD_ERROR;
}
return qs;
@@ -174,6 +204,7 @@ deposit_precheck (void *cls,
&deposit->amount_with_fee,
&deposit_fee));
*mhd_ret = reply_deposit_success (connection,
+ &dc->kyc,
&deposit->coin.coin_pub,
&deposit->h_wire,
&deposit->h_contract_terms,
@@ -218,7 +249,6 @@ deposit_transaction (void *cls,
mhd_ret);
if (qs < 0)
return qs;
-
/* Theoretically, someone other threat may have received
and committed the deposit in the meantime. Check now
that we are in the transaction scope. */
@@ -369,11 +399,10 @@ TEH_handler_deposit (struct MHD_Connection *connection,
}
/* validate merchant's wire details (as far as we can) */
{
- char *payto;
char *emsg;
- payto = TALER_JSON_wire_to_payto (wire);
- if (NULL == payto)
+ dc.payto_uri = TALER_JSON_wire_to_payto (wire);
+ if (NULL == dc.payto_uri)
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@@ -382,8 +411,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"wire");
}
- emsg = TALER_payto_validate (payto);
- GNUNET_free (payto);
+ emsg = TALER_payto_validate (dc.payto_uri);
if (NULL != emsg)
{
MHD_RESULT ret;
@@ -395,6 +423,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
emsg);
GNUNET_free (emsg);
+ GNUNET_free (dc.payto_uri);
return ret;
}
}
@@ -403,6 +432,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE,
@@ -415,6 +445,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
TALER_LOG_WARNING (
"Failed to parse JSON wire format specification for /deposit request\n");
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_JSON,
@@ -425,6 +456,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
{
/* Client hashed wire details differently than we did, reject */
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT,
@@ -444,6 +476,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&dc))
{
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return mhd_ret;
}
}
@@ -462,6 +495,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
if (NULL == dk)
{
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return mret;
}
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit))
@@ -472,6 +506,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection,
&deposit.coin.denom_pub_hash,
@@ -487,6 +522,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection,
&deposit.coin.denom_pub_hash,
@@ -502,6 +538,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
(void) GNUNET_TIME_round_abs (&now);
/* This denomination has been revoked */
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection,
&deposit.coin.denom_pub_hash,
@@ -518,6 +555,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
{
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_UNAUTHORIZED,
TALER_EC_EXCHANGE_DENOMINATION_SIGNATURE_INVALID,
@@ -530,6 +568,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE,
@@ -562,6 +601,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
{
TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_UNAUTHORIZED,
TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID,
@@ -581,9 +621,11 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&dc))
{
GNUNET_JSON_parse_free (spec);
+ GNUNET_free (dc.payto_uri);
return mhd_ret;
}
}
+ GNUNET_free (dc.payto_uri);
/* generate regular response */
{
@@ -595,6 +637,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&deposit.amount_with_fee,
&deposit.deposit_fee));
res = reply_deposit_success (connection,
+ &dc.kyc,
&deposit.coin.coin_pub,
&deposit.h_wire,
&deposit.h_contract_terms,
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index eda6468ba..dfd7432e3 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -359,6 +359,17 @@ prepare_statements (struct PostgresClosure *pg)
" WHERE reserve_pub=$1"
" LIMIT 1;",
1),
+#if FIXME_DD23
+ /* Used in #postgres_get_kyc_status() */
+ GNUNET_PQ_make_prepare ("get_kyc_status",
+ "SELECT"
+ ",kyc_ok"
+ ",wire_target_serial_id AS payment_target_uuid"
+ " FROM wire_targets"
+ " WHERE payto_uri=$1"
+ " LIMIT 1;",
+ 1),
+#endif
/* Used in #reserves_get() */
GNUNET_PQ_make_prepare ("reserves_get",
"SELECT"
@@ -3517,6 +3528,50 @@ postgres_reserves_get (void *cls,
/**
+ * Get the KYC status for a bank account.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param payto_uri payto:// URI that identifies the bank account
+ * @param[out] kyc set to the KYC status of the reserve
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_get_kyc_status (void *cls,
+ const char *payto_uri,
+ struct TALER_EXCHANGEDB_KycStatus *kyc)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (payto_uri),
+ GNUNET_PQ_query_param_end
+ };
+ uint8_t ok8;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("payment_target_uuid",
+ &kyc->payment_target_uuid),
+ GNUNET_PQ_result_spec_auto_from_type ("kyc_ok",
+ &ok8),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+#if FIXME_DD23
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_kyc_status",
+ params,
+ rs);
+#else
+ qs = 1;
+ ok8 = 0;
+ kyc->payment_target_uuid = 0;
+#endif
+ kyc->type = TALER_EXCHANGEDB_KYC_DEPOSIT;
+ kyc->ok = (0 != ok8);
+ return qs;
+}
+
+
+/**
* Get the summary of a reserve.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
@@ -11071,6 +11126,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
plugin->iterate_auditor_denominations =
&postgres_iterate_auditor_denominations;
plugin->reserves_get = &postgres_reserves_get;
+ plugin->get_kyc_status = &postgres_get_kyc_status;
plugin->reserves_in_insert = &postgres_reserves_in_insert;
plugin->get_latest_reserve_in_reference =
&postgres_get_latest_reserve_in_reference;
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 34196aadd..17d78217d 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -2377,6 +2377,20 @@ struct TALER_EXCHANGEDB_Plugin
/**
+ * Get the KYC status for a bank account.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param payto_uri payto:// URI that identifies the bank account
+ * @param[out] kyc set to the KYC status of the reserve
+ * @return transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*get_kyc_status)(void *cls,
+ const char *payto_uri,
+ struct TALER_EXCHANGEDB_KycStatus *kyc);
+
+
+ /**
* Insert a incoming transaction into reserves. New reserves are
* also created through this function.
*