avoid duplication

This commit is contained in:
Christian Grothoff 2021-11-15 14:39:18 +01:00
parent c67df63699
commit 0325a79631
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
5 changed files with 204 additions and 90 deletions

@ -1 +1 @@
Subproject commit 15a8cae393bf35f95ae15836c4ec4b2b22e42604
Subproject commit 597e273cc73122ba5cd0023f37b43b4f3784fe0c

View File

@ -27,6 +27,7 @@
#include "taler_json_lib.h"
#include "taler_mhd_lib.h"
#include "taler_signatures.h"
#include "taler_dbevents.h"
#include "taler-exchange-httpd_keys.h"
#include "taler-exchange-httpd_kyc-wallet.h"
#include "taler-exchange-httpd_responses.h"
@ -187,6 +188,42 @@ kyc_check (void *cls,
}
/**
* Function called on events received from Postgres.
* Wakes up long pollers.
*
* @param cls the `struct TEH_RequestContext *`
* @param extra additional event data provided
* @param extra_size number of bytes in @a extra
*/
static void
db_event_cb (void *cls,
const void *extra,
size_t extra_size)
{
struct TEH_RequestContext *rc = cls;
struct KycPoller *kyp = rc->rh_ctx;
struct GNUNET_AsyncScopeSave old_scope;
(void) extra;
(void) extra_size;
if (! kyp->suspended)
return; /* event triggered while main transaction
was still running, or got multiple wake-up events */
kyp->suspended = false;
GNUNET_async_scope_enter (&rc->async_scope_id,
&old_scope);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Resuming from long-polling on KYC status\n");
GNUNET_CONTAINER_DLL_remove (kyp_head,
kyp_tail,
kyp);
MHD_resume_connection (kyp->connection);
TALER_MHD_daemon_trigger ();
GNUNET_async_scope_restore (&old_scope);
}
MHD_RESULT
TEH_handler_kyc_check (
struct TEH_RequestContext *rc,
@ -195,6 +232,7 @@ TEH_handler_kyc_check (
struct KycPoller *kyp = rc->rh_ctx;
MHD_RESULT res;
enum GNUNET_GenericReturnValue ret;
struct GNUNET_TIME_Absolute now;
if (NULL == kyp)
{
@ -285,87 +323,120 @@ TEH_handler_kyc_check (
NULL,
NULL,
0);
if ( (NULL == kyp->eh) &&
GNUNET_TIME_absolute_is_future (kyp->timeout) )
{
struct GNUNET_TIME_Absolute now;
struct TALER_KycCompletedEventP rep = {
.header.size = htons (sizeof (rep)),
.header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
.h_payto = kyp->auth_h_payto
};
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
ret = TEH_DB_run_transaction (rc->connection,
"kyc check",
&res,
&kyc_check,
kyp);
if (GNUNET_SYSERR == ret)
return res;
if (0 !=
GNUNET_memcmp (&kyp->h_payto,
&kyp->auth_h_payto))
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Starting DB event listening\n");
kyp->eh = TEH_plugin->event_listen (
TEH_plugin->cls,
GNUNET_TIME_absolute_get_remaining (kyp->timeout),
&rep.header,
&db_event_cb,
rc);
}
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
ret = TEH_DB_run_transaction (rc->connection,
"kyc check",
&res,
&kyc_check,
kyp);
if (GNUNET_SYSERR == ret)
return res;
if (0 !=
GNUNET_memcmp (&kyp->h_payto,
&kyp->auth_h_payto))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_UNAUTHORIZED,
TALER_EC_EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED,
"h_payto");
}
/* long polling? */
if ( (! kyp->kyc.ok) &&
GNUNET_TIME_absolute_is_future (kyp->timeout))
{
GNUNET_assert (NULL != kyp->eh);
kyp->suspended = true;
GNUNET_CONTAINER_DLL_insert (kyp_head,
kyp_tail,
kyp);
MHD_suspend_connection (kyp->connection);
return MHD_YES;
}
/* KYC failed? */
if (! kyp->kyc.ok)
{
char *url;
char *redirect_uri;
char *redirect_uri_encoded;
GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
GNUNET_asprintf (&redirect_uri,
"%s/kyc-proof/%llu",
TEH_base_url,
(unsigned long long) kyp->payment_target_uuid);
redirect_uri_encoded = TALER_urlencode (redirect_uri);
GNUNET_free (redirect_uri);
GNUNET_asprintf (&url,
"%s/login?client_id=%s&redirect_uri=%s",
TEH_kyc_config.details.oauth2.url,
TEH_kyc_config.details.oauth2.client_id,
redirect_uri_encoded);
GNUNET_free (redirect_uri_encoded);
res = TALER_MHD_REPLY_JSON_PACK (
rc->connection,
MHD_HTTP_ACCEPTED,
GNUNET_JSON_pack_string ("kyc_url",
url));
GNUNET_free (url);
return res;
}
/* KYC succeeded! */
{
struct TALER_ExchangePublicKeyP pub;
struct TALER_ExchangeSignatureP sig;
struct TALER_ExchangeAccountSetupSuccessPS as = {
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
.purpose.size = htonl (sizeof (as)),
.h_payto = kyp->h_payto,
.timestamp = GNUNET_TIME_absolute_hton (now)
};
enum TALER_ErrorCode ec;
if (TALER_EC_NONE !=
(ec = TEH_keys_exchange_sign (&as,
&pub,
&sig)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_UNAUTHORIZED,
TALER_EC_EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED,
"h_payto");
}
if (! kyp->kyc.ok)
{
char *url;
char *redirect_uri;
char *redirect_uri_encoded;
GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
GNUNET_asprintf (&redirect_uri,
"%s/kyc-proof/%llu",
TEH_base_url,
(unsigned long long) kyp->payment_target_uuid);
redirect_uri_encoded = TALER_urlencode (redirect_uri);
GNUNET_free (redirect_uri);
GNUNET_asprintf (&url,
"%s/login?client_id=%s&redirect_uri=%s",
TEH_kyc_config.details.oauth2.url,
TEH_kyc_config.details.oauth2.client_id,
redirect_uri_encoded);
GNUNET_free (redirect_uri_encoded);
res = TALER_MHD_REPLY_JSON_PACK (
rc->connection,
MHD_HTTP_ACCEPTED,
GNUNET_JSON_pack_string ("kyc_url",
url));
GNUNET_free (url);
return res;
}
{
struct TALER_ExchangePublicKeyP pub;
struct TALER_ExchangeSignatureP sig;
struct TALER_ExchangeAccountSetupSuccessPS as = {
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
.purpose.size = htonl (sizeof (as)),
.h_payto = kyp->h_payto,
.timestamp = GNUNET_TIME_absolute_hton (now)
};
enum TALER_ErrorCode ec;
if (TALER_EC_NONE !=
(ec = TEH_keys_exchange_sign (&as,
&pub,
&sig)))
{
return TALER_MHD_reply_with_ec (rc->connection,
ec,
NULL);
}
return TALER_MHD_REPLY_JSON_PACK (
rc->connection,
MHD_HTTP_OK,
GNUNET_JSON_pack_data_auto ("exchange_sig",
&sig),
GNUNET_JSON_pack_data_auto ("exchange_pub",
&pub),
GNUNET_JSON_pack_time_abs ("now",
now));
return TALER_MHD_reply_with_ec (rc->connection,
ec,
NULL);
}
return TALER_MHD_REPLY_JSON_PACK (
rc->connection,
MHD_HTTP_OK,
GNUNET_JSON_pack_data_auto ("exchange_sig",
&sig),
GNUNET_JSON_pack_data_auto ("exchange_pub",
&pub),
GNUNET_JSON_pack_time_abs ("now",
now));
}
}

View File

@ -385,6 +385,14 @@ prepare_statements (struct PostgresClosure *pg)
" SET kyc_ok=TRUE"
" WHERE wire_target_serial_id=$1",
1),
GNUNET_PQ_make_prepare (
"get_kyc_h_payto",
"SELECT"
" h_payto"
" FROM wire_targets"
" WHERE wire_target_serial_id=$1"
" LIMIT 1;",
1),
/* Used in #postgres_get_kyc_status() */
GNUNET_PQ_make_prepare (
"get_kyc_status",
@ -3804,10 +3812,33 @@ postgres_set_kyc_ok (void *cls,
GNUNET_PQ_query_param_uint64 (&payment_target_uuid),
GNUNET_PQ_query_param_end
};
struct TALER_KycCompletedEventP rep = {
.header.size = htons (sizeof (rep)),
.header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED)
};
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("h_payto",
&rep.h_payto),
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"set_kyc_ok",
params);
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
"set_kyc_ok",
params);
if (qs <= 0)
return qs;
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"get_kyc_h_payto",
params,
rs);
if (qs <= 0)
return qs;
postgres_event_notify (pg,
&rep.header,
NULL,
0);
return qs;
}
@ -5684,9 +5715,10 @@ postgres_ensure_coin_known (void *cls,
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
case GNUNET_DB_STATUS_SOFT_ERROR:
GNUNET_break (0);
return TALER_EXCHANGEDB_CKS_HARD_FAIL;
case GNUNET_DB_STATUS_SOFT_ERROR:
return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
GNUNET_break (0);
return TALER_EXCHANGEDB_CKS_HARD_FAIL;

View File

@ -323,12 +323,6 @@ struct TALER_CoinSpendPublicKeyP
*/
struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub;
/*
* If age restriction applies to the coin, it must come with a hash of the
* age commitment. A zero value indicates that the coin has no age
* commitment set.
*/
struct TALER_AgeHash age_commitment_hash;
};

View File

@ -74,7 +74,7 @@ struct TALER_EXCHANGEDB_DenominationKeyInformationP
/**
* Signature of events signalling a reseve got funding.
* Signature of events signalling a reserve got funding.
*/
struct TALER_ReserveEventP
{
@ -90,6 +90,23 @@ struct TALER_ReserveEventP
};
/**
* Signature of events signalling a KYC process was completed.
*/
struct TALER_KycCompletedEventP
{
/**
* Of type #TALER_DBEVENT_EXCHANGE_KYC_COMPLETED.
*/
struct GNUNET_DB_EventHeaderP header;
/**
* Public key of the reserve the event is about.
*/
struct TALER_PaytoHash h_payto;
};
GNUNET_NETWORK_STRUCT_END
/**