diff options
| author | Christian Grothoff <christian@grothoff.org> | 2022-10-03 09:36:10 +0200 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2022-10-03 09:36:10 +0200 | 
| commit | 87ec6916c8d018566451ff941157d89e71dcd75a (patch) | |
| tree | 6c1ba32a6ec135d6173a6c1a647646d06f888a45 | |
| parent | 3bca75d6cfb4c28e9800198d606ae030930e126b (diff) | |
complete taler-exchange-httpd_reserves_attest.c logic (first pass, still without DB logic or tests)
| -rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_attest.c | 154 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_get_attest.c | 2 | 
2 files changed, 140 insertions, 16 deletions
| diff --git a/src/exchange/taler-exchange-httpd_reserves_attest.c b/src/exchange/taler-exchange-httpd_reserves_attest.c index 6a030dbd..a740bb25 100644 --- a/src/exchange/taler-exchange-httpd_reserves_attest.c +++ b/src/exchange/taler-exchange-httpd_reserves_attest.c @@ -23,9 +23,10 @@  #include "platform.h"  #include <gnunet/gnunet_util_lib.h>  #include <jansson.h> -#include "taler_mhd_lib.h" -#include "taler_json_lib.h"  #include "taler_dbevents.h" +#include "taler_kyclogic_lib.h" +#include "taler_json_lib.h" +#include "taler_mhd_lib.h"  #include "taler-exchange-httpd_keys.h"  #include "taler-exchange-httpd_reserves_attest.h"  #include "taler-exchange-httpd_responses.h" @@ -50,6 +51,11 @@ struct ReserveAttestContext    const struct TALER_ReservePublicKeyP *reserve_pub;    /** +   * Hash of the payto URI of this reserve. +   */ +  struct TALER_PaytoHashP h_payto; + +  /**     * Timestamp of the request.     */    struct GNUNET_TIME_Timestamp timestamp; @@ -74,6 +80,16 @@ struct ReserveAttestContext     */    json_t *json_attest; +  /** +   * Error code encountered in interaction with KYC provider. +   */ +  enum TALER_ErrorCode ec; + +  /** +   * Set to true if we did not find the reserve. +   */ +  bool not_found; +  }; @@ -130,6 +146,79 @@ reply_reserve_attest_success (struct MHD_Connection *connection,  /** + * Function called with information about all applicable + * legitimization processes for the given user.  Finds the + * available attributes and merges them into our result + * set based on the details requested by the client. + * + * @param cls our `struct ReserveAttestContext *` + * @param provider_section KYC provider configuration section + * @param provider_user_id UID at a provider (can be NULL) + * @param legi_id legitimization process ID (can be NULL) + */ +static void +kyc_process_cb (void *cls, +                const char *provider_section, +                const char *provider_user_id, +                const char *legi_id) +{ +  struct ReserveAttestContext *rsc = cls; +  struct GNUNET_TIME_Timestamp etime; +  json_t *attrs; +  bool match = false; + +  rsc->ec = TALER_KYCLOGIC_user_to_attributes (provider_section, +                                               provider_user_id, +                                               legi_id, +                                               &etime, +                                               &attrs); +  if (TALER_EC_NONE != rsc->ec) +    return; +  if (GNUNET_TIME_absolute_is_past (etime.abs_time)) +  { +    json_decref (attrs); +    return; +  } +  { +    json_t *val; +    const char *name; + +    json_object_foreach (attrs, name, val) +    { +      bool requested = false; +      size_t idx; +      json_t *str; + +      if (NULL != json_object_get (rsc->json_attest, +                                   name)) +        continue; /* duplicate */ +      json_array_foreach (rsc->details, idx, str) +      { +        if (0 == strcmp (json_string_value (str), +                         name)) +        { +          requested = true; +          break; +        } +      } +      if (! requested) +        continue; +      match = true; +      GNUNET_assert (0 == +                     json_object_set (rsc->json_attest, /* NOT set_new! */ +                                      name, +                                      val)); +    } +  } +  json_decref (attrs); +  if (! match) +    return; +  rsc->etime = GNUNET_TIME_timestamp_min (etime, +                                          rsc->etime); +} + + +/**   * Function implementing /reserves/$RID/attest transaction.  Given the public   * key of a reserve, return the associated transaction attest.  Runs the   * transaction logic; IF it returns a non-error code, the transaction logic @@ -152,25 +241,32 @@ reserve_attest_transaction (void *cls,    struct ReserveAttestContext *rsc = cls;    enum GNUNET_DB_QueryStatus qs; -#if FIXME -  qs = TEH_plugin->get_reserve_attest (TEH_plugin->cls, -                                       rsc->reserve_pub, -                                       &rsc->json_attest, -                                       &etime); -#else -  qs = GNUNET_DB_STATUS_HARD_ERROR; -  (void) rsc; -#endif -  if (GNUNET_DB_STATUS_HARD_ERROR == qs) +  rsc->json_attest = json_array (); +  GNUNET_assert (NULL != rsc->json_attest); +  qs = TEH_plugin->iterate_kyc_reference (TEH_plugin->cls, +                                          &rsc->h_payto, +                                          &kyc_process_cb, +                                          rsc); +  switch (qs)    { +  case GNUNET_DB_STATUS_HARD_ERROR:      GNUNET_break (0);      *mhd_ret        = TALER_MHD_reply_with_error (connection,                                      MHD_HTTP_INTERNAL_SERVER_ERROR,                                      TALER_EC_GENERIC_DB_FETCH_FAILED, -                                    "get_reserve_attest"); +                                    "iterate_kyc_reference"); +    return qs; +  case GNUNET_DB_STATUS_SOFT_ERROR: +    GNUNET_break (0); +    return qs; +  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: +    rsc->not_found = true; +    return qs; +  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: +    rsc->not_found = false; +    break;    } -  // FIXME: filter json_attest by requested attributes!    return qs;  } @@ -180,7 +276,9 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,                               const struct TALER_ReservePublicKeyP *reserve_pub,                               const json_t *root)  { -  struct ReserveAttestContext rsc; +  struct ReserveAttestContext rsc = { +    .etime = GNUNET_TIME_UNIT_FOREVER_TS +  };    MHD_RESULT mhd_ret;    struct GNUNET_JSON_Specification spec[] = {      GNUNET_JSON_spec_timestamp ("request_timestamp", @@ -235,6 +333,17 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,                                         TALER_EC_EXCHANGE_RESERVES_ATTEST_BAD_SIGNATURE,                                         NULL);    } + +  { +    char *payto_uri; + +    payto_uri = TALER_reserve_make_payto (TEH_base_url, +                                          rsc.reserve_pub); +    TALER_payto_hash (payto_uri, +                      &rsc.h_payto); +    GNUNET_free (payto_uri); +  } +    if (GNUNET_OK !=        TEH_DB_run_transaction (rc->connection,                                "post reserve attest", @@ -245,6 +354,21 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,    {      return mhd_ret;    } +  if (rsc.not_found) +  { +    json_decref (rsc.json_attest); +    return TALER_MHD_reply_with_error (rc->connection, +                                       MHD_HTTP_NOT_FOUND, +                                       TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN, +                                       NULL); +  } +  if (TALER_EC_NONE != rsc.ec) +  { +    json_decref (rsc.json_attest); +    return TALER_MHD_reply_with_ec (rc->connection, +                                    rsc.ec, +                                    NULL); +  }    mhd_ret = reply_reserve_attest_success (rc->connection,                                            &rsc);    return mhd_ret; diff --git a/src/exchange/taler-exchange-httpd_reserves_get_attest.c b/src/exchange/taler-exchange-httpd_reserves_get_attest.c index bd574acd..aa0f26a4 100644 --- a/src/exchange/taler-exchange-httpd_reserves_get_attest.c +++ b/src/exchange/taler-exchange-httpd_reserves_get_attest.c @@ -156,7 +156,7 @@ reserve_attest_transaction (void *cls,        = TALER_MHD_reply_with_error (connection,                                      MHD_HTTP_INTERNAL_SERVER_ERROR,                                      TALER_EC_GENERIC_DB_FETCH_FAILED, -                                    "get_reserve_attributes"); +                                    "iterate_kyc_reference");      return qs;    case GNUNET_DB_STATUS_SOFT_ERROR:      GNUNET_break (0); | 
