aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-11-07 21:00:56 +0100
committerFlorian Dold <florian@dold.me>2024-11-07 21:00:56 +0100
commitf10bc444579a5af215a8ac38c5d0e627786e423e (patch)
tree20293656774fcef9a3e72cf7694597c54f36dcaf
parent8dc83c0c3e783bd96de51858bf934ebc74797e2c (diff)
kyclogic: make TEH_kyc_finished useable without MHD response
-rw-r--r--src/exchange/taler-exchange-httpd_aml-decision.c36
-rw-r--r--src/exchange/taler-exchange-httpd_common_kyc.c105
-rw-r--r--src/exchange/taler-exchange-httpd_common_kyc.h12
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-info.c94
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-proof.c187
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-upload.c34
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-webhook.c82
7 files changed, 289 insertions, 261 deletions
diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c b/src/exchange/taler-exchange-httpd_aml-decision.c
index 78056b28f..e73302dea 100644
--- a/src/exchange/taler-exchange-httpd_aml-decision.c
+++ b/src/exchange/taler-exchange-httpd_aml-decision.c
@@ -126,22 +126,37 @@ aml_decision_cleaner (struct TEH_RequestContext *rc)
* Function called after the KYC-AML trigger is done.
*
* @param cls closure
- * @param http_status final HTTP status to return
- * @param[in] response final HTTP ro return
+ * @param ec error code or 0 on success
+ * @param detail error message or NULL on success / no info
*/
static void
aml_trigger_callback (
void *cls,
- unsigned int http_status,
- struct MHD_Response *response)
+ enum TALER_ErrorCode ec,
+ const char *detail)
{
struct AmlDecisionContext *adc = cls;
adc->kat = NULL;
GNUNET_assert (NULL == adc->response);
- GNUNET_assert (NULL != response);
- adc->response_code = http_status;
- adc->response = response;
+
+ if (TALER_EC_NONE != ec)
+ {
+ adc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ adc->response = TALER_MHD_make_error (
+ ec,
+ detail);
+ }
+ else
+ {
+ adc->response_code = MHD_HTTP_NO_CONTENT;
+ adc->response = MHD_create_response_from_buffer_static (
+ 0,
+ "");
+ }
+
+ GNUNET_assert (NULL != adc->response);
+
MHD_resume_connection (adc->rc->connection);
GNUNET_CONTAINER_DLL_remove (adc_head,
adc_tail,
@@ -384,7 +399,6 @@ TEH_handler_post_aml_decision (
/* Run instant measure if necessary */
{
const struct TALER_KYCLOGIC_Measure *instant_ms = NULL;
- struct MHD_Response *empty_response;
enum GNUNET_DB_QueryStatus qs;
if (NULL != new_measures)
@@ -405,10 +419,6 @@ TEH_handler_post_aml_decision (
"Running instant measure after AML decision\n");
GNUNET_assert (NULL != attributes);
- empty_response
- = MHD_create_response_from_buffer_static (0,
- "");
- GNUNET_assert (NULL != empty_response);
qs = TEH_plugin->insert_kyc_requirement_process (
TEH_plugin->cls,
@@ -441,8 +451,6 @@ TEH_handler_post_aml_decision (
NULL,
GNUNET_TIME_UNIT_FOREVER_ABS,
attributes,
- MHD_HTTP_NO_CONTENT, /* http status */
- empty_response, /* MHD_Response */
&aml_trigger_callback,
adc);
json_decref (attributes);
diff --git a/src/exchange/taler-exchange-httpd_common_kyc.c b/src/exchange/taler-exchange-httpd_common_kyc.c
index 95466781f..7546c3fb7 100644
--- a/src/exchange/taler-exchange-httpd_common_kyc.c
+++ b/src/exchange/taler-exchange-httpd_common_kyc.c
@@ -124,21 +124,11 @@ struct TEH_KycAmlTrigger
uint32_t measure_index;
/**
- * response to return to the HTTP client
- */
- struct MHD_Response *response;
-
- /**
* Handle to an external process that evaluates the
* need to run AML on the account.
*/
struct TALER_KYCLOGIC_AmlProgramRunnerHandle *kyc_aml;
- /**
- * HTTP status code of @e response
- */
- unsigned int http_status;
-
};
@@ -167,18 +157,14 @@ fallback_result_cb (void *cls,
if (result)
{
kat->cb (kat->cb_cls,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE,
- NULL));
+ TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE,
+ NULL);
}
else
{
kat->cb (kat->cb_cls,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_MHD_make_error (
- TALER_EC_EXCHANGE_GENERIC_KYC_FALLBACK_FAILED,
- kat->fallback_name));
+ TALER_EC_EXCHANGE_GENERIC_KYC_FALLBACK_FAILED,
+ kat->fallback_name);
}
TEH_kyc_finished_cancel (kat);
GNUNET_async_scope_restore (&old_scope);
@@ -220,10 +206,8 @@ kyc_aml_finished (
/* double-bad: error during error handling */
GNUNET_break (0);
kat->cb (kat->cb_cls,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_MHD_make_error (
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "insert_kyc_failure"));
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_kyc_failure");
TEH_kyc_finished_cancel (kat);
GNUNET_async_scope_restore (&old_scope);
return;
@@ -233,10 +217,8 @@ kyc_aml_finished (
/* Not sure this can happen (fallback required?),
but report AML program failure to client */
kat->cb (kat->cb_cls,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE,
- NULL));
+ TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE,
+ NULL);
TEH_kyc_finished_cancel (kat);
GNUNET_async_scope_restore (&old_scope);
return;
@@ -259,10 +241,8 @@ kyc_aml_finished (
{
GNUNET_break (0);
kat->cb (kat->cb_cls,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_MHD_make_error (
- TALER_EC_EXCHANGE_GENERIC_KYC_FALLBACK_UNKNOWN,
- kat->fallback_name));
+ TALER_EC_EXCHANGE_GENERIC_KYC_FALLBACK_UNKNOWN,
+ kat->fallback_name);
TEH_kyc_finished_cancel (kat);
GNUNET_async_scope_restore (&old_scope);
return;
@@ -290,13 +270,10 @@ kyc_aml_finished (
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to parse birthdate `%s' from KYC attributes\n",
birthdate);
- if (NULL != kat->response)
- MHD_destroy_response (kat->response);
- kat->http_status = MHD_HTTP_BAD_REQUEST;
- kat->response = TALER_MHD_make_error (
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- TALER_ATTRIBUTE_BIRTHDATE);
- goto RETURN_RESULT;
+ kat->cb (kat->cb_cls,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "TALER_ATTRIBUTE_BIRTHDATE");
+ goto done;
}
}
}
@@ -330,22 +307,19 @@ kyc_aml_finished (
if (qs < 0)
{
GNUNET_break (0);
- if (NULL != kat->response)
- MHD_destroy_response (kat->response);
- kat->http_status
- = MHD_HTTP_INTERNAL_SERVER_ERROR;
- kat->response
- = TALER_MHD_make_error (
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "do_insert_kyc_measure_result");
- /* Continued below to return the response */
+ kat->cb (kat->cb_cls,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "do_insert_kyc_measure_result");
+ /* Continued below to clean up. */
}
-RETURN_RESULT:
- /* Finally, return result to main handler */
- kat->cb (kat->cb_cls,
- kat->http_status,
- kat->response);
- kat->response = NULL;
+ else
+ {
+ /* Finally, return result to main handler */
+ kat->cb (kat->cb_cls,
+ TALER_EC_NONE,
+ 0);
+ }
+done:
TEH_kyc_finished_cancel (kat);
GNUNET_async_scope_restore (&old_scope);
}
@@ -493,8 +467,6 @@ TEH_kyc_finished (
const char *provider_legitimization_id,
struct GNUNET_TIME_Absolute expiration,
const json_t *attributes,
- unsigned int http_status,
- struct MHD_Response *response,
TEH_KycAmlTriggerCallback cb,
void *cb_cls)
{
@@ -515,8 +487,6 @@ TEH_kyc_finished (
= GNUNET_strdup (provider_legitimization_id);
kat->expiration = expiration;
kat->attributes = json_incref ((json_t*) attributes);
- kat->http_status = http_status;
- kat->response = response;
kat->cb = cb;
kat->cb_cls = cb_cls;
if (NULL == instant_ms)
@@ -633,11 +603,6 @@ TEH_kyc_finished_cancel (struct TEH_KycAmlTrigger *kat)
json_decref (kat->attributes);
json_decref (kat->aml_history);
json_decref (kat->kyc_history);
- if (NULL != kat->response)
- {
- MHD_destroy_response (kat->response);
- kat->response = NULL;
- }
GNUNET_free (kat);
}
@@ -1111,22 +1076,24 @@ legitimization_check_run (
* Function called after the KYC-AML trigger is done.
*
* @param cls must be a `struct TEH_LegitimizationCheckHandle *`
- * @param http_status final HTTP status to return
- * @param[in] response final HTTP ro return
+ * @param ec error code or 0 on success
+ * @param detail error message or NULL on success / no info
*/
static void
legi_check_aml_trigger_cb (
void *cls,
- unsigned int http_status,
- struct MHD_Response *response)
+ enum TALER_ErrorCode ec,
+ const char *detail)
{
struct TEH_LegitimizationCheckHandle *lch = cls;
lch->kat = NULL;
- if (NULL != response)
+ if (TALER_EC_NONE != ec)
{
- lch->lcr.http_status = http_status;
- lch->lcr.response = response;
+ lch->lcr.http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ lch->lcr.response = TALER_MHD_make_error (
+ ec,
+ detail);
lch->async_task
= GNUNET_SCHEDULER_add_now (
&async_return_legi_result,
@@ -1807,8 +1774,6 @@ legitimization_check_run (
NULL,
GNUNET_TIME_UNIT_FOREVER_ABS,
attributes,
- 0, /* http status */
- NULL, /* MHD_Response */
&legi_check_aml_trigger_cb,
lch);
json_decref (attributes);
diff --git a/src/exchange/taler-exchange-httpd_common_kyc.h b/src/exchange/taler-exchange-httpd_common_kyc.h
index 4e7c7e7e6..fb2ee1306 100644
--- a/src/exchange/taler-exchange-httpd_common_kyc.h
+++ b/src/exchange/taler-exchange-httpd_common_kyc.h
@@ -94,14 +94,14 @@ TEH_kyc_run_measure_instant (
* Function called after the KYC-AML trigger is done.
*
* @param cls closure
- * @param http_status final HTTP status to return
- * @param[in] response final HTTP ro return
+ * @param ec error code or 0 on success
+ * @param detail error message or NULL on success / no info
*/
typedef void
(*TEH_KycAmlTriggerCallback) (
void *cls,
- unsigned int http_status,
- struct MHD_Response *response);
+ enum TALER_ErrorCode ec,
+ const char *detail);
/**
@@ -128,8 +128,6 @@ struct TEH_KycAmlTrigger;
* @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown
* @param expiration until when is the KYC check valid
* @param attributes user attributes returned by the provider
- * @param http_status HTTP status code of @a response
- * @param[in] response to return to the HTTP client
* @param cb function to call with the result
* @param cb_cls closure for @a cb
* @return handle to cancel the operation
@@ -145,8 +143,6 @@ TEH_kyc_finished (
const char *provider_legitimization_id,
struct GNUNET_TIME_Absolute expiration,
const json_t *attributes,
- unsigned int http_status,
- struct MHD_Response *response,
TEH_KycAmlTriggerCallback cb,
void *cb_cls);
diff --git a/src/exchange/taler-exchange-httpd_kyc-info.c b/src/exchange/taler-exchange-httpd_kyc-info.c
index 1309b10f8..f6abc48ba 100644
--- a/src/exchange/taler-exchange-httpd_kyc-info.c
+++ b/src/exchange/taler-exchange-httpd_kyc-info.c
@@ -417,8 +417,7 @@ TEH_handler_kyc_info (
uint64_t legitimization_outcome_last_row;
json_t *jmeasures = NULL;
json_t *jvoluntary = NULL;
- json_t *jnew_rules;
- struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
+ struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs = NULL;
if (NULL == kyp)
{
@@ -435,11 +434,12 @@ TEH_handler_kyc_info (
sizeof (kyp->access_token)))
{
GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (
+ res = TALER_MHD_reply_with_error (
rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"access token");
+ goto cleanup;
}
TALER_MHD_parse_request_timeout (rc->connection,
&kyp->timeout);
@@ -485,20 +485,21 @@ TEH_handler_kyc_info (
if (qs < 0)
{
GNUNET_break (0);
- return TALER_MHD_reply_with_ec (
+ res = TALER_MHD_reply_with_ec (
rc->connection,
TALER_EC_GENERIC_DB_FETCH_FAILED,
"lookup_h_payto_by_access_token");
+ goto cleanup;
}
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
GNUNET_break_op (0);
- return TALER_MHD_REPLY_JSON_PACK (
+ res = TALER_MHD_REPLY_JSON_PACK (
rc->connection,
MHD_HTTP_FORBIDDEN,
TALER_JSON_pack_ec (
TALER_EC_EXCHANGE_KYC_INFO_AUTHORIZATION_FAILED));
-
+ goto cleanup;
}
if (GNUNET_TIME_absolute_is_future (kyp->timeout))
@@ -520,31 +521,37 @@ TEH_handler_kyc_info (
}
} /* end of one-time initialization */
- qs = TEH_plugin->lookup_rules_by_access_token (
- TEH_plugin->cls,
- &kyp->h_payto,
- &jnew_rules,
- &legitimization_outcome_last_row);
- if (qs < 0)
+ /* Get rules. */
{
- GNUNET_break (0);
- return TALER_MHD_reply_with_ec (
- rc->connection,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "lookup_rules_by_access_token");
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- /* Nothing was triggered, return the measures
- that apply for any amount. */
- lrs = NULL;
- }
- else
- {
- lrs = TALER_KYCLOGIC_rules_parse (jnew_rules);
- GNUNET_break (NULL != lrs);
- json_decref (jnew_rules);
+ json_t *jnew_rules;
+ qs = TEH_plugin->lookup_rules_by_access_token (
+ TEH_plugin->cls,
+ &kyp->h_payto,
+ &jnew_rules,
+ &legitimization_outcome_last_row);
+ if (qs < 0)
+ {
+ GNUNET_break (0);
+ res = TALER_MHD_reply_with_ec (
+ rc->connection,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "lookup_rules_by_access_token");
+ goto cleanup;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ /* Nothing was triggered, return the measures
+ that apply for any amount. */
+ lrs = NULL;
+ }
+ else
+ {
+ lrs = TALER_KYCLOGIC_rules_parse (jnew_rules);
+ GNUNET_break (NULL != lrs);
+ json_decref (jnew_rules);
+ }
}
+
jvoluntary
= TALER_KYCLOGIC_voluntary_measures (lrs);
@@ -556,11 +563,11 @@ TEH_handler_kyc_info (
if (qs < 0)
{
GNUNET_break (0);
- TALER_KYCLOGIC_rules_free (lrs);
- return TALER_MHD_reply_with_ec (
+ res = TALER_MHD_reply_with_ec (
rc->connection,
TALER_EC_GENERIC_DB_FETCH_FAILED,
"lookup_kyc_status_by_token");
+ goto cleanup;
}
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
@@ -570,13 +577,13 @@ TEH_handler_kyc_info (
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"No KYC requirement open\n");
- TALER_KYCLOGIC_rules_free (lrs);
- return TALER_MHD_REPLY_JSON_PACK (
+ res = TALER_MHD_REPLY_JSON_PACK (
rc->connection,
MHD_HTTP_OK,
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_array_steal ("voluntary_measures",
jvoluntary)));
+ goto cleanup;
}
qs = TEH_plugin->insert_active_legitimization_measure (
@@ -587,14 +594,16 @@ TEH_handler_kyc_info (
if (qs < 0)
{
GNUNET_break (0);
- TALER_KYCLOGIC_rules_free (lrs);
- return TALER_MHD_reply_with_ec (
+ res = TALER_MHD_reply_with_ec (
rc->connection,
TALER_EC_GENERIC_DB_STORE_FAILED,
"insert_active_legitimization_measure");
+ goto cleanup;
}
}
+ /* We can free rules early here. */
TALER_KYCLOGIC_rules_free (lrs);
+ lrs = NULL;
if ( (legitimization_measure_last_row == kyp->etag_measure_in) &&
(legitimization_outcome_last_row == kyp->etag_outcome_in) &&
GNUNET_TIME_absolute_is_future (kyp->timeout) )
@@ -611,19 +620,19 @@ TEH_handler_kyc_info (
kyp_tail,
kyp);
MHD_suspend_connection (rc->connection);
- return MHD_YES;
+ res = MHD_YES;
+ goto cleanup;
}
/* FIXME: We should instead long-poll on the running KYC program. */
if (contains_instant_measure (jmeasures))
{
- json_decref (jmeasures);
- json_decref (jvoluntary);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Still waiting for KYC program.\n");
- return TALER_MHD_reply_with_ec (
+ res = TALER_MHD_reply_with_ec (
rc->connection,
TALER_EC_EXCHANGE_KYC_INFO_BUSY,
"waiting for KYC program");
+ goto cleanup;
}
if ( (legitimization_measure_last_row ==
kyp->etag_measure_in) &&
@@ -632,18 +641,17 @@ TEH_handler_kyc_info (
{
char etags[128];
- json_decref (jmeasures);
- json_decref (jvoluntary);
GNUNET_snprintf (etags,
sizeof (etags),
"\"%llu-%llu\"",
(unsigned long long) legitimization_measure_last_row,
(unsigned long long) legitimization_outcome_last_row);
- return TEH_RESPONSE_reply_not_modified (
+ res = TEH_RESPONSE_reply_not_modified (
rc->connection,
etags,
&add_response_headers,
NULL);
+ goto cleanup;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Generating success reply to kyc-info query\n");
@@ -652,6 +660,8 @@ TEH_handler_kyc_info (
legitimization_outcome_last_row,
jmeasures,
jvoluntary);
+cleanup:
+ TALER_KYCLOGIC_rules_free (lrs);
json_decref (jmeasures);
json_decref (jvoluntary);
return res;
diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c b/src/exchange/taler-exchange-httpd_kyc-proof.c
index 926770073..c3e38e3df 100644
--- a/src/exchange/taler-exchange-httpd_kyc-proof.c
+++ b/src/exchange/taler-exchange-httpd_kyc-proof.c
@@ -92,11 +92,26 @@ struct KycProofContext
struct TALER_NormalizedPaytoHashP h_payto;
/**
- * HTTP response to return.
+ * Final HTTP response to return.
*/
struct MHD_Response *response;
/**
+ * Final HTTP response code to return.
+ */
+ unsigned int response_code;
+
+ /**
+ * HTTP response from the KYC provider plugin.
+ */
+ struct MHD_Response *proof_response;
+
+ /**
+ * HTTP response code from the KYC provider plugin.
+ */
+ unsigned int proof_response_code;
+
+ /**
* Provider configuration section name of the logic we are running.
*/
const char *provider_name;
@@ -107,11 +122,6 @@ struct KycProofContext
uint64_t process_row;
/**
- * HTTP response code to return.
- */
- unsigned int response_code;
-
- /**
* True if we are suspended,
*/
bool suspended;
@@ -131,6 +141,46 @@ static struct KycProofContext *kpc_tail;
/**
+ * Generate HTML error for @a connection using @a template.
+ *
+ * @param connection HTTP client connection
+ * @param template template to expand
+ * @param[in,out] http_status HTTP status of the response
+ * @param ec Taler error code to return
+ * @param message extended message to return
+ * @return MHD response object
+ */
+static struct MHD_Response *
+make_html_error (struct MHD_Connection *connection,
+ const char *template,
+ unsigned int *http_status,
+ enum TALER_ErrorCode ec,
+ const char *message)
+{
+ struct MHD_Response *response = NULL;
+ json_t *body;
+
+ body = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string ("message",
+ message)),
+ TALER_JSON_pack_ec (
+ ec));
+ GNUNET_break (
+ GNUNET_SYSERR !=
+ TALER_TEMPLATING_build (connection,
+ http_status,
+ template,
+ NULL,
+ NULL,
+ body,
+ &response));
+ json_decref (body);
+ return response;
+}
+
+
+/**
* Resume processing the @a kpc request.
*
* @param kpc request to resume
@@ -169,66 +219,42 @@ TEH_kyc_proof_cleanup (void)
* Function called after the KYC-AML trigger is done.
*
* @param cls closure
- * @param http_status final HTTP status to return
- * @param[in] response final HTTP ro return
+ * @param ec error code or 0 on success
+ * @param detail error message or NULL on success / no info
*/
static void
proof_finish (
void *cls,
- unsigned int http_status,
- struct MHD_Response *response)
+ enum TALER_ErrorCode ec,
+ const char *detail)
{
struct KycProofContext *kpc = cls;
kpc->kat = NULL;
+ if (TALER_EC_NONE != ec)
+ {
+ kpc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ kpc->response = make_html_error (
+ kpc->rc->connection,
+ "kyc-proof-internal-error",
+ &kpc->response_code,
+ ec,
+ detail);
+ }
+ else
+ {
+ GNUNET_assert (NULL != kpc->proof_response);
+ kpc->response_code = kpc->proof_response_code;
+ kpc->response = kpc->proof_response;
+ kpc->proof_response = NULL;
+ kpc->proof_response_code = 0;
+ }
GNUNET_assert (NULL == kpc->response);
- kpc->response_code = http_status;
- kpc->response = response;
kpc_resume (kpc);
}
/**
- * Generate HTML error for @a connection using @a template.
- *
- * @param connection HTTP client connection
- * @param template template to expand
- * @param[in,out] http_status HTTP status of the response
- * @param ec Taler error code to return
- * @param message extended message to return
- * @return MHD response object
- */
-static struct MHD_Response *
-make_html_error (struct MHD_Connection *connection,
- const char *template,
- unsigned int *http_status,
- enum TALER_ErrorCode ec,
- const char *message)
-{
- struct MHD_Response *response = NULL;
- json_t *body;
-
- body = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_string ("message",
- message)),
- TALER_JSON_pack_ec (
- ec));
- GNUNET_break (
- GNUNET_SYSERR !=
- TALER_TEMPLATING_build (connection,
- http_status,
- template,
- NULL,
- NULL,
- body,
- &response));
- json_decref (body);
- return response;
-}
-
-
-/**
* Respond with an HTML message on the given @a rc.
*
* @param[in,out] rc request to respond to
@@ -292,6 +318,8 @@ proof_cb (
struct GNUNET_AsyncScopeSave old_scope;
kpc->ph = NULL;
+ kpc->proof_response = response;
+ kpc->proof_response_code = http_status;
GNUNET_async_scope_enter (&rc->async_scope_id,
&old_scope);
switch (status)
@@ -310,20 +338,13 @@ proof_cb (
provider_legitimization_id,
expiration,
attributes,
- http_status,
- response,
&proof_finish,
kpc);
- response = NULL; /* taken over by TEH_kyc_finished */
if (NULL == kpc->kat)
{
- http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
- response = make_html_error (
- kpc->rc->connection,
- "kyc-proof-internal-error",
- &http_status,
- TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
- "[exchange] AML_KYC_TRIGGER");
+ proof_finish (kpc,
+ TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
+ "[exchange] AML_KYC_TRIGGER");
}
break;
case TALER_KYCLOGIC_STATUS_FAILED:
@@ -342,16 +363,12 @@ proof_cb (
char *msg;
/* OAuth2 server had a problem, do NOT log this as a KYC failure */
- if (NULL != response)
- MHD_destroy_response (response);
GNUNET_asprintf (&msg,
"Failure by KYC provider (HTTP status %u)\n",
http_status);
http_status = MHD_HTTP_BAD_GATEWAY;
- response = make_html_error (
- kpc->rc->connection,
- "kyc-proof-internal-error",
- &http_status,
+ proof_finish (
+ kpc,
TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY,
msg);
GNUNET_free (msg);
@@ -368,16 +385,21 @@ proof_cb (
TALER_EC_EXCHANGE_GENERIC_KYC_FAILED))
{
GNUNET_break (0);
- if (NULL != response)
- MHD_destroy_response (response);
- http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
- response = make_html_error (
- kpc->rc->connection,
- "kyc-proof-internal-error",
- &http_status,
+ proof_finish (
+ kpc,
TALER_EC_GENERIC_DB_STORE_FAILED,
"insert_kyc_failure");
}
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC process #%llu failed with status %d\n",
+ (unsigned long long) kpc->process_row,
+ status);
+ proof_finish (kpc,
+ TALER_EC_NONE,
+ NULL);
+ }
}
break;
default:
@@ -389,16 +411,6 @@ proof_cb (
(int) status);
break;
}
- if (NULL == kpc->kat)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "KYC process #%llu failed with status %d\n",
- (unsigned long long) kpc->process_row,
- status);
- proof_finish (kpc,
- http_status,
- response);
- }
GNUNET_async_scope_restore (&old_scope);
}
@@ -428,6 +440,11 @@ clean_kpc (struct TEH_RequestContext *rc)
MHD_destroy_response (kpc->response);
kpc->response = NULL;
}
+ if (NULL != kpc->proof_response)
+ {
+ MHD_destroy_response (kpc->proof_response);
+ kpc->proof_response = NULL;
+ }
GNUNET_free (kpc->provider_user_id);
GNUNET_free (kpc->provider_legitimization_id);
GNUNET_free (kpc);
diff --git a/src/exchange/taler-exchange-httpd_kyc-upload.c b/src/exchange/taler-exchange-httpd_kyc-upload.c
index aeeb646f0..4e0b0cd70 100644
--- a/src/exchange/taler-exchange-httpd_kyc-upload.c
+++ b/src/exchange/taler-exchange-httpd_kyc-upload.c
@@ -334,22 +334,35 @@ post_helper (void *cls,
* Function called after the KYC-AML trigger is done.
*
* @param cls closure
- * @param http_status final HTTP status to return
- * @param[in] response final HTTP ro return
+ * @param ec error code or 0 on success
+ * @param detail error message or NULL on success / no info
*/
static void
aml_trigger_callback (
void *cls,
- unsigned int http_status,
- struct MHD_Response *response)
+ enum TALER_ErrorCode ec,
+ const char *detail)
{
struct UploadContext *uc = cls;
uc->kat = NULL;
GNUNET_assert (NULL == uc->response);
- GNUNET_assert (NULL != response);
- uc->response_code = http_status;
- uc->response = response;
+ if (TALER_EC_NONE != ec)
+ {
+ uc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ uc->response = TALER_MHD_make_error (
+ ec,
+ detail);
+ }
+ else
+ {
+ uc->response_code = MHD_HTTP_NO_CONTENT;
+ uc->response = MHD_create_response_from_buffer_static (
+ 0,
+ ""
+ );
+ }
+
MHD_resume_connection (uc->rc->connection);
GNUNET_CONTAINER_DLL_remove (uc_head,
uc_tail,
@@ -458,7 +471,6 @@ TEH_handler_kyc_upload (
struct TALER_NormalizedPaytoHashP h_payto;
enum GNUNET_DB_QueryStatus qs;
json_t *jmeasures;
- struct MHD_Response *empty_response;
bool is_finished = false;
size_t enc_attributes_len;
void *enc_attributes;
@@ -578,9 +590,6 @@ TEH_handler_kyc_upload (
"insert_kyc_requirement_process");
}
- empty_response
- = MHD_create_response_from_buffer_static (0,
- "");
uc->kat = TEH_kyc_finished (
&rc->async_scope_id,
legi_process_row,
@@ -591,11 +600,8 @@ TEH_handler_kyc_upload (
NULL /* provider legi ID */,
GNUNET_TIME_UNIT_FOREVER_ABS, /* expiration time */
uc->result,
- MHD_HTTP_NO_CONTENT,
- empty_response,
&aml_trigger_callback,
uc);
- empty_response = NULL; /* taken over by TEH_kyc_finished */
if (NULL == uc->kat)
{
GNUNET_break (0);
diff --git a/src/exchange/taler-exchange-httpd_kyc-webhook.c b/src/exchange/taler-exchange-httpd_kyc-webhook.c
index 588143291..605288ce7 100644
--- a/src/exchange/taler-exchange-httpd_kyc-webhook.c
+++ b/src/exchange/taler-exchange-httpd_kyc-webhook.c
@@ -81,16 +81,30 @@ struct KycWebhookContext
struct TALER_KYCLOGIC_WebhookHandle *wh;
/**
- * HTTP response to return.
+ * Final HTTP response to return.
*/
struct MHD_Response *response;
/**
- * HTTP response code to return.
+ * Final HTTP response code to return.
*/
unsigned int response_code;
/**
+ * Response from the webhook plugin.
+ *
+ * Will become the final response on successfully
+ * running the measure with the new attributes.
+ */
+ struct MHD_Response *webhook_response;
+
+ /**
+ * Response code to return for the webhook plugin
+ * response.
+ */
+ unsigned int webhook_response_code;
+
+ /**
* #GNUNET_YES if we are suspended,
* #GNUNET_NO if not.
* #GNUNET_SYSERR if we had some error.
@@ -150,21 +164,35 @@ TEH_kyc_webhook_cleanup (void)
* Function called after the KYC-AML trigger is done.
*
* @param cls closure with a `struct KycWebhookContext *`
- * @param http_status final HTTP status to return
- * @param[in] response final HTTP ro return
+ * @param ec error code or 0 on success
+ * @param detail error message or NULL on success / no info
*/
static void
kyc_aml_webhook_finished (
void *cls,
- unsigned int http_status,
- struct MHD_Response *response)
+ enum TALER_ErrorCode ec,
+ const char *detail)
{
struct KycWebhookContext *kwh = cls;
kwh->kat = NULL;
GNUNET_assert (NULL == kwh->response);
- kwh->response = response;
- kwh->response_code = http_status;
+ if (TALER_EC_NONE != ec)
+ {
+ kwh->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ kwh->response = TALER_MHD_make_error (
+ ec,
+ detail
+ );
+ }
+ else
+ {
+ GNUNET_assert (NULL != kwh->webhook_response);
+ kwh->response_code = kwh->webhook_response_code;
+ kwh->response = kwh->webhook_response;
+ kwh->webhook_response = NULL;
+ kwh->webhook_response_code = 0;
+ }
kwh_resume (kwh);
}
@@ -204,6 +232,9 @@ webhook_finished_cb (
struct KycWebhookContext *kwh = cls;
kwh->wh = NULL;
+ kwh->webhook_response = response;
+ kwh->webhook_response_code = http_status;
+
switch (status)
{
case TALER_KYCLOGIC_STATUS_SUCCESS:
@@ -217,21 +248,15 @@ webhook_finished_cb (
provider_legitimization_id,
expiration,
attributes,
- http_status,
- response,
&kyc_aml_webhook_finished,
kwh);
if (NULL == kwh->kat)
{
- if (NULL != response)
- MHD_destroy_response (response);
- http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
- response = TALER_MHD_make_error (
- TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
- "[exchange] AML_KYC_TRIGGER");
- break;
+ kyc_aml_webhook_finished (kwh,
+ TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
+ "[exchange] AML_KYC_TRIGGER");
}
- return;
+ break;
case TALER_KYCLOGIC_STATUS_FAILED:
case TALER_KYCLOGIC_STATUS_PROVIDER_FAILED:
case TALER_KYCLOGIC_STATUS_USER_ABORTED:
@@ -252,12 +277,9 @@ webhook_finished_cb (
TALER_EC_EXCHANGE_GENERIC_KYC_FAILED))
{
GNUNET_break (0);
- if (NULL != response)
- MHD_destroy_response (response);
- http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
- response = TALER_MHD_make_error (
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "insert_kyc_failure");
+ kyc_aml_webhook_finished (kwh,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_kyc_failure");
}
break;
default:
@@ -268,12 +290,11 @@ webhook_finished_cb (
provider_legitimization_id,
(unsigned long long) process_row,
(int) status);
+ kyc_aml_webhook_finished (kwh,
+ TALER_EC_NONE,
+ NULL);
break;
}
- GNUNET_break (NULL == kwh->kat);
- kyc_aml_webhook_finished (kwh,
- http_status,
- response);
}
@@ -302,6 +323,11 @@ clean_kwh (struct TEH_RequestContext *rc)
MHD_destroy_response (kwh->response);
kwh->response = NULL;
}
+ if (NULL != kwh->webhook_response)
+ {
+ MHD_destroy_response (kwh->response);
+ kwh->webhook_response = NULL;
+ }
GNUNET_free (kwh);
}