diff options
| author | Christian Grothoff <christian@grothoff.org> | 2022-08-09 13:00:58 +0200 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2022-08-09 13:00:58 +0200 | 
| commit | d58334cf89f2c43dcd20e4a8deb01f45c852f7df (patch) | |
| tree | df358c94144249d518b010518244caca1d7c50fa /src | |
| parent | f50a2e11b09d67eaa1db3b2de882294f08c2847a (diff) | |
implement kyc-proof hook in kyc-tester
Diffstat (limited to 'src')
| -rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-webhook.c | 2 | ||||
| -rw-r--r-- | src/include/taler_kyclogic_plugin.h | 4 | ||||
| -rw-r--r-- | src/kyclogic/plugin_kyclogic_oauth2.c | 2 | ||||
| -rw-r--r-- | src/kyclogic/plugin_kyclogic_template.c | 2 | ||||
| -rw-r--r-- | src/kyclogic/taler-exchange-kyc-tester.c | 253 | 
5 files changed, 242 insertions, 21 deletions
| diff --git a/src/exchange/taler-exchange-httpd_kyc-webhook.c b/src/exchange/taler-exchange-httpd_kyc-webhook.c index bba8e1a5..6faa2556 100644 --- a/src/exchange/taler-exchange-httpd_kyc-webhook.c +++ b/src/exchange/taler-exchange-httpd_kyc-webhook.c @@ -272,7 +272,7 @@ handler_kyc_webhook_generic (                    kwh->logic);        return TALER_MHD_reply_with_error (rc->connection,                                           MHD_HTTP_NOT_FOUND, -                                         TALER_EC_EXCHANGE_KYC_WEBHOOK_LOGIC_UNKNOWN, +                                         TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN,                                           "$LOGIC");      }      kwh->wh = kwh->plugin->webhook (kwh->plugin->cls, diff --git a/src/include/taler_kyclogic_plugin.h b/src/include/taler_kyclogic_plugin.h index 8e52e051..a4bddde6 100644 --- a/src/include/taler_kyclogic_plugin.h +++ b/src/include/taler_kyclogic_plugin.h @@ -292,7 +292,7 @@ struct TALER_KYCLOGIC_Plugin     *     * @param cls the @e cls of this struct with the plugin-specific state     * @param pd provider configuration details -   * @param url_path rest of the URL after `/kyc-webhook/` +   * @param url_path rest of the URL after `/kyc-webhook/$H_PAYTO/$LOGIC`     * @param connection MHD connection object (for HTTP headers)     * @param account_id which account to trigger process for     * @param provider_user_id user ID (or NULL) the proof is for @@ -304,7 +304,7 @@ struct TALER_KYCLOGIC_Plugin    struct TALER_KYCLOGIC_ProofHandle *    (*proof)(void *cls,             const struct TALER_KYCLOGIC_ProviderDetails *pd, -           const char *url_path, +           const char *const url_path[],             struct MHD_Connection *connection,             const struct TALER_PaytoHashP *account_id,             const char *provider_user_id, diff --git a/src/kyclogic/plugin_kyclogic_oauth2.c b/src/kyclogic/plugin_kyclogic_oauth2.c index 0a19a849..cbf5ea3a 100644 --- a/src/kyclogic/plugin_kyclogic_oauth2.c +++ b/src/kyclogic/plugin_kyclogic_oauth2.c @@ -767,7 +767,7 @@ handle_curl_proof_finished (void *cls,  static struct TALER_KYCLOGIC_ProofHandle *  oauth2_proof (void *cls,                const struct TALER_KYCLOGIC_ProviderDetails *pd, -              const char *url_path, +              const char *const url_path[],                struct MHD_Connection *connection,                const struct TALER_PaytoHashP *account_id,                const char *provider_user_id, diff --git a/src/kyclogic/plugin_kyclogic_template.c b/src/kyclogic/plugin_kyclogic_template.c index e59c15da..f5e583db 100644 --- a/src/kyclogic/plugin_kyclogic_template.c +++ b/src/kyclogic/plugin_kyclogic_template.c @@ -262,7 +262,7 @@ template_initiate_cancel (struct TALER_KYCLOGIC_InitiateHandle *ih)  static struct TALER_KYCLOGIC_ProofHandle *  template_proof (void *cls,                  const struct TALER_KYCLOGIC_ProviderDetails *pd, -                const char *url_path, +                const char *const url_path[],                  struct MHD_Connection *connection,                  const struct TALER_PaytoHashP *account_id,                  const char *provider_user_id, diff --git a/src/kyclogic/taler-exchange-kyc-tester.c b/src/kyclogic/taler-exchange-kyc-tester.c index 753c6517..a389b081 100644 --- a/src/kyclogic/taler-exchange-kyc-tester.c +++ b/src/kyclogic/taler-exchange-kyc-tester.c @@ -162,6 +162,48 @@ struct TEKT_RequestHandler  /** + * Information we track per ongoing kyc-proof request. + */ +struct ProofRequestState +{ +  /** +   * Kept in a DLL. +   */ +  struct ProofRequestState *next; + +  /** +   * Kept in a DLL. +   */ +  struct ProofRequestState *prev; + +  /** +   * Handle for operation with the plugin. +   */ +  struct TALER_KYCLOGIC_ProofHandle *ph; + +  /** +   * Logic plugin we are using. +   */ +  struct TALER_KYCLOGIC_Plugin *logic; + +  /** +   * HTTP request details. +   */ +  struct TEKT_RequestContext *rc; + +}; + +/** + * Head of DLL. + */ +static struct ProofRequestState *rs_head; + +/** + * Tail of DLL. + */ +static struct ProofRequestState *rs_tail; + +/**   * The exchange's configuration (global)   */  static const struct GNUNET_CONFIGURATION_Handle *TEKT_cfg; @@ -182,6 +224,16 @@ static char *TEKT_base_url;  static struct TALER_PaytoHashP cmd_line_h_payto;  /** + * Provider user ID to use. + */ +static char *cmd_provider_user_id; + +/** + * Provider legitimization ID to use. + */ +static char *cmd_provider_legitimization_id; + +/**   * Row ID to use, override with '-r'   */  static unsigned int kyc_row_id = 42; @@ -214,7 +266,7 @@ static struct TALER_KYCLOGIC_InitiateHandle *ih;  /**   * KYC logic running for @e ih.   */ -static struct TALER_KYCLOGIC_Plugin *logic; +static struct TALER_KYCLOGIC_Plugin *ih_logic;  /**   * Port to run the daemon on. @@ -484,7 +536,7 @@ handler_kyc_webhook_generic (                    kwh->logic);        return TALER_MHD_reply_with_error (rc->connection,                                           MHD_HTTP_NOT_FOUND, -                                         TALER_EC_EXCHANGE_KYC_WEBHOOK_LOGIC_UNKNOWN, +                                         TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN,                                           "$LOGIC");      }      kwh->wh = kwh->plugin->webhook (kwh->plugin->cls, @@ -531,6 +583,13 @@ handler_kyc_webhook_generic (  } +/** + * Handle a GET "/kyc-webhook" request. + * + * @param rc request to handle + * @param args one argument with the payment_target_uuid + * @return MHD result code + */  static MHD_RESULT  handler_kyc_webhook_get (    struct TEKT_RequestContext *rc, @@ -543,6 +602,14 @@ handler_kyc_webhook_get (  } +/** + * Handle a POST "/kyc-webhook" request. + * + * @param rc request to handle + * @param root uploaded JSON body (can be NULL) + * @param args one argument with the payment_target_uuid + * @return MHD result code + */  static MHD_RESULT  handler_kyc_webhook_post (    struct TEKT_RequestContext *rc, @@ -557,6 +624,127 @@ handler_kyc_webhook_post (  /** + * Function called with the result of a proof check operation. + * + * Note that the "decref" for the @a response + * will be done by the callee and MUST NOT be done by the plugin. + * + * @param cls closure with the `struct ProofRequestState` + * @param status KYC status + * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown + * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown + * @param expiration until when is the KYC check valid + * @param http_status HTTP status code of @a response + * @param[in] response to return to the HTTP client + */ +static void +proof_cb ( +  void *cls, +  enum TALER_KYCLOGIC_KycStatus status, +  const char *provider_user_id, +  const char *provider_legitimization_id, +  struct GNUNET_TIME_Absolute expiration, +  unsigned int http_status, +  struct MHD_Response *response) +{ +  struct ProofRequestState *rs = cls; + +  MHD_resume_connection (rs->rc->connection); +  // FIXME: kick MHD event loop! +  // FIXME: actually queue response... +  GNUNET_CONTAINER_DLL_remove (rs_head, +                               rs_tail, +                               rs); +  GNUNET_free (rs); +} + + +/** + * Function called when we receive a 'GET' to the + * '/kyc-proof' endpoint. + * + * @param rc request context + * @param args remaining URL arguments; + *        args[0] is the 'h_payto', + *        args[1] should be the logic plugin name + */ +static MHD_RESULT +handler_kyc_proof_get ( +  struct TEKT_RequestContext *rc, +  const char *const args[]) +{ +  struct TALER_PaytoHashP h_payto; +  struct TALER_KYCLOGIC_ProviderDetails *pd; +  struct TALER_KYCLOGIC_Plugin *logic; +  struct ProofRequestState *rs; + +  if ( (NULL == args[0]) || +       (NULL == args[1]) ) +  { +    GNUNET_break_op (0); +    return TALER_MHD_reply_with_error (rc->connection, +                                       MHD_HTTP_NOT_FOUND, +                                       TALER_EC_GENERIC_ENDPOINT_UNKNOWN, +                                       "'/$H_PAYTO/$LOGIC' required after '/kyc-proof'"); +  } +  if (GNUNET_OK != +      GNUNET_STRINGS_string_to_data (args[0], +                                     strlen (args[0]), +                                     &h_payto, +                                     sizeof (h_payto))) +  { +    GNUNET_break_op (0); +    return TALER_MHD_reply_with_error (rc->connection, +                                       MHD_HTTP_BAD_REQUEST, +                                       TALER_EC_GENERIC_PARAMETER_MALFORMED, +                                       "h_payto"); +  } +  if (0 != +      GNUNET_memcmp (&h_payto, +                     &cmd_line_h_payto)) +  { +    GNUNET_break_op (0); +    return TALER_MHD_reply_with_error (rc->connection, +                                       MHD_HTTP_NOT_FOUND, +                                       TALER_EC_EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN, +                                       "h_payto"); +  } + +  if (GNUNET_OK != +      TALER_KYCLOGIC_kyc_get_logic (args[1], +                                    &logic, +                                    &pd)) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Could not initiate KYC with provider `%s' (configuration error?)\n", +                initiate_section); +    return TALER_MHD_reply_with_error (rc->connection, +                                       MHD_HTTP_NOT_FOUND, +                                       TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN, +                                       args[1]); +  } +  rs = GNUNET_new (struct ProofRequestState); +  rs->rc = rc; +  rs->logic = logic; +  MHD_suspend_connection (rc->connection); +  GNUNET_CONTAINER_DLL_insert (rs_head, +                               rs_tail, +                               rs); +  rs->ph = logic->proof (logic->cls, +                         pd, +                         &args[2], +                         rc->connection, +                         &h_payto, +                         cmd_provider_user_id, +                         cmd_provider_legitimization_id, +                         &proof_cb, +                         rs); +  GNUNET_assert (NULL != rs->ph); +  return MHD_YES; +} + + +/**   * Function called whenever MHD is done with a request.  If the   * request was a POST, we may have stored a `struct Buffer *` in the   * @a con_cls that might still need to be cleaned up.  Call the @@ -757,15 +945,14 @@ handle_mhd_request (void *cls,                      void **con_cls)  {    static struct TEKT_RequestHandler handlers[] = { -#if FIXME      /* simulated KYC endpoints */      {        .url = "kyc-proof",        .method = MHD_HTTP_METHOD_GET, -      .handler.get = &TEKT_handler_kyc_proof, -      .nargs = 1 +      .handler.get = &handler_kyc_proof_get, +      .nargs = 128, +      .nargs_is_upper_bound = true      }, -#endif      {        .url = "kyc-webhook",        .method = MHD_HTTP_METHOD_POST, @@ -993,11 +1180,21 @@ static void  do_shutdown (void *cls)  {    struct MHD_Daemon *mhd; -  (void) cls; +  struct ProofRequestState *rs; +  (void) cls; +  while (NULL != (rs = rs_head)) +  { +    GNUNET_CONTAINER_DLL_remove (rs_head, +                                 rs_tail, +                                 rs); +    rs->logic->proof_cancel (rs->ph); +    MHD_resume_connection (rs->rc->connection); +    GNUNET_free (rs); +  }    if (NULL != ih)    { -    logic->initiate_cancel (ih); +    ih_logic->initiate_cancel (ih);      ih = NULL;    }    kyc_webhook_cleanup (); @@ -1050,10 +1247,16 @@ initiate_cb (      return;    }    fprintf (stdout, -           "Visit `%s' to begin KYC process (%s/%s)\n", +           "Visit `%s' to begin KYC process (-u: '%s', -l: '%s')\n",             redirect_url,             provider_user_id,             provider_legitimization_id); +  GNUNET_free (cmd_provider_user_id); +  GNUNET_free (cmd_provider_legitimization_id); +  if (NULL != provider_user_id) +    cmd_provider_user_id = GNUNET_strdup (provider_user_id); +  if (NULL != provider_legitimization_id) +    cmd_provider_legitimization_id = GNUNET_strdup (provider_legitimization_id);  } @@ -1113,7 +1316,7 @@ run (void *cls,      if (GNUNET_OK !=          TALER_KYCLOGIC_kyc_get_logic (initiate_section, -                                      &logic, +                                      &ih_logic,                                        &pd))      {        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -1123,12 +1326,12 @@ run (void *cls,        GNUNET_SCHEDULER_shutdown ();        return;      } -    ih = logic->initiate (logic->cls, -                          pd, -                          &cmd_line_h_payto, -                          kyc_row_id, -                          &initiate_cb, -                          NULL); +    ih = ih_logic->initiate (ih_logic->cls, +                             pd, +                             &cmd_line_h_payto, +                             kyc_row_id, +                             &initiate_cb, +                             NULL);      GNUNET_break (NULL != ih);    }    if (run_webservice) @@ -1217,6 +1420,24 @@ main (int argc,        "SECTION_NAME",        "initiate KYC check using provider configured in SECTION_NAME of the configuration",        &initiate_section), +    GNUNET_GETOPT_option_string ( +      'i', +      "initiate", +      "SECTION_NAME", +      "initiate KYC check using provider configured in SECTION_NAME of the configuration", +      &initiate_section), +    GNUNET_GETOPT_option_string ( +      'u', +      "user", +      "ID", +      "use the given provider user ID (overridden if -i is also used)", +      &cmd_provider_user_id), +    GNUNET_GETOPT_option_string ( +      'l', +      "legitimization", +      "ID", +      "use the given provider legitimization ID (overridden if -i is also used)", +      &cmd_provider_legitimization_id),      GNUNET_GETOPT_option_base32_fixed_size (        'p',        "payto-hash", | 
