diff options
author | Florian Dold <florian@dold.me> | 2024-11-07 21:00:56 +0100 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2024-11-07 21:00:56 +0100 |
commit | f10bc444579a5af215a8ac38c5d0e627786e423e (patch) | |
tree | 20293656774fcef9a3e72cf7694597c54f36dcaf | |
parent | 8dc83c0c3e783bd96de51858bf934ebc74797e2c (diff) |
kyclogic: make TEH_kyc_finished useable without MHD response
-rw-r--r-- | src/exchange/taler-exchange-httpd_aml-decision.c | 36 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_common_kyc.c | 105 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_common_kyc.h | 12 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-info.c | 94 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-proof.c | 187 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-upload.c | 34 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-webhook.c | 82 |
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); } |