commit b45be8fd69052a93dbe92a6e6de8e537d8c82e8b
parent 92f069d89d5421da00412a62920471bf26ef777a
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 7 Jul 2024 15:03:00 +0200
WIP: kyc-start
Diffstat:
5 files changed, 258 insertions(+), 386 deletions(-)
diff --git a/src/exchange/taler-exchange-httpd_kyc-start.c b/src/exchange/taler-exchange-httpd_kyc-start.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 Affero General Public License as published by the Free Software
@@ -35,10 +35,21 @@
/**
- * Reserve GET request that is long-polling.
+ * POST request in asynchronous processing.
*/
struct KycPoller
{
+
+ /**
+ * Access token for the KYC data of the account.
+ */
+ struct TALER_AccountAccessTokenP access_token;
+
+ /**
+ * Hash of the payto:// URI we are starting to the KYC for.
+ */
+ struct TALER_PaytoHashP h_payto;
+
/**
* Kept in a DLL.
*/
@@ -66,55 +77,39 @@ struct KycPoller
struct TALER_KYCLOGIC_InitiateHandle *ih;
/**
- * Subscription for the database event we are
- * waiting for.
- */
- struct GNUNET_DB_EventHandler *eh;
-
- /**
- * Row of the requirement being started.
- */
- uint64_t requirement_row;
-
- /**
- * Row of KYC process being initiated.
+ * Set of applicable KYC measures.
*/
- uint64_t process_row;
+ json_t *jmeasures;
/**
- * Hash of the payto:// URI we are confirming to
- * have finished the KYC for.
+ * Where to redirect the user to start the KYC process.
*/
- struct TALER_PaytoHashP h_payto;
+ char *redirect_url;
/**
- * When will this request time out?
+ * Set to the name of the KYC provider.
*/
- struct GNUNET_TIME_Absolute timeout;
+ char *provider_name;
/**
- * Public limits that apply to the account,
- * if @e have_token is true.
- * NULL if no limits are public.
+ * Set to error details, on error (@ec not TALER_EC_NONE).
*/
- json_t *limits;
+ char *hint;
/**
- * Set to access token for a KYC process by the account,
- * if @e have_token is true.
+ * Row of the requirement being started.
*/
- struct TALER_AccountAccessTokenP access_token;
+ unsigned long long legitimization_measure_serial_id;
/**
- * Signature by the account owner authorizing this
- * operation.
+ * Row of KYC process being initiated.
*/
- union TALER_AccountSignatureP account_sig;
+ uint64_t process_row;
/**
- * Set to error details, on error (@ec not TALER_EC_NONE).
+ * Index of the measure this upload is for.
*/
- char *hint;
+ unsigned int measure_index;
/**
* Set to error encountered with KYC logic, if any.
@@ -122,41 +117,20 @@ struct KycPoller
enum TALER_ErrorCode ec;
/**
- * True if account is under AML review and this is
- * exposed.
- */
- bool aml_review;
-
- /**
- * True if @e access_token was initialized.
- */
- bool have_token;
-
- /**
* True if we are still suspended.
*/
bool suspended;
- /**
- * False if KYC is not required.
- */
- bool kyc_required;
-
- /**
- * True if we once tried the KYC initiation.
- */
- bool ih_done;
-
};
/**
- * Head of list of requests in long polling.
+ * Head of list of requests in asynchronous processing.
*/
static struct KycPoller *kyp_head;
/**
- * Tail of list of requests in long polling.
+ * Tail of list of requests in asynchronous processing.
*/
static struct KycPoller *kyp_tail;
@@ -197,27 +171,19 @@ kyp_cleanup (struct TEH_RequestContext *rc)
struct KycPoller *kyp = rc->rh_ctx;
GNUNET_assert (! kyp->suspended);
- if (NULL != kyp->eh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "Cancelling DB event listening\n");
- TEH_plugin->event_listen_cancel (TEH_plugin->cls,
- kyp->eh);
- kyp->eh = NULL;
- }
if (NULL != kyp->ih)
{
kyp->ih_logic->initiate_cancel (kyp->ih);
kyp->ih = NULL;
}
- json_decref (kyp->kyc_details);
- GNUNET_free (kyp->kyc_url);
+ GNUNET_free (kyp->redirect_url);
+ GNUNET_free (kyp->provider_name);
GNUNET_free (kyp->hint);
+ json_decref (kyp->jmeasures);
GNUNET_free (kyp);
}
-#if FIXME
/**
* Function called with the result of a KYC initiation
* operation.
@@ -242,7 +208,6 @@ initiate_cb (
enum GNUNET_DB_QueryStatus qs;
kyp->ih = NULL;
- kyp->ih_done = true;
GNUNET_log (GNUNET_ERROR_TYPE_START,
"KYC initiation `%s' completed with ec=%d (%s)\n",
provider_legitimization_id,
@@ -253,16 +218,17 @@ initiate_cb (
kyp->ec = ec;
if (TALER_EC_NONE == ec)
{
- kyp->kyc_url = GNUNET_strdup (redirect_url);
+ kyp->redirect_url = GNUNET_strdup (redirect_url);
}
else
{
kyp->hint = GNUNET_strdup (error_msg_hint);
}
+ // FIXME: also store errors!
qs = TEH_plugin->update_kyc_process_by_row (
TEH_plugin->cls,
kyp->process_row,
- kyp->section_name,
+ kyp->provider_name,
&kyp->h_payto,
provider_user_id,
provider_legitimization_id,
@@ -285,221 +251,6 @@ initiate_cb (
}
-#endif
-
-
-/**
- * Function implementing database transaction to start wallet's KYC status.
- * Runs the transaction logic; IF it returns a non-error code, the transaction
- * logic MUST NOT queue a MHD response. IF it returns an hard error, the
- * transaction logic MUST queue a MHD response and set @a mhd_ret. IF it
- * returns the soft error code, the function MAY be called again to retry and
- * MUST not queue a MHD response.
- *
- * @param cls closure with a `struct KycPoller *`
- * @param connection MHD request which triggered the transaction
- * @param[out] mhd_ret set to MHD response status for @a connection,
- * if transaction failed (!)
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-kyc_start (void *cls,
- struct MHD_Connection *connection,
- MHD_RESULT *mhd_ret)
-{
-#if FIXME
- struct KycPoller *kyp = cls;
- enum GNUNET_DB_QueryStatus qs;
- struct TALER_KYCLOGIC_ProviderDetails *pd;
- enum GNUNET_GenericReturnValue ret;
- struct TALER_PaytoHashP h_payto;
- char *requirements;
- char *redirect_url;
- bool satisfied;
-
- qs = TEH_plugin->lookup_kyc_requirement_by_row (
- TEH_plugin->cls,
- kyp->requirement_row,
- &requirements,
- &h_payto);
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "No KYC requirements open for %llu\n",
- (unsigned long long) kyp->requirement_row);
- return qs;
- }
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
- return qs;
- }
- if (0 !=
- GNUNET_memcmp (&kyp->h_payto,
- &h_payto))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Requirement %llu provided, but h_payto does not match\n",
- (unsigned long long) kyp->requirement_row);
- GNUNET_break_op (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_EXCHANGE_KYC_START_AUTHORIZATION_FAILED,
- "h_payto");
- GNUNET_free (requirements);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- qs = TALER_KYCLOGIC_start_satisfied (
- &requirements,
- &h_payto,
- &kyp->kyc_details,
- TEH_plugin->select_satisfied_kyc_processes,
- TEH_plugin->cls,
- &satisfied);
- if (qs < 0)
- {
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- return qs;
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "kyc_test_required");
- GNUNET_free (requirements);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (satisfied)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "KYC requirements `%s' already satisfied\n",
- requirements);
- GNUNET_free (requirements);
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
-
- kyp->kyc_required = true;
- ret = TALER_KYCLOGIC_requirements_to_logic (requirements,
- &kyp->ih_logic,
- &pd,
- &kyp->section_name);
- if (GNUNET_OK != ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "KYC requirements `%s' cannot be started, but are set as required in database!\n",
- requirements);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_GONE,
- requirements);
- GNUNET_free (requirements);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- GNUNET_free (requirements);
-
- if (kyp->ih_done)
- return qs;
- qs = TEH_plugin->get_pending_kyc_requirement_process (
- TEH_plugin->cls,
- &h_payto,
- kyp->section_name,
- &redirect_url);
- if (qs < 0)
- {
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- return qs;
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "insert_kyc_requirement_process");
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if ( (qs > 0) &&
- (NULL != redirect_url) )
- {
- kyp->kyc_url = redirect_url;
- return qs;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- /* set up new requirement process */
- qs = TEH_plugin->insert_kyc_requirement_process (
- TEH_plugin->cls,
- &h_payto,
- kyp->section_name,
- NULL,
- NULL,
- &kyp->process_row);
- if (qs < 0)
- {
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- return qs;
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "insert_kyc_requirement_process");
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "Initiating KYC start with logic %s\n",
- kyp->ih_logic->name);
- kyp->ih = kyp->ih_logic->initiate (kyp->ih_logic->cls,
- pd,
- &h_payto,
- kyp->process_row,
- &initiate_cb,
- kyp);
- GNUNET_break (NULL != kyp->ih);
- return qs;
-#else
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
-#endif
-}
-
-
-/**
- * Function called on events received from Postgres.
- * Wakes up long pollers.
- *
- * @param cls the `struct TEH_RequestContext *`
- * @param extra additional event data provided
- * @param extra_size number of bytes in @a extra
- */
-static void
-db_event_cb (void *cls,
- const void *extra,
- size_t extra_size)
-{
- struct TEH_RequestContext *rc = cls;
- struct KycPoller *kyp = rc->rh_ctx;
- struct GNUNET_AsyncScopeSave old_scope;
-
- (void) extra;
- (void) extra_size;
- if (! kyp->suspended)
- return; /* event triggered while main transaction
- was still running, or got multiple wake-up events */
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "Received KYC update event\n");
- kyp->suspended = false;
- GNUNET_async_scope_enter (&rc->async_scope_id,
- &old_scope);
- TEH_start_invariants ();
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "Resuming from long-polling on KYC status\n");
- GNUNET_CONTAINER_DLL_remove (kyp_head,
- kyp_tail,
- kyp);
- MHD_resume_connection (kyp->connection);
- TALER_MHD_daemon_trigger ();
- TEH_start_invariants ();
- GNUNET_async_scope_restore (&old_scope);
-}
-
-
MHD_RESULT
TEH_handler_kyc_start (
struct TEH_RequestContext *rc,
@@ -511,6 +262,9 @@ TEH_handler_kyc_start (
if (NULL == kyp)
{
+ enum GNUNET_DB_QueryStatus qs;
+ const struct TALER_KYCLOGIC_KycProvider *provider;
+
kyp = GNUNET_new (struct KycPoller);
kyp->connection = rc->connection;
rc->rh_ctx = kyp;
@@ -519,88 +273,185 @@ TEH_handler_kyc_start (
{
unsigned long long requirement_row;
char dummy;
+ const char *slash;
- if (1 !=
- sscanf (args[0],
- "%llu%c",
- &requirement_row,
+ slash = strchr (id, '-');
+ if (NULL == slash)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
+ rc->url);
+ }
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (id,
+ slash - id,
+ &kyp->access_token,
+ sizeof (kyp->access_token)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "Access token in ID is malformed");
+ }
+ if (2 !=
+ sscanf (slash + 1,
+ "%u-%llu%c",
+ &kyp->measure_index,
+ &kyp->legitimization_measure_serial_id,
&dummy))
{
GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "requirement_row");
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "ID is malformed");
}
- kyp->requirement_row = (uint64_t) requirement_row;
}
- TALER_MHD_parse_request_timeout (rc->connection,
- &kyp->timeout);
- }
- if ( (NULL == kyp->eh) &&
- GNUNET_TIME_absolute_is_future (kyp->timeout) )
- {
- struct TALER_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = kyp->h_payto
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "Starting DB event listening\n");
- kyp->eh = TEH_plugin->event_listen (
+ // FIXME: bad check, cannot return jmeasures,
+ // we need a redirect_url AND an EC to see if
+ // we should restart 'initiate' anyway!
+ qs = TEH_plugin->lookup_pending_legitimization (
TEH_plugin->cls,
- GNUNET_TIME_absolute_get_remaining (kyp->timeout),
- &rep.header,
- &db_event_cb,
- rc);
- }
+ kyp->legitimization_measure_serial_id,
+ &kyp->access_token,
+ &kyp->h_payto,
+ &kyp->jmeasures);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return TALER_MHD_reply_with_ec (
+ rc->connection,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "lookup_pending_legitimization");
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
+ rc->url);
+ }
- ret = TEH_DB_run_transaction (rc->connection,
- "kyc start",
- TEH_MT_REQUEST_OTHER,
- &res,
- &kyc_start,
- kyp);
- if (GNUNET_SYSERR == ret)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "Transaction failed.\n");
- return res;
- }
+ {
+ const char *check_name;
+ const char *prog_name;
+ const json_t *context;
+ json_t *req;
+
+ kyp->ec = TALER_KYCLOGIC_select_measure (
+ kyp->jmeasures,
+ kyp->measure_index,
+ &check_name,
+ &prog_name);
+ if (TALER_EC_NONE != kyp->ec)
+ {
+ /* return EC in next call to this function */
+ GNUNET_break_op (0);
+ kyp->hint
+ = GNUNET_strdup ("TALER_KYCLOGIC_select_measure");
+ return MHD_YES;
+ }
- if (TALER_EC_NONE != kyp->ec)
- {
- return TALER_MHD_reply_with_ec (rc->connection,
- kyp->ec,
- kyp->hint);
- }
+ provider = TALER_KYCLOGIC_check_to_provider (
+ check_name);
+ if (NULL == provider)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_CONFLICT,
+ 42, // FIXME: TALER_EC_EXCHANGE_BAD_CHECK_FOR_KYC_START,
+ check_name);
+ }
+ }
- if (NULL != kyp->ih)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "Suspending HTTP request on KYC logic...\n");
- kyp->suspended = true;
- GNUNET_CONTAINER_DLL_insert (kyp_head,
- kyp_tail,
- kyp);
- MHD_suspend_connection (kyp->connection);
- return MHD_YES;
- }
+ ret = TALER_KYCLOGIC_provider_to_logic (
+ provider,
+ &kyp->ih_logic,
+ &pd,
+ &kyp->provider_name);
+ if (GNUNET_OK != ret)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "KYC requirements `%s' cannot be started, but are set as required in database!\n",
+ requirements);
+ GNUNET_free (requirements);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_GONE,
+ NULL);
+ }
- /* long polling for positive result? */
- if ( (kyp->kyc_required) &&
- GNUNET_TIME_absolute_is_future (kyp->timeout))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "Suspending HTTP request on timeout (%s) now...\n",
- GNUNET_TIME_relative2s (GNUNET_TIME_absolute_get_remaining (
- kyp->timeout),
- true));
- GNUNET_assert (NULL != kyp->eh);
+ /* FIXME: the next two DB interactions should be ONE
+ transaction */
+ /* Check if we already initiated this process */
+ qs = TEH_plugin->get_pending_kyc_requirement_process (
+ TEH_plugin->cls,
+ &h_payto,
+ kyp->provider_name,
+ &kyp->redirect_url);
+ if (qs < 0)
+ {
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ return qs;
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "get_pending_kyc_requirement_process");
+ }
+ if (NULL != kyp->redirect_url)
+ return MHD_YES; /* success, return the redirect URL
+ (in next call to this function) */
+
+ /* set up new requirement process */
+ qs = TEH_plugin->insert_kyc_requirement_process (
+ TEH_plugin->cls,
+ &h_payto,
+ kyp->measure_index,
+ kyp->legitimization_measure_serial_id,
+ kyp->provider_name,
+ NULL, /* provider_account_id */
+ NULL, /* provider_legitimziation_id */
+ &kyp->process_row);
+ if (qs < 0)
+ {
+ GNUNET_break (0);
+ *mhd_ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_kyc_requirement_process");
+ }
+
+ kyp->ih = kyp->ih_logic->initiate (
+ kyp->ih_logic->cls,
+ pd,
+ &h_payto,
+ kyp->process_row,
+ &initiate_cb,
+ kyp);
+ if (NULL == kyp->ih)
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_BUG,
+ "initiate KYC process");
+ }
kyp->suspended = true;
- kyp->section_name = NULL;
GNUNET_CONTAINER_DLL_insert (kyp_head,
kyp_tail,
kyp);
@@ -608,34 +459,24 @@ TEH_handler_kyc_start (
return MHD_YES;
}
- /* KYC plugin generated reply? */
- if (kyp->have_token)
+ if ( (TALER_EC_NONE != kyp->ec) ||
+ (NULL == kyp->redirect_url) )
{
- return TALER_MHD_REPLY_JSON_PACK (
- rc->connection,
- kyp->kyc_required
- ? MHD_HTTP_ACCEPTED
- : MHD_HTTP_OK,
- GNUNET_JSON_pack_bool ("aml_review",
- kyp->aml_review),
- GNUNET_JSON_pack_data_auto ("access_token",
- &kyp->access_token),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_array_steal ("limits",
- kyp->limits)));
+ GNUNET_break (0);
+ if (TALER_EC_NONE == kyp->ec)
+ {
+ GNUNET_break (0);
+ kyp->ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ }
+ return TALER_MHD_reply_with_ec (rc->connection,
+ kyp->ec,
+ kyp->hint);
}
- l
- /* KYC not required */
- GNUNET_log (GNUNET_ERROR_TYPE_START,
- "KYC not required %llu\n",
- (unsigned long long) kyp->requirement_row);
-
- return TALER_MHD_reply_static (
+ return TALER_MHD_REPLY_JSON_PACK (
rc->connection,
- MHD_HTTP_NO_CONTENT,
- NULL,
- NULL,
- 0);
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_string ("redirect_url",
+ kyp->redirect_url));
}
diff --git a/src/exchange/taler-exchange-httpd_kyc-upload.c b/src/exchange/taler-exchange-httpd_kyc-upload.c
@@ -44,7 +44,7 @@ struct UploadContext
/**
* Index of the measure this upload is for.
*/
- unsigned long long measure_index;
+ unsigned int measure_index;
/**
* Index in the legitimization measures table this ID
@@ -294,7 +294,7 @@ TEH_handler_kyc_upload (struct TEH_RequestContext *rc,
rc->rh_ctx = uc;
rc->rh_cleaner = &upload_cleaner;
- slash = strchr (id, '/');
+ slash = strchr (id, '-');
if (NULL == slash)
{
GNUNET_break_op (0);
@@ -313,12 +313,12 @@ TEH_handler_kyc_upload (struct TEH_RequestContext *rc,
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (
rc->connection,
- MHD_HTTP_NOT_FOUND,
+ MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"Access token in ID is malformed");
}
if (2 != sscanf (slash + 1,
- "%llu/%llu%c",
+ "%u-%llu%c",
&uc->measure_index,
&uc->legitimization_measure_serial_id,
&dummy))
@@ -326,7 +326,7 @@ TEH_handler_kyc_upload (struct TEH_RequestContext *rc,
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (
rc->connection,
- MHD_HTTP_NOT_FOUND,
+ MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"ID is malformed");
}
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
@@ -4545,9 +4545,6 @@ void
TALER_EXCHANGE_kyc_info_cancel (struct TALER_EXCHANGE_KycInfoHandle *kih);
-// FIXME: /kyc-upload API?
-
-
/**
* Handle for an operation to start the KYC process.
*/
diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h
@@ -417,6 +417,27 @@ TALER_KYCLOGIC_rules_to_limits (const json_t *jrules);
/**
+ * Parse the given @a jmeasures and return the measure
+ * at the @a measure_index.
+ *
+ * @param jmeasures a LegitimizationMeasures object
+ * @param measure_index an index into the measures
+ * @param[out] check_name set to the name of the check
+ * @param[out] prog_name set to the name of the program
+ * @param[out] context set to the measure context
+ * (or NULL if there is no context)
+ * @return #TALER_EC_NONE on success
+ */
+enum TALER_ErrorCode
+TALER_KYCLOGIC_select_measure (
+ const json_t *jmeasures,
+ size_t measure_index,
+ const char **check_name,
+ const char **prog_name,
+ const json_t **context);
+
+
+/**
* Convert MeasureInformation into the
* KycRequirementInformation used by the client.
*
diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c
@@ -2326,4 +2326,17 @@ TALER_KYCLOGIC_get_measure_configuration (
}
+enum TALER_ErrorCode
+TALER_KYCLOGIC_select_measure (
+ const json_t *jmeasures,
+ size_t measure_index,
+ const char **check_name,
+ const char **prog_name,
+ const json_t **context)
+{
+ // parse jmeasures
+ // check measure_index is valid (in bounds and of right type)
+}
+
+
/* end of kyclogic_api.c */