commit eff2f2cca6b14db6b983e7235a7b5379a88636a1
parent f18c25828e6f7175b0a26f76048fb86611cadd08
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 5 May 2024 10:51:24 +0200
get exchange_api_kyc_check.c to build again
Diffstat:
7 files changed, 238 insertions(+), 150 deletions(-)
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
@@ -1822,6 +1822,35 @@ struct TALER_FreshCoin
};
+/**
+ * Details about an encrypted contract.
+ */
+struct TALER_EncryptedContract
+{
+
+ /**
+ * Signature of the client affiming this encrypted contract.
+ */
+ struct TALER_PurseContractSignatureP econtract_sig;
+
+ /**
+ * Contract decryption key for the purse.
+ */
+ struct TALER_ContractDiffiePublicP contract_pub;
+
+ /**
+ * Encrypted contract, can be NULL.
+ */
+ void *econtract;
+
+ /**
+ * Number of bytes in @e econtract.
+ */
+ size_t econtract_size;
+
+};
+
+
GNUNET_NETWORK_STRUCT_BEGIN
/**
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
@@ -25,7 +25,7 @@
#include <jansson.h>
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_db_lib.h>
-#include "taler_json_lib.h"
+#include "taler_util.h"
#include "taler_signatures.h"
#include "taler_extensions_policy.h"
diff --git a/src/include/taler_extensions_policy.h b/src/include/taler_extensions_policy.h
@@ -23,7 +23,6 @@
#include <gnunet/gnunet_util_lib.h>
#include "taler_util.h"
-#include "taler_json_lib.h"
#include "taler_mhd_lib.h"
/*
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
@@ -26,6 +26,7 @@
#include <gnunet/gnunet_json_lib.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler_util.h"
+#include "taler_kyclogic_lib.h"
#include "taler_error_codes.h"
/**
@@ -33,34 +34,6 @@
*/
#define TALER_JSON_LIB_VERSION 0x00020000
-/**
- * Details about an encrypted contract.
- */
-struct TALER_EncryptedContract
-{
-
- /**
- * Signature of the client affiming this encrypted contract.
- */
- struct TALER_PurseContractSignatureP econtract_sig;
-
- /**
- * Contract decryption key for the purse.
- */
- struct TALER_ContractDiffiePublicP contract_pub;
-
- /**
- * Encrypted contract, can be NULL.
- */
- void *econtract;
-
- /**
- * Number of bytes in @e econtract.
- */
- size_t econtract_size;
-
-};
-
/**
* Print JSON parsing related error information
@@ -341,6 +314,21 @@ TALER_JSON_spec_otp_type (const char *name,
/**
+ * Provide specification to parse a KYC trigger
+ * event type.
+ * The value could be provided as an integer or
+ * as a descriptive string.
+ *
+ * @param name name of the OTP method type in the JSON
+ * @param[out] kte where to store the operation type
+ * @return spec for parsing trigger event type
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_kycte (const char *name,
+ enum TALER_KYCLOGIC_KycTriggerEvent *kte);
+
+
+/**
* Generate specification to parse all fees for
* a denomination under a prefix @a pfx.
*
diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h
@@ -34,34 +34,39 @@ enum TALER_KYCLOGIC_KycTriggerEvent
{
/**
+ * Reserved value for invalid event types.
+ */
+ TALER_KYCLOGIC_KYC_TRIGGER_NONE = 0,
+
+ /**
* Customer withdraws coins.
*/
- TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW = 0,
+ TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW = 1,
/**
* Merchant deposits coins.
*/
- TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT = 1,
+ TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT = 2,
/**
* Wallet receives P2P payment.
*/
- TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE = 2,
+ TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE = 3,
/**
* Wallet balance exceeds threshold.
*/
- TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE = 3,
+ TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE = 4,
/**
* Reserve is being closed by force.
*/
- TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE = 4,
+ TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE = 5,
/**
* Customer withdraws coins via age-withdraw.
*/
- TALER_KYCLOGIC_KYC_TRIGGER_AGE_WITHDRAW = 5,
+ TALER_KYCLOGIC_KYC_TRIGGER_AGE_WITHDRAW = 6,
};
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
@@ -1441,4 +1441,100 @@ TALER_JSON_spec_otp_type (const char *name,
}
+/**
+ * Parse given JSON object to `enum TALER_KYCLOGIC_KycTriggerEvent`
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_kycte (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ static const struct Entry
+ {
+ const char *name;
+ enum TALER_KYCLOGIC_KycTriggerEvent val;
+ } lt [] = {
+ { .name = "NONE",
+ .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
+ { .name = "WITHDRAW",
+ .val = TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW },
+ { .name = "DEPOSIT",
+ .val = TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT },
+ { .name = "P2P-RECEIVE",
+ .val = TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE },
+ { .name = "WALLET-BALANCE",
+ .val = TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE },
+ { .name = "RESERVE-CLOSE",
+ .val = TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE },
+ { .name = "AGE-WITHDRAW",
+ .val = TALER_KYCLOGIC_KYC_TRIGGER_AGE_WITHDRAW },
+ { .name = NULL,
+ .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE },
+ };
+ enum TALER_KYCLOGIC_KycTriggerEvent *res
+ = (enum TALER_KYCLOGIC_KycTriggerEvent *) spec->ptr;
+
+ (void) cls;
+ if (json_is_string (root))
+ {
+ const char *str;
+
+ str = json_string_value (root);
+ if (NULL == str)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ for (unsigned int i = 0; NULL != lt[i].name; i++)
+ {
+ if (0 == strcasecmp (str,
+ lt[i].name))
+ {
+ *res = lt[i].val;
+ return GNUNET_OK;
+ }
+ }
+ GNUNET_break_op (0);
+ }
+ if (json_is_integer (root))
+ {
+ json_int_t val;
+
+ val = json_integer_value (root);
+ for (unsigned int i = 0; NULL != lt[i].name; i++)
+ {
+ if (val == lt[i].val)
+ {
+ *res = lt[i].val;
+ return GNUNET_OK;
+ }
+ }
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_kycte (const char *name,
+ enum TALER_KYCLOGIC_KycTriggerEvent *kte)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_kycte,
+ .field = name,
+ .ptr = kte
+ };
+
+ *kte = TALER_KYCLOGIC_KYC_TRIGGER_NONE;
+ return ret;
+}
+
+
/* end of json/json_helper.c */
diff --git a/src/lib/exchange_api_kyc_check.c b/src/lib/exchange_api_kyc_check.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021-2023 Taler Systems SA
+ Copyright (C) 2021-2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -42,11 +42,6 @@ struct TALER_EXCHANGE_KycCheckHandle
char *url;
/**
- * Keys of the exchange.
- */
- struct TALER_EXCHANGE_Keys *keys;
-
- /**
* Handle for the request.
*/
struct GNUNET_CURL_Job *job;
@@ -61,14 +56,83 @@ struct TALER_EXCHANGE_KycCheckHandle
*/
void *cb_cls;
- /**
- * Hash of the payto:// URL that is being KYC'ed.
- */
- struct TALER_PaytoHashP h_payto;
-
};
+static enum GNUNET_GenericReturnValue
+parse_account_status (struct TALER_EXCHANGE_KycCheckHandle *kch,
+ const json_t *j,
+ struct TALER_EXCHANGE_KycStatus *ks,
+ struct TALER_EXCHANGE_AccountKycStatus *aks)
+{
+ const json_t *limits = NULL;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_bool ("aml_review",
+ &aks->aml_review),
+ GNUNET_JSON_spec_fixed_auto ("access_token",
+ &aks->access_token),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_array_const ("limits",
+ &limits),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (j,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if ( (NULL != limits) &&
+ (0 != json_array_size (limits)) )
+ {
+ size_t als = json_array_size (limits);
+ struct TALER_EXCHANGE_AccountLimit ala[GNUNET_NZL (als)];
+ size_t i;
+ json_t *limit;
+
+ json_array_foreach (limits, i, limit)
+ {
+ struct TALER_EXCHANGE_AccountLimit *al = &ala[i];
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_bool ("soft_limit",
+ &al->soft_limit),
+ GNUNET_JSON_spec_relative_time ("timeframe",
+ &al->timeframe),
+ TALER_JSON_spec_kycte ("operation_type",
+ &al->operation_type),
+ TALER_JSON_spec_amount_any ("threshold",
+ &al->threshold),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (limit,
+ ispec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ }
+ aks->limits = ala;
+ aks->limits_length = als;
+ kch->cb (kch->cb_cls,
+ ks);
+ }
+ else
+ {
+ kch->cb (kch->cb_cls,
+ ks);
+ }
+ GNUNET_JSON_parse_free (spec);
+ return GNUNET_OK;
+}
+
+
/**
* Function called when we're done processing the
* HTTP /kyc-check request.
@@ -96,86 +160,33 @@ handle_kyc_check_finished (void *cls,
break;
case MHD_HTTP_OK:
{
- const json_t *kyc_details;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &ks.details.ok.exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &ks.details.ok.exchange_pub),
- GNUNET_JSON_spec_timestamp ("now",
- &ks.details.ok.timestamp),
- GNUNET_JSON_spec_object_const ("kyc_details",
- &kyc_details),
- TALER_JSON_spec_aml_decision ("aml_status",
- &ks.details.ok.aml_status),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- ks.http_status = 0;
- ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- }
- ks.details.ok.kyc_details = kyc_details;
if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (kch->keys,
- &ks.details.ok.exchange_pub))
+ parse_account_status (kch,
+ j,
+ &ks,
+ &ks.details.ok))
{
GNUNET_break_op (0);
ks.http_status = 0;
ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- GNUNET_JSON_parse_free (spec);
break;
}
-
- if (GNUNET_OK !=
- TALER_exchange_online_account_setup_success_verify (
- &kch->h_payto,
- ks.details.ok.kyc_details,
- ks.details.ok.timestamp,
- &ks.details.ok.exchange_pub,
- &ks.details.ok.exchange_sig))
- {
- GNUNET_break_op (0);
- ks.http_status = 0;
- ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- GNUNET_JSON_parse_free (spec);
- break;
- }
- kch->cb (kch->cb_cls,
- &ks);
- GNUNET_JSON_parse_free (spec);
TALER_EXCHANGE_kyc_check_cancel (kch);
return;
}
case MHD_HTTP_ACCEPTED:
{
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_web_url ("kyc_url",
- &ks.details.accepted.kyc_url),
- TALER_JSON_spec_aml_decision ("aml_status",
- &ks.details.accepted.aml_status),
- GNUNET_JSON_spec_end ()
- };
-
if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
+ parse_account_status (kch,
+ j,
+ &ks,
+ &ks.details.accepted))
{
GNUNET_break_op (0);
ks.http_status = 0;
ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
- kch->cb (kch->cb_cls,
- &ks);
- GNUNET_JSON_parse_free (spec);
TALER_EXCHANGE_kyc_check_cancel (kch);
return;
}
@@ -192,31 +203,6 @@ handle_kyc_check_finished (void *cls,
case MHD_HTTP_NOT_FOUND:
ks.ec = TALER_JSON_get_error_code (j);
break;
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- {
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_aml_decision (
- "aml_status",
- &ks.details.unavailable_for_legal_reasons.aml_status),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- ks.http_status = 0;
- ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- }
- kch->cb (kch->cb_cls,
- &ks);
- GNUNET_JSON_parse_free (spec);
- TALER_EXCHANGE_kyc_check_cancel (kch);
- return;
- }
case MHD_HTTP_INTERNAL_SERVER_ERROR:
ks.ec = TALER_JSON_get_error_code (j);
/* Server had an internal issue; we should retry, but this API
@@ -242,10 +228,8 @@ struct TALER_EXCHANGE_KycCheckHandle *
TALER_EXCHANGE_kyc_check (
struct GNUNET_CURL_Context *ctx,
const char *url,
- struct TALER_EXCHANGE_Keys *keys,
uint64_t requirement_row,
- const struct TALER_PaytoHashP *h_payto,
- enum TALER_KYCLOGIC_KycUserType ut,
+ const struct GNUNET_CRYPTO_EddsaPrivateKey *pk,
struct GNUNET_TIME_Relative timeout,
TALER_EXCHANGE_KycStatusCallback cb,
void *cb_cls)
@@ -255,27 +239,16 @@ TALER_EXCHANGE_kyc_check (
char *arg_str;
{
- char payto_str[sizeof (*h_payto) * 2];
- char *end;
unsigned long long timeout_ms;
- end = GNUNET_STRINGS_data_to_string (
- h_payto,
- sizeof (*h_payto),
- payto_str,
- sizeof (payto_str) - 1);
- *end = '\0';
timeout_ms = timeout.rel_value_us
/ GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
GNUNET_asprintf (&arg_str,
- "kyc-check/%llu/%s/%s?timeout_ms=%llu",
+ "kyc-check/%llu?timeout_ms=%llu",
(unsigned long long) requirement_row,
- payto_str,
- TALER_KYCLOGIC_kyc_user_type2s (ut),
timeout_ms);
}
kch = GNUNET_new (struct TALER_EXCHANGE_KycCheckHandle);
- kch->h_payto = *h_payto;
kch->cb = cb;
kch->cb_cls = cb_cls;
kch->url = TALER_url_join (url,
@@ -295,7 +268,6 @@ TALER_EXCHANGE_kyc_check (
GNUNET_free (kch);
return NULL;
}
- kch->keys = TALER_EXCHANGE_keys_incref (keys);
kch->job = GNUNET_CURL_job_add_with_ct_json (ctx,
eh,
&handle_kyc_check_finished,
@@ -312,7 +284,6 @@ TALER_EXCHANGE_kyc_check_cancel (struct TALER_EXCHANGE_KycCheckHandle *kch)
GNUNET_CURL_job_cancel (kch->job);
kch->job = NULL;
}
- TALER_EXCHANGE_keys_decref (kch->keys);
GNUNET_free (kch->url);
GNUNET_free (kch);
}