diff options
Diffstat (limited to 'src/exchange/taler-exchange-httpd_common_kyc.c')
-rw-r--r-- | src/exchange/taler-exchange-httpd_common_kyc.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/src/exchange/taler-exchange-httpd_common_kyc.c b/src/exchange/taler-exchange-httpd_common_kyc.c new file mode 100644 index 000000000..62e6fe526 --- /dev/null +++ b/src/exchange/taler-exchange-httpd_common_kyc.c @@ -0,0 +1,259 @@ +/* + This file is part of TALER + Copyright (C) 2023 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file taler-exchange-httpd_common_kyc.c + * @brief shared logic for finishing a KYC process + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-exchange-httpd_common_kyc.h" +#include "taler_attributes.h" +#include "taler_exchangedb_plugin.h" + +struct TEH_KycAmlTrigger +{ + + /** + * Our logging scope. + */ + struct GNUNET_AsyncScopeId scope; + + /** + * account the operation is about + */ + struct TALER_PaytoHashP account_id; + + /** + * until when is the KYC data valid + */ + struct GNUNET_TIME_Absolute expiration; + + /** + * legitimization process the KYC data is about + */ + uint64_t process_row; + + /** + * name of the configuration section of the logic that was run + */ + char *provider_section; + + /** + * set to user ID at the provider, or NULL if not supported or unknown + */ + char *provider_user_id; + + /** + * provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown + */ + char *provider_legitimization_id; + + /** + * function to call with the result + */ + TEH_KycAmlTriggerCallback cb; + + /** + * closure for @e cb + */ + void *cb_cls; + + /** + * user attributes returned by the provider + */ + json_t *attributes; + + /** + * response to return to the HTTP client + */ + struct MHD_Response *response; + + /** + * Handle to an external process that evalutates the + * need to run AML on the account. + */ + struct TALER_JSON_ExternalConversion *kyc_aml; + + /** + * HTTP status code of @e response + */ + unsigned int http_status; + +}; + + +/** + * Type of a callback that receives a JSON @a result. + * + * @param cls closure of type `struct TEH_KycAmlTrigger *` + * @param status_type how did the process die + * @param code termination status code from the process + * @param result some JSON result, NULL if we failed to get an JSON output + */ +static void +kyc_aml_finished (void *cls, + enum GNUNET_OS_ProcessStatusType status_type, + unsigned long code, + const json_t *result) +{ + struct TEH_KycAmlTrigger *kat = cls; + enum GNUNET_DB_QueryStatus qs; + size_t eas; + void *ea; + const char *birthdate; + struct GNUNET_ShortHashCode kyc_prox; + struct GNUNET_AsyncScopeSave old_scope; + + kat->kyc_aml = NULL; + GNUNET_async_scope_enter (&kat->scope, + &old_scope); + TALER_CRYPTO_attributes_to_kyc_prox (kat->attributes, + &kyc_prox); + birthdate = json_string_value (json_object_get (kat->attributes, + TALER_ATTRIBUTE_BIRTHDATE)); + TALER_CRYPTO_kyc_attributes_encrypt (&TEH_attribute_key, + kat->attributes, + &ea, + &eas); + // FIXME: begin transaction (or move everything into one stored procedure?) + qs = TEH_plugin->insert_kyc_attributes ( + TEH_plugin->cls, + &kat->account_id, + &kyc_prox, + kat->provider_section, + birthdate, + GNUNET_TIME_timestamp_get (), + GNUNET_TIME_absolute_to_timestamp (kat->expiration), + eas, + ea); + GNUNET_free (ea); + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + 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, + "insert_kyc_attributes"); + goto finish; + } + qs = TEH_plugin->update_kyc_process_by_row (TEH_plugin->cls, + kat->process_row, + kat->provider_section, + &kat->account_id, + kat->provider_user_id, + kat->provider_legitimization_id, + kat->expiration); + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + 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, + "update_kyc_process_by_row"); + goto finish; + } + // FIXME: do DB work, possibly updating kat! + if (0 != code) + { + // FIXME: trigger AML! + GNUNET_break (0); // FIXME: not implemented + } + // FIXME: end transaction + + /* Finally, return result to main handler */ +finish: + kat->cb (kat->cb_cls, + kat->http_status, + kat->response); + kat->response = NULL; + TEH_kyc_finished_cancel (kat); + GNUNET_async_scope_restore (&old_scope); +} + + +struct TEH_KycAmlTrigger * +TEH_kyc_finished (const struct GNUNET_AsyncScopeId *scope, + uint64_t process_row, + const struct TALER_PaytoHashP *account_id, + const char *provider_section, + const char *provider_user_id, + 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) +{ + struct TEH_KycAmlTrigger *kat; + + kat = GNUNET_new (struct TEH_KycAmlTrigger); + kat->scope = *scope; + kat->process_row = process_row; + kat->account_id = *account_id; + kat->provider_section + = GNUNET_strdup (provider_section); + if (NULL != provider_user_id) + kat->provider_user_id + = GNUNET_strdup (provider_user_id); + if (NULL != provider_legitimization_id) + kat->provider_legitimization_id + = 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; + kat->kyc_aml + = TALER_JSON_external_conversion_start ( + attributes, + &kyc_aml_finished, + kat, + TEH_kyc_aml_trigger, + TEH_kyc_aml_trigger, + NULL); + if (NULL == kat->kyc_aml) + { + GNUNET_break (0); + TEH_kyc_finished_cancel (kat); + return NULL; + } + return kat; +} + + +void +TEH_kyc_finished_cancel (struct TEH_KycAmlTrigger *kat) +{ + if (NULL != kat->kyc_aml) + { + TALER_JSON_external_conversion_stop (kat->kyc_aml); + kat->kyc_aml = NULL; + } + GNUNET_free (kat->provider_section); + GNUNET_free (kat->provider_user_id); + GNUNET_free (kat->provider_legitimization_id); + json_decref (kat->attributes); + if (NULL != kat->response) + { + MHD_destroy_response (kat->response); + kat->response = NULL; + } + GNUNET_free (kat); +} |