diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-09-08 09:36:58 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-09-08 09:36:58 +0200 |
commit | 409fc3fea7a33e4efe66321c79b6531d44bd6571 (patch) | |
tree | 62c6ccc9e82dbc5750e15f77b29d17c09c961a52 | |
parent | bc44dc29c3ebc2ea7363187dd65f9032ac324c28 (diff) |
clean up and complete taler-merchant-kyccheck logic
-rw-r--r-- | src/backend/taler-merchant-kyccheck.c | 237 |
1 files changed, 129 insertions, 108 deletions
diff --git a/src/backend/taler-merchant-kyccheck.c b/src/backend/taler-merchant-kyccheck.c index dfb2be53..bfa22451 100644 --- a/src/backend/taler-merchant-kyccheck.c +++ b/src/backend/taler-merchant-kyccheck.c @@ -400,22 +400,20 @@ pack_limit (const struct TALER_EXCHANGE_AccountLimit *limit, /** - * Store KYC response from the exchange in the - * local database. + * Update KYC status for @a i based on + * @a account_kyc_status * * @param[in,out] i inquiry context, jlimits is updated - * @param ks HTTP response details * @param account_kyc_status account KYC status details */ static void store_kyc_status ( struct Inquiry *i, - const struct TALER_EXCHANGE_KycStatus *ks, const struct TALER_EXCHANGE_AccountKycStatus *account_kyc_status) { - enum GNUNET_DB_QueryStatus qs; json_t *jlimits; + json_decref (i->jlimits); jlimits = json_array (); GNUNET_assert (NULL != jlimits); for (unsigned int j = 0; j<account_kyc_status->limits_length; j++) @@ -426,29 +424,10 @@ store_kyc_status ( pack_limit (limit, jlimits); } - json_decref (i->jlimits); i->jlimits = jlimits; - // FIXME: update more of i? - - qs = db_plugin->account_kyc_set_status ( - db_plugin->cls, - i->a->instance_id, - &i->a->h_wire, - i->e->keys->exchange_url, - GNUNET_TIME_timestamp_get (), - ks->hr.http_status, - ks->hr.ec, - &account_kyc_status->access_token, - jlimits, - account_kyc_status->aml_review, - MHD_HTTP_OK == ks->hr.http_status); - if (qs < 0) - { - GNUNET_break (0); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } + i->access_token = account_kyc_status->access_token; + i->aml_review = account_kyc_status->aml_review; + i->kyc_ok = (MHD_HTTP_OK == i->last_http_status); } @@ -466,6 +445,8 @@ exchange_check_cb ( struct Inquiry *i = cls; i->kyc = NULL; + i->last_http_status = ks->hr.http_status; + i->last_ec = ks->hr.ec; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Checking KYC status of `%s' at `%s' is %u\n", i->a->merchant_account_uri, @@ -474,100 +455,109 @@ exchange_check_cb ( switch (ks->hr.http_status) { case MHD_HTTP_OK: + i->last_kyc_check = GNUNET_TIME_timestamp_get (); + /* exchange says KYC is OK, gives status information */ store_kyc_status (i, - ks, &ks->details.ok); + i->backoff = GNUNET_TIME_UNIT_ZERO; + /* KYC is OK, only check again if triggered */ + i->due = GNUNET_TIME_UNIT_FOREVER_ABS; break; case MHD_HTTP_ACCEPTED: + i->last_kyc_check = GNUNET_TIME_timestamp_get (); + /* exchange says KYC is required */ store_kyc_status (i, - ks, &ks->details.accepted); + i->backoff = GNUNET_TIME_UNIT_ZERO; + /* Start immediately with long-polling */ + i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time, + i->timeout); break; case MHD_HTTP_NO_CONTENT: - { - enum GNUNET_DB_QueryStatus qs; - - // FIXME: update i? - qs = db_plugin->account_kyc_set_status ( - db_plugin->cls, - i->a->instance_id, - &i->a->h_wire, - i->e->keys->exchange_url, - GNUNET_TIME_timestamp_get (), - MHD_HTTP_NO_CONTENT, - TALER_EC_NONE, - NULL, - NULL, - false, - true); - if (qs < 0) - { - GNUNET_break (0); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - } + i->last_kyc_check = GNUNET_TIME_timestamp_get (); + i->backoff = GNUNET_TIME_UNIT_ZERO; + /* exchange claims KYC is off! */ + i->kyc_ok = true; + i->aml_review = false; + /* Clear limits, in case exchange had KYC on previously */ + json_decref (i->jlimits); + i->jlimits = NULL; + /* KYC is OK, only check again if triggered */ + i->due = GNUNET_TIME_UNIT_FOREVER_ABS; break; case MHD_HTTP_FORBIDDEN: /* bad signature */ + i->last_kyc_check = GNUNET_TIME_timestamp_get (); + /* Forbidden => KYC auth must be wrong */ + i->auth_ok = false; + /* Start with long-polling */ + i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time, + i->timeout); + i->backoff = GNUNET_TIME_UNIT_ZERO; + break; case MHD_HTTP_NOT_FOUND: /* account unknown */ + i->last_kyc_check = GNUNET_TIME_timestamp_get (); + /* Account unknown => no KYC auth yet */ + i->auth_ok = false; + /* unknown account => no requirements! */ + i->kyc_ok = true; + /* There should not be any limits yet, but clear them + just in case the exchange has amnesia */ + json_decref (i->jlimits); + i->jlimits = NULL; + /* Start immediately with Long-polling */ + i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time, + i->timeout); + i->backoff = GNUNET_TIME_UNIT_ZERO; + break; case MHD_HTTP_CONFLICT: /* no account_pub known */ - { - enum GNUNET_DB_QueryStatus qs; - - // FIXME: update i? - qs = db_plugin->account_kyc_set_status ( - db_plugin->cls, - i->a->instance_id, - &i->a->h_wire, - i->e->keys->exchange_url, - GNUNET_TIME_timestamp_get (), - ks->hr.http_status, - ks->hr.ec, - NULL, - NULL, - false, - true); - if (qs < 0) - { - GNUNET_break (0); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - } + i->last_kyc_check = GNUNET_TIME_timestamp_get (); + /* Conflict => KYC auth wire transfer missing! */ + i->auth_ok = false; + /* Start immediately with Long-polling */ + i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time, + i->timeout); + i->backoff = GNUNET_TIME_UNIT_ZERO; break; default: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Exchange responded with HTTP status %u (%d) to /kyc-check request!\n", + ks->hr.http_status, + ks->hr.ec); + i->backoff + = GNUNET_TIME_randomized_backoff (i->backoff, + EXCHANGE_TIMEOUT); + i->last_kyc_check = GNUNET_TIME_timestamp_get (); + i->due = GNUNET_TIME_relative_to_absolute (i->backoff); + break; + } + + { + enum GNUNET_DB_QueryStatus qs; + + qs = db_plugin->account_kyc_set_status ( + db_plugin->cls, + i->a->instance_id, + &i->a->h_wire, + i->e->keys->exchange_url, + i->last_kyc_check, + i->last_http_status, + i->last_ec, + &i->access_token, + i->jlimits, + i->aml_review, + i->kyc_ok); + if (qs < 0) { - enum GNUNET_DB_QueryStatus qs; - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Exchange responded with HTTP status %u (%d) to /kyc-check request!\n", - ks->hr.http_status, - ks->hr.ec); - // FIXME: update i? - qs = db_plugin->account_kyc_set_status ( - db_plugin->cls, - i->a->instance_id, - &i->a->h_wire, - i->e->keys->exchange_url, - GNUNET_TIME_timestamp_get (), - ks->hr.http_status, - ks->hr.ec, - NULL /* access token */, - NULL /* jlimits */, - false /* in_aml_review? well, unknown... */, - true /* kyc_ok? well, unknown... */); - if (qs < 0) - { - GNUNET_break (0); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - break; + GNUNET_break (0); + global_ret = EXIT_FAILURE; + GNUNET_SCHEDULER_shutdown (); + return; } } + if (! GNUNET_TIME_absolute_is_never (i->due)) + i->task = GNUNET_SCHEDULER_add_at (i->due, + &inquiry_work, + i); end_inquiry (); } @@ -578,9 +568,14 @@ inquiry_work (void *cls) struct Inquiry *i = cls; i->task = NULL; - // FIXME: update i->due, i->timeout, i->backoff if (! GNUNET_TIME_absolute_is_past (i->due)) + { + i->task + = GNUNET_SCHEDULER_add_at (i->due, + &inquiry_work, + i); goto finish; + } GNUNET_assert (OPEN_INQUIRY_LIMIT >= active_inquiries); if (OPEN_INQUIRY_LIMIT <= active_inquiries) @@ -592,24 +587,26 @@ inquiry_work (void *cls) return; } at_limit = false; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Checking KYC status of `%s' at `%s'\n", i->a->merchant_account_uri, i->e->keys->exchange_url); + i->timeout + = GNUNET_TIME_relative_to_absolute (EXCHANGE_TIMEOUT); i->kyc = TALER_EXCHANGE_kyc_check ( ctx, i->e->keys->exchange_url, &i->a->h_payto, &i->a->ap, - GNUNET_TIME_absolute_get_remaining (i->timeout), + EXCHANGE_TIMEOUT, &exchange_check_cb, i); if (NULL == i->kyc) { GNUNET_break (0); + i->due = i->timeout; i->task - = GNUNET_SCHEDULER_add_at (i->timeout, + = GNUNET_SCHEDULER_add_at (i->due, &inquiry_work, i); goto finish; @@ -739,6 +736,30 @@ start_inquiry (struct Exchange *e, GNUNET_SCHEDULER_shutdown (); return; } + switch (i->last_http_status) + { + case MHD_HTTP_OK: + /* KYC is OK, only check again if triggered */ + i->due = GNUNET_TIME_UNIT_FOREVER_ABS; + break; + case MHD_HTTP_ACCEPTED: + /* KYC required, due immediately */ + break; + case MHD_HTTP_NO_CONTENT: + /* KYC is OFF, only check again if triggered */ + i->due = GNUNET_TIME_UNIT_FOREVER_ABS; + break; + case MHD_HTTP_FORBIDDEN: /* bad signature */ + case MHD_HTTP_NOT_FOUND: /* account unknown */ + case MHD_HTTP_CONFLICT: /* no account_pub known */ + /* go immediately into long-polling */ + break; + default: + /* start with decent back-off after hard failure */ + i->backoff + = GNUNET_TIME_randomize (GNUNET_TIME_UNIT_MINUTES); + break; + } inquiry_work (i); } |