summaryrefslogtreecommitdiff
path: root/src/kyclogic/kyclogic_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kyclogic/kyclogic_api.c')
-rw-r--r--src/kyclogic/kyclogic_api.c522
1 files changed, 486 insertions, 36 deletions
diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c
index f2d31acf5..186799dbb 100644
--- a/src/kyclogic/kyclogic_api.c
+++ b/src/kyclogic/kyclogic_api.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2022 Taler Systems SA
+ Copyright (C) 2022-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
@@ -22,6 +22,12 @@
#include "taler_kyclogic_lib.h"
/**
+ * Name of the KYC check that may never be passed. Useful if some
+ * operations/amounts are categorically forbidden.
+ */
+#define KYC_CHECK_IMPOSSIBLE "impossible"
+
+/**
* Information about a KYC provider.
*/
struct TALER_KYCLOGIC_KycProvider;
@@ -180,9 +186,11 @@ TALER_KYCLOGIC_kyc_trigger_from_string (const char *trigger_s,
enum TALER_KYCLOGIC_KycTriggerEvent out;
} map [] = {
{ "withdraw", TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW },
+ { "age-withdraw", TALER_KYCLOGIC_KYC_TRIGGER_AGE_WITHDRAW },
{ "deposit", TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT },
{ "merge", TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE },
{ "balance", TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE },
+ { "close", TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE },
{ NULL, 0 }
};
@@ -207,12 +215,16 @@ TALER_KYCLOGIC_kyc_trigger2s (enum TALER_KYCLOGIC_KycTriggerEvent trigger)
{
case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW:
return "withdraw";
+ case TALER_KYCLOGIC_KYC_TRIGGER_AGE_WITHDRAW:
+ return "age-withdraw";
case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT:
return "deposit";
case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE:
return "merge";
case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE:
return "balance";
+ case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE:
+ return "close";
}
GNUNET_break (0);
return NULL;
@@ -226,7 +238,7 @@ TALER_KYCLOGIC_kyc_user_type_from_string (const char *ut_s,
struct
{
const char *in;
- enum TALER_KYCLOGIC_KycTriggerEvent out;
+ enum TALER_KYCLOGIC_KycUserType out;
} map [] = {
{ "individual", TALER_KYCLOGIC_KYC_UT_INDIVIDUAL },
{ "business", TALER_KYCLOGIC_KYC_UT_BUSINESS },
@@ -262,6 +274,38 @@ TALER_KYCLOGIC_kyc_user_type2s (enum TALER_KYCLOGIC_KycUserType ut)
}
+enum GNUNET_GenericReturnValue
+TALER_KYCLOGIC_check_satisfiable (
+ const char *check_name)
+{
+ for (unsigned int i = 0; i<num_kyc_checks; i++)
+ if (0 == strcmp (check_name,
+ kyc_checks[i]->name))
+ return GNUNET_OK;
+ if (0 == strcmp (check_name,
+ KYC_CHECK_IMPOSSIBLE))
+ return GNUNET_NO;
+ return GNUNET_SYSERR;
+}
+
+
+json_t *
+TALER_KYCLOGIC_get_satisfiable ()
+{
+ json_t *requirements;
+
+ requirements = json_array ();
+ GNUNET_assert (NULL != requirements);
+ for (unsigned int i = 0; i<num_kyc_checks; i++)
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (
+ requirements,
+ json_string (kyc_checks[i]->name)));
+ return requirements;
+}
+
+
/**
* Load KYC logic plugin.
*
@@ -279,20 +323,32 @@ load_logic (const struct GNUNET_CONFIGURATION_Handle *cfg,
GNUNET_asprintf (&lib_name,
"libtaler_plugin_kyclogic_%s",
name);
+ for (unsigned int i = 0; i<num_kyc_logics; i++)
+ if (0 == strcmp (lib_name,
+ kyc_logics[i]->library_name))
+ {
+ GNUNET_free (lib_name);
+ return kyc_logics[i];
+ }
plugin = GNUNET_PLUGIN_load (lib_name,
(void *) cfg);
- if (NULL != plugin)
- plugin->library_name = lib_name;
- else
+ if (NULL == plugin)
+ {
GNUNET_free (lib_name);
+ return NULL;
+ }
+ plugin->library_name = lib_name;
+ plugin->name = GNUNET_strdup (name);
+ GNUNET_array_append (kyc_logics,
+ num_kyc_logics,
+ plugin);
return plugin;
}
/**
- * Add check type to global array of checks.
- * First checks if the type already exists, otherwise
- * adds a new one.
+ * Add check type to global array of checks. First checks if the type already
+ * exists, otherwise adds a new one.
*
* @param check name of the check
* @return pointer into the global list
@@ -316,9 +372,8 @@ add_check (const char *check)
/**
- * Parse list of checks from @a checks and build an
- * array of aliases into the global checks array
- * in @a provided_checks.
+ * Parse list of checks from @a checks and build an array of aliases into the
+ * global checks array in @a provided_checks.
*
* @param[in,out] checks list of checks; clobbered
* @param[out] p_checks where to put array of aliases
@@ -471,6 +526,14 @@ add_provider (const struct GNUNET_CONFIGURATION_Handle *cfg,
}
+/**
+ * Parse configuration @a cfg in section @a section for
+ * the specification of a KYC trigger.
+ *
+ * @param cfg configuration to parse
+ * @param section configuration section to parse
+ * @return #GNUNET_OK on success
+ */
static enum GNUNET_GenericReturnValue
add_trigger (const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *section)
@@ -562,6 +625,29 @@ add_trigger (const struct GNUNET_CONFIGURATION_Handle *cfg,
GNUNET_array_append (kyc_triggers,
num_kyc_triggers,
kt);
+ for (unsigned int i = 0; i<kt->num_checks; i++)
+ {
+ const struct TALER_KYCLOGIC_KycCheck *ck = kt->required_checks[i];
+
+ if (0 != ck->num_providers)
+ continue;
+ if (0 == strcmp (ck->name,
+ KYC_CHECK_IMPOSSIBLE))
+ continue;
+ {
+ char *msg;
+
+ GNUNET_asprintf (&msg,
+ "Required check `%s' cannot be satisfied: not provided by any provider",
+ ck->name);
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "REQUIRED_CHECKS",
+ msg);
+ GNUNET_free (msg);
+ }
+ return GNUNET_SYSERR;
+ }
}
return GNUNET_OK;
}
@@ -591,8 +677,8 @@ struct SectionContext
* @param section name of the section
*/
static void
-handle_section (void *cls,
- const char *section)
+handle_provider_section (void *cls,
+ const char *section)
{
struct SectionContext *sc = cls;
@@ -606,6 +692,21 @@ handle_section (void *cls,
sc->result = false;
return;
}
+}
+
+
+/**
+ * Function to iterate over configuration sections.
+ *
+ * @param cls a `struct SectionContext *`
+ * @param section name of the section
+ */
+static void
+handle_trigger_section (void *cls,
+ const char *section)
+{
+ struct SectionContext *sc = cls;
+
if (0 == strncasecmp (section,
"kyc-legitimization-",
strlen ("kyc-legitimization-")))
@@ -657,7 +758,10 @@ TALER_KYCLOGIC_kyc_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
};
GNUNET_CONFIGURATION_iterate_sections (cfg,
- &handle_section,
+ &handle_provider_section,
+ &sc);
+ GNUNET_CONFIGURATION_iterate_sections (cfg,
+ &handle_trigger_section,
&sc);
if (! sc.result)
{
@@ -676,10 +780,11 @@ TALER_KYCLOGIC_kyc_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
TALER_KYCLOGIC_kyc_done ();
return GNUNET_SYSERR;
}
- qsort (kyc_triggers,
- num_kyc_triggers,
- sizeof (struct TALER_KYCLOGIC_KycTrigger *),
- &sort_by_timeframe);
+ if (0 != num_kyc_triggers)
+ qsort (kyc_triggers,
+ num_kyc_triggers,
+ sizeof (struct TALER_KYCLOGIC_KycTrigger *),
+ &sort_by_timeframe);
return GNUNET_OK;
}
@@ -717,6 +822,7 @@ TALER_KYCLOGIC_kyc_done (void)
struct TALER_KYCLOGIC_Plugin *lp = kyc_logics[i];
char *lib_name = lp->library_name;
+ GNUNET_free (lp->name);
GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
lp));
GNUNET_free (lib_name);
@@ -728,6 +834,9 @@ TALER_KYCLOGIC_kyc_done (void)
{
struct TALER_KYCLOGIC_KycCheck *kc = kyc_checks[i];
+ GNUNET_array_grow (kc->providers,
+ kc->num_providers,
+ 0);
GNUNET_free (kc->name);
GNUNET_free (kc);
}
@@ -797,6 +906,9 @@ eval_trigger (void *cls,
struct GNUNET_TIME_Relative duration;
bool bump = true;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC check with new amount %s\n",
+ TALER_amount2s (amount));
duration = GNUNET_TIME_absolute_get_duration (date);
if (ttc->have_total)
{
@@ -812,19 +924,31 @@ eval_trigger (void *cls,
else
{
ttc->total = *amount;
+ ttc->have_total = true;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC check: new total is %s\n",
+ TALER_amount2s (&ttc->total));
for (unsigned int i = ttc->start; i<num_kyc_triggers; i++)
{
const struct TALER_KYCLOGIC_KycTrigger *kt = kyc_triggers[i];
if (ttc->event != kt->trigger)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC check #%u: trigger type does not match\n",
+ i);
continue;
+ }
duration = GNUNET_TIME_relative_max (duration,
kt->timeframe);
if (GNUNET_TIME_relative_cmp (kt->timeframe,
>,
duration))
{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC check #%u: amount is beyond time limit\n",
+ i);
if (bump)
ttc->start = i;
return GNUNET_OK;
@@ -833,6 +957,9 @@ eval_trigger (void *cls,
TALER_amount_cmp (&ttc->total,
&kt->threshold))
{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC check #%u: amount is below threshold\n",
+ i);
if (bump)
ttc->start = i;
bump = false;
@@ -848,6 +975,9 @@ eval_trigger (void *cls,
for (unsigned int k = 0; k<*ttc->needed_cnt; k++)
if (ttc->needed[k] == rc)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC rule #%u already listed\n",
+ j);
found = true;
break;
}
@@ -857,6 +987,11 @@ eval_trigger (void *cls,
(*ttc->needed_cnt)++;
}
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC check #%u (%s) is applicable, %u checks needed so far\n",
+ i,
+ ttc->needed[(*ttc->needed_cnt) - 1]->name,
+ *ttc->needed_cnt);
}
if (bump)
return GNUNET_NO; /* we hit all possible triggers! */
@@ -880,6 +1015,10 @@ struct RemoveContext
*/
unsigned int *needed_cnt;
+ /**
+ * Object with information about collected KYC data.
+ */
+ json_t *kyc_details;
};
@@ -903,13 +1042,30 @@ remove_satisfied (void *cls,
if (0 != strcasecmp (provider_name,
kp->provider_section_name))
continue;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Provider `%s' satisfied\n",
+ provider_name);
for (unsigned int j = 0; j<kp->num_checks; j++)
{
const struct TALER_KYCLOGIC_KycCheck *kc = kp->provided_checks[j];
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Provider satisfies check `%s'\n",
+ kc->name);
+ if (NULL != rc->kyc_details)
+ {
+ GNUNET_assert (0 ==
+ json_object_set_new (
+ rc->kyc_details,
+ kc->name,
+ json_object ()));
+ }
for (unsigned int k = 0; k<*rc->needed_cnt; k++)
if (kc == rc->needed[k])
{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Removing check `%s' from list\n",
+ kc->name);
rc->needed[k] = rc->needed[*rc->needed_cnt - 1];
(*rc->needed_cnt)--;
if (0 == *rc->needed_cnt)
@@ -922,20 +1078,19 @@ remove_satisfied (void *cls,
}
-const char *
+enum GNUNET_DB_QueryStatus
TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
const struct TALER_PaytoHashP *h_payto,
TALER_KYCLOGIC_KycSatisfiedIterator ki,
void *ki_cls,
TALER_KYCLOGIC_KycAmountIterator ai,
- void *ai_cls)
+ void *ai_cls,
+ char **required)
{
struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks];
unsigned int needed_cnt = 0;
+ char *ret;
struct GNUNET_TIME_Relative timeframe;
- unsigned long long min_cost = ULONG_LONG_MAX;
- unsigned int max_checks = 0;
- const struct TALER_KYCLOGIC_KycProvider *kp_best = NULL;
timeframe = GNUNET_TIME_UNIT_ZERO;
for (unsigned int i = 0; i<num_kyc_triggers; i++)
@@ -963,7 +1118,40 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
&ttc);
}
if (0 == needed_cnt)
- return NULL;
+ {
+ *required = NULL;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ timeframe = GNUNET_TIME_UNIT_ZERO;
+ for (unsigned int i = 0; i<num_kyc_triggers; i++)
+ {
+ const struct TALER_KYCLOGIC_KycTrigger *kt = kyc_triggers[i];
+
+ if (event != kt->trigger)
+ continue;
+ timeframe = GNUNET_TIME_relative_max (timeframe,
+ kt->timeframe);
+ }
+ {
+ struct GNUNET_TIME_Absolute now;
+ struct ThresholdTestContext ttc = {
+ .event = event,
+ .needed = needed,
+ .needed_cnt = &needed_cnt
+ };
+
+ now = GNUNET_TIME_absolute_get ();
+ ai (ai_cls,
+ GNUNET_TIME_absolute_subtract (now,
+ timeframe),
+ &eval_trigger,
+ &ttc);
+ }
+ if (0 == needed_cnt)
+ {
+ *required = NULL;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
{
struct RemoveContext rc = {
.needed = needed,
@@ -973,14 +1161,206 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
/* Check what provider checks are already satisfied for h_payto (with
database), remove those from the 'needed' array. */
- GNUNET_break (0);
- // FIXME: do via callback!
qs = ki (ki_cls,
h_payto,
- &
- remove_satisfied,
+ &remove_satisfied,
+ &rc);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+ }
+ if (0 == needed_cnt)
+ {
+ *required = NULL;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ {
+ struct RemoveContext rc = {
+ .needed = needed,
+ .needed_cnt = &needed_cnt
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Check what provider checks are already satisfied for h_payto (with
+ database), remove those from the 'needed' array. */
+ qs = ki (ki_cls,
+ h_payto,
+ &remove_satisfied,
+ &rc);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+ }
+ if (0 == needed_cnt)
+ {
+ *required = NULL;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ ret = NULL;
+ for (unsigned int k = 0; k<needed_cnt; k++)
+ {
+ const struct TALER_KYCLOGIC_KycCheck *kc = needed[k];
+
+ if (NULL == ret)
+ {
+ ret = GNUNET_strdup (kc->name);
+ }
+ else /* append */
+ {
+ char *tmp = ret;
+
+ GNUNET_asprintf (&ret,
+ "%s %s",
+ tmp,
+ kc->name);
+ GNUNET_free (tmp);
+ }
+ }
+ *required = ret;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
+
+
+void
+TALER_KYCLOGIC_kyc_get_details (
+ const char *logic_name,
+ TALER_KYCLOGIC_DetailsCallback cb,
+ void *cb_cls)
+{
+ for (unsigned int i = 0; i<num_kyc_providers; i++)
+ {
+ struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
+
+ if (0 !=
+ strcmp (kp->logic->name,
+ logic_name))
+ continue;
+ if (GNUNET_OK !=
+ cb (cb_cls,
+ kp->pd,
+ kp->logic->cls))
+ return;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_KYCLOGIC_check_satisfied (char **requirements,
+ const struct TALER_PaytoHashP *h_payto,
+ json_t **kyc_details,
+ TALER_KYCLOGIC_KycSatisfiedIterator ki,
+ void *ki_cls,
+ bool *satisfied)
+{
+ struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks];
+ unsigned int needed_cnt = 0;
+
+ if (NULL == requirements)
+ {
+ *satisfied = true;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ {
+ char *req = *requirements;
+
+ for (const char *tok = strtok (req, " ");
+ NULL != tok;
+ tok = strtok (NULL, " "))
+ needed[needed_cnt++] = add_check (tok);
+ GNUNET_free (req);
+ *requirements = NULL;
+ }
+
+ {
+ struct RemoveContext rc = {
+ .needed = needed,
+ .needed_cnt = &needed_cnt,
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ rc.kyc_details = json_object ();
+ GNUNET_assert (NULL != rc.kyc_details);
+
+ /* Check what provider checks are already satisfied for h_payto (with
+ database), remove those from the 'needed' array. */
+ qs = ki (ki_cls,
+ h_payto,
+ &remove_satisfied,
&rc);
- GNUNET_break (qs >= 0); // FIXME: handle DB failure more nicely?
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ *satisfied = false;
+ return qs;
+ }
+ if (0 != needed_cnt)
+ {
+ json_decref (rc.kyc_details);
+ *kyc_details = NULL;
+ }
+ else
+ {
+ *kyc_details = rc.kyc_details;
+ }
+ }
+ *satisfied = (0 == needed_cnt);
+
+ {
+ char *res = NULL;
+
+ for (unsigned int i = 0; i<needed_cnt; i++)
+ {
+ const struct TALER_KYCLOGIC_KycCheck *need = needed[i];
+
+ if (NULL == res)
+ {
+ res = GNUNET_strdup (need->name);
+ }
+ else
+ {
+ char *tmp;
+
+ GNUNET_asprintf (&tmp,
+ "%s %s",
+ res,
+ need->name);
+ GNUNET_free (res);
+ res = tmp;
+ }
+ }
+ *requirements = res;
+ }
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_KYCLOGIC_requirements_to_logic (const char *requirements,
+ enum TALER_KYCLOGIC_KycUserType ut,
+ struct TALER_KYCLOGIC_Plugin **plugin,
+ struct TALER_KYCLOGIC_ProviderDetails **pd,
+ const char **configuration_section)
+{
+ struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks];
+ unsigned int needed_cnt = 0;
+ unsigned long long min_cost = ULLONG_MAX;
+ unsigned int max_checks = 0;
+ const struct TALER_KYCLOGIC_KycProvider *kp_best = NULL;
+
+ if (NULL == requirements)
+ return GNUNET_NO;
+ {
+ char *req = GNUNET_strdup (requirements);
+
+ for (const char *tok = strtok (req, " ");
+ NULL != tok;
+ tok = strtok (NULL, " "))
+ needed[needed_cnt++] = add_check (tok);
+ GNUNET_free (req);
}
/* Count maximum number of remaining checks covered by any
@@ -990,6 +1370,8 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
const struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
unsigned int matched = 0;
+ if (kp->user_type != ut)
+ continue;
for (unsigned int j = 0; j<kp->num_checks; j++)
{
const struct TALER_KYCLOGIC_KycCheck *kc = kp->provided_checks[j];
@@ -1004,6 +1386,8 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
max_checks = GNUNET_MAX (max_checks,
matched);
}
+ if (0 == max_checks)
+ return GNUNET_SYSERR;
/* Find min-cost provider covering max_checks. */
for (unsigned int i = 0; i<num_kyc_providers; i++)
@@ -1011,6 +1395,8 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
const struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
unsigned int matched = 0;
+ if (kp->user_type != ut)
+ continue;
for (unsigned int j = 0; j<kp->num_checks; j++)
{
const struct TALER_KYCLOGIC_KycCheck *kc = kp->provided_checks[j];
@@ -1029,34 +1415,98 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,
kp_best = kp;
}
}
-
GNUNET_assert (NULL != kp_best);
- return kp_best->provider_section_name;
+ *plugin = kp_best->logic;
+ *pd = kp_best->pd;
+ *configuration_section = kp_best->provider_section_name;
+ return GNUNET_OK;
}
enum GNUNET_GenericReturnValue
-TALER_KYCLOGIC_kyc_get_logic (const char *provider_section_name,
- struct TALER_KYCLOGIC_Plugin **plugin,
- struct TALER_KYCLOGIC_ProviderDetails **pd)
+TALER_KYCLOGIC_lookup_logic (const char *name,
+ struct TALER_KYCLOGIC_Plugin **plugin,
+ struct TALER_KYCLOGIC_ProviderDetails **pd,
+ const char **provider_section)
{
for (unsigned int i = 0; i<num_kyc_providers; i++)
{
struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
if (0 !=
- strcasecmp (provider_section_name,
+ strcasecmp (name,
kp->provider_section_name))
continue;
*plugin = kp->logic;
*pd = kp->pd;
+ *provider_section = kp->provider_section_name;
+ return GNUNET_OK;
+ }
+ for (unsigned int i = 0; i<num_kyc_logics; i++)
+ {
+ struct TALER_KYCLOGIC_Plugin *logic = kyc_logics[i];
+
+ if (0 !=
+ strcasecmp (logic->name,
+ name))
+ continue;
+ *plugin = logic;
+ *pd = NULL;
+ *provider_section = NULL;
return GNUNET_OK;
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Provider `%s' unknown\n",
- provider_section_name);
+ name);
return GNUNET_SYSERR;
}
+void
+TALER_KYCLOGIC_kyc_iterate_thresholds (
+ enum TALER_KYCLOGIC_KycTriggerEvent event,
+ TALER_KYCLOGIC_KycThresholdIterator it,
+ void *it_cls)
+{
+ for (unsigned int i = 0; i<num_kyc_triggers; i++)
+ {
+ const struct TALER_KYCLOGIC_KycTrigger *kt = kyc_triggers[i];
+
+ if (event != kt->trigger)
+ continue;
+ it (it_cls,
+ &kt->threshold);
+ }
+}
+
+
+void
+TALER_KYCLOGIC_lookup_checks (const char *section_name,
+ unsigned int *num_checks,
+ char ***provided_checks)
+{
+ *num_checks = 0;
+ *provided_checks = NULL;
+ for (unsigned int i = 0; i<num_kyc_providers; i++)
+ {
+ struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
+
+ if (0 !=
+ strcasecmp (section_name,
+ kp->provider_section_name))
+ continue;
+ *num_checks = kp->num_checks;
+ if (0 != kp->num_checks)
+ {
+ char **pc = GNUNET_new_array (kp->num_checks,
+ char *);
+ for (unsigned int i = 0; i<kp->num_checks; i++)
+ pc[i] = GNUNET_strdup (kp->provided_checks[i]->name);
+ *provided_checks = pc;
+ }
+ return;
+ }
+}
+
+
/* end of taler-exchange-httpd_kyc.c */