diff options
Diffstat (limited to 'src/exchange/taler-exchange-httpd_kyc-proof.c')
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-proof.c | 219 |
1 files changed, 182 insertions, 37 deletions
diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c b/src/exchange/taler-exchange-httpd_kyc-proof.c index b3175bd28..bad377a2a 100644 --- a/src/exchange/taler-exchange-httpd_kyc-proof.c +++ b/src/exchange/taler-exchange-httpd_kyc-proof.c @@ -27,6 +27,7 @@ #include "taler_json_lib.h" #include "taler_kyclogic_lib.h" #include "taler_mhd_lib.h" +#include "taler_templating_lib.h" #include "taler-exchange-httpd_common_kyc.h" #include "taler-exchange-httpd_kyc-proof.h" #include "taler-exchange-httpd_responses.h" @@ -187,6 +188,79 @@ proof_finish ( /** + * 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 + */ +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 + * @param http_status HTTP status code to use + * @param template template to fill in + * @param ec error code to use for the template + * @param message additional message to return + * @return MHD result code + */ +static MHD_RESULT +respond_html_ec (struct TEH_RequestContext *rc, + unsigned int http_status, + const char *template, + enum TALER_ErrorCode ec, + const char *message) +{ + struct MHD_Response *response; + MHD_RESULT res; + + response = make_html_error (rc->connection, + template, + &http_status, + ec, + message); + res = MHD_queue_response (rc->connection, + http_status, + response); + MHD_destroy_response (response); + return res; +} + + +/** * Function called with the result of a proof check operation. * * Note that the "decref" for the @a response @@ -219,8 +293,12 @@ proof_cb ( kpc->ph = NULL; GNUNET_async_scope_enter (&rc->async_scope_id, &old_scope); - if (TALER_KYCLOGIC_STATUS_SUCCESS == status) + switch (status) { + case TALER_KYCLOGIC_STATUS_SUCCESS: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "KYC process #%llu succeeded with KYC provider\n", + (unsigned long long) kpc->process_row); kpc->kat = TEH_kyc_finished (&rc->async_scope_id, kpc->process_row, &kpc->h_payto, @@ -238,10 +316,70 @@ proof_cb ( http_status = MHD_HTTP_INTERNAL_SERVER_ERROR; if (NULL != response) MHD_destroy_response (response); - response = TALER_MHD_make_error ( - TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION, - "[exchange] AML_KYC_TRIGGER"); + response = make_html_error (kpc->rc->connection, + "kyc-proof-internal-error", + &http_status, + TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION, + "[exchange] AML_KYC_TRIGGER"); } + break; + case TALER_KYCLOGIC_STATUS_FAILED: + case TALER_KYCLOGIC_STATUS_PROVIDER_FAILED: + case TALER_KYCLOGIC_STATUS_USER_ABORTED: + case TALER_KYCLOGIC_STATUS_ABORTED: + GNUNET_assert (NULL == kpc->kat); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "KYC process %s/%s (Row #%llu) failed: %d\n", + provider_user_id, + provider_legitimization_id, + (unsigned long long) kpc->process_row, + status); + if (5 == http_status / 100) + { + 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, + TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY, + msg); + GNUNET_free (msg); + } + else + { + if (! TEH_kyc_failed (kpc->process_row, + &kpc->h_payto, + kpc->provider_section, + provider_user_id, + provider_legitimization_id)) + { + 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, + TALER_EC_GENERIC_DB_STORE_FAILED, + "insert_kyc_failure"); + } + } + break; + default: + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "KYC status of %s/%s (Row #%llu) is %d\n", + provider_user_id, + provider_legitimization_id, + (unsigned long long) kpc->process_row, + (int) status); + break; } if (NULL == kpc->kat) { @@ -302,10 +440,11 @@ TEH_handler_kyc_proof ( if (NULL == provider_section_or_logic) { GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_GENERIC_ENDPOINT_UNKNOWN, - "'/kyc-proof/$PROVIDER_SECTION?state=$H_PAYTO' required"); + return respond_html_ec (rc, + MHD_HTTP_NOT_FOUND, + "kyc-proof-endpoint-unknown", + TALER_EC_GENERIC_ENDPOINT_UNKNOWN, + "'/kyc-proof/$PROVIDER_SECTION?state=$H_PAYTO' required"); } kpc = GNUNET_new (struct KycProofContext); kpc->rc = rc; @@ -321,10 +460,11 @@ TEH_handler_kyc_proof ( &kpc->provider_section)) { GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN, - provider_section_or_logic); + return respond_html_ec (rc, + MHD_HTTP_NOT_FOUND, + "kyc-proof-target-unknown", + TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN, + provider_section_or_logic); } if (NULL != kpc->provider_section) { @@ -335,10 +475,11 @@ TEH_handler_kyc_proof ( kpc->provider_section)) { GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "PROVIDER_SECTION"); + return respond_html_ec (rc, + MHD_HTTP_BAD_REQUEST, + "kyc-proof-bad-request", + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "PROVIDER_SECTION"); } qs = TEH_plugin->lookup_kyc_process_by_account ( @@ -353,26 +494,28 @@ TEH_handler_kyc_proof ( { case GNUNET_DB_STATUS_HARD_ERROR: case GNUNET_DB_STATUS_SOFT_ERROR: - return TALER_MHD_reply_with_ec (rc->connection, - TALER_EC_GENERIC_DB_STORE_FAILED, - "lookup_kyc_requirement_by_account"); + return respond_html_ec (rc, + MHD_HTTP_INTERNAL_SERVER_ERROR, + "kyc-proof-internal-error", + TALER_EC_GENERIC_DB_FETCH_FAILED, + "lookup_kyc_process_by_account"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN, - kpc->provider_section); + return respond_html_ec (rc, + MHD_HTTP_NOT_FOUND, + "kyc-proof-target-unknown", + TALER_EC_EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN, + kpc->provider_section); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: break; } if (GNUNET_TIME_absolute_is_future (expiration)) { /* KYC not required */ - return TALER_MHD_reply_static ( - rc->connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0); + return respond_html_ec (rc, + MHD_HTTP_OK, + "kyc-proof-already-done", + TALER_EC_NONE, + NULL); } } kpc->ph = kpc->logic->proof (kpc->logic->cls, @@ -387,10 +530,11 @@ TEH_handler_kyc_proof ( if (NULL == kpc->ph) { GNUNET_break (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, - "could not start proof with KYC logic"); + return respond_html_ec (rc, + MHD_HTTP_INTERNAL_SERVER_ERROR, + "kyc-proof-internal-error", + TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, + "could not start proof with KYC logic"); } @@ -405,10 +549,11 @@ TEH_handler_kyc_proof ( if (NULL == kpc->response) { GNUNET_break (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, - "handler resumed without response"); + return respond_html_ec (rc, + MHD_HTTP_INTERNAL_SERVER_ERROR, + "kyc-proof-internal-error", + TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, + "handler resumed without response"); } /* return response from KYC logic */ |