diff options
| -rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-check.c | 3 | ||||
| -rw-r--r-- | src/exchangedb/common-0001.sql | 63 | ||||
| -rw-r--r-- | src/exchangedb/exchange-0001-part.sql | 30 | ||||
| -rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 413 | ||||
| -rw-r--r-- | src/include/taler_exchangedb_plugin.h | 104 | ||||
| -rw-r--r-- | src/include/taler_kyclogic_plugin.h | 218 | ||||
| -rw-r--r-- | src/util/exchange_signatures.c | 4 | 
7 files changed, 829 insertions, 6 deletions
| diff --git a/src/exchange/taler-exchange-httpd_kyc-check.c b/src/exchange/taler-exchange-httpd_kyc-check.c index 4a96d4c8..b4ec4197 100644 --- a/src/exchange/taler-exchange-httpd_kyc-check.c +++ b/src/exchange/taler-exchange-httpd_kyc-check.c @@ -245,6 +245,7 @@ TEH_handler_kyc_check (      rc->rh_cleaner = &kyp_cleanup;      { +      // FIXME: now 'legitimization_uuid'!        unsigned long long payment_target_uuid;        char dummy; @@ -290,6 +291,8 @@ TEH_handler_kyc_check (                                           tms));        }      } + +    // FIXME: replace with args[1]!      kyp->hps = MHD_lookup_connection_value (rc->connection,                                              MHD_GET_ARGUMENT_KIND,                                              "h_payto"); diff --git a/src/exchangedb/common-0001.sql b/src/exchangedb/common-0001.sql index 7ec6ce6a..ae5d452a 100644 --- a/src/exchangedb/common-0001.sql +++ b/src/exchangedb/common-0001.sql @@ -56,8 +56,8 @@ BEGIN        '(wire_target_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE'        ',wire_target_h_payto BYTEA PRIMARY KEY CHECK (LENGTH(wire_target_h_payto)=32)'        ',payto_uri VARCHAR NOT NULL' -      ',kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE)' -      ',external_id VARCHAR' +      ',kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE)' -- FIXME: REMOVE! +      ',external_id VARCHAR' -- FIXME: REMOVE!      ') %s ;'      ,'wire_targets'      ,'PARTITION BY HASH (wire_target_h_payto)' @@ -85,6 +85,65 @@ BEGIN  END  $$; + +----------------------- legitimizations --------------------------- + +CREATE OR REPLACE FUNCTION create_table_legitimizations( +  IN shard_suffix VARCHAR DEFAULT NULL +) +RETURNS VOID +LANGUAGE plpgsql +AS $$ +BEGIN + +  PERFORM create_partitioned_table( +    'CREATE TABLE IF NOT EXISTS %I' +      '(legitimization_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE' +      ',h_payto BYTEA NOT NULL CHECK (LENGTH(h_payto)=64)' +      ',expiration_time INT8 NOT NULL DEFAULT (0)' +      ',provider_section VARCHAR NOT NULL' +      ',provider_user_id VARCHAR DEFAULT NULL' +      ',provider_legitimization_id VARCHAR DEFAULT NULL' +    ') %s ;' +    ,'legitimizations' +    ,'PARTITION BY HASH (h_payto)' +    ,shard_suffix +  ); + +END +$$; + +-- We need a separate function for this, as we call create_table only once but need to add +-- those constraints to each partition which gets created +CREATE OR REPLACE FUNCTION add_constraints_to_legitimizations_partition( +  IN partition_suffix VARCHAR +) +RETURNS void +LANGUAGE plpgsql +AS $$ +DECLARE +  partition_name VARCHAR; +BEGIN + +  partition_name = concat_ws('_', 'legitimizations', partition_suffix); + +  EXECUTE FORMAT ( +    'ALTER TABLE ' || partition_name +    || ' ' +      'ADD CONSTRAINT ' || partition_name || '_legitimization_serial_id_key ' +        'UNIQUE (legitimization_serial_id)'); +  EXECUTE FORMAT ( +    'CREATE INDEX IF NOT EXISTS ' || partition_name || '_by_provider_and_legi_index ' +        'ON '|| partition_name || ' ' +        '(provider_section,provider_legitimization_id)' +  ); +  EXECUTE FORMAT ( +    'COMMENT ON INDEX ' || partition_name || '_by_provider_and_legi_index ' +    'IS ' || quote_literal('used (rarely) in kyc_provider_account_lookup') || ';' +  ); +END +$$; +  ------------------------ reserves -------------------------------  CREATE OR REPLACE FUNCTION create_table_reserves( diff --git a/src/exchangedb/exchange-0001-part.sql b/src/exchangedb/exchange-0001-part.sql index 97f5829e..efff3874 100644 --- a/src/exchangedb/exchange-0001-part.sql +++ b/src/exchangedb/exchange-0001-part.sql @@ -104,8 +104,10 @@ COMMENT ON COLUMN wire_targets.payto_uri    IS 'Can be a regular bank account, or also be a URI identifying a reserve-account (for P2P payments)';  COMMENT ON COLUMN wire_targets.wire_target_h_payto    IS 'Unsalted hash of payto_uri'; +-- FIXME: remove:  COMMENT ON COLUMN wire_targets.kyc_ok    IS 'true if the KYC check was passed successfully'; +-- FIXME: remove:  COMMENT ON COLUMN wire_targets.external_id    IS 'Name of the user that was used for OAuth 2.0-based legitimization'; @@ -115,6 +117,34 @@ CREATE TABLE IF NOT EXISTS wire_targets_default  SELECT add_constraints_to_wire_targets_partition('default'); + +-- ------------------------------ legitimizations ---------------------------------------- + +SELECT create_table_legitimizations(); + +COMMENT ON TABLE legitimizations +  IS 'List of legitimizations (required and completed) by account and provider'; +COMMENT ON COLUMN legitimizations.legitimization_serial_id +  IS 'unique ID for this legitimization process at the exchange'; +COMMENT ON COLUMN legitimizations.h_payto +  IS 'foreign key linking the entry to the wire_targets table, NOT a primary key (multiple legitimizations are possible per wire target)'; +COMMENT ON COLUMN legitimizations.expiration_time +  IS 'in the future if the respective KYC check was passed successfully'; +COMMENT ON COLUMN legitimizations.provider_section +  IS 'Configuration file section with details about this provider'; +COMMENT ON COLUMN legitimizations.provider_user_id +  IS 'Identifier for the user at the provider that was used for the legitimization. NULL if provider is unaware.'; +COMMENT ON COLUMN legitimizations.provider_legitimization_id +  IS 'Identifier for the specific legitimization process at the provider. NULL if legitimization was not started.'; + +CREATE TABLE IF NOT EXISTS legitimizations_default +  PARTITION OF legitimizations +  FOR VALUES WITH (MODULUS 1, REMAINDER 0); + +SELECT add_constraints_to_legitimizations_partition('default'); + + +  -- ------------------------------ reserves ----------------------------------------  SELECT create_table_reserves(); diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index f08c1184..6ada10ca 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -4515,7 +4515,70 @@ prepare_statements (struct PostgresClosure *pg)        " FROM exchange_do_close_request"        "  ($1, $2, $3)",        3), - +    /* Used in #postgres_insert_kyc_requirement_for_account() */ +    GNUNET_PQ_make_prepare ( +      "insert_legitimization_requirement", +      "INSERT INTO legitimizations" +      "  (h_payto" +      "  ,provider_section" +      "  ) VALUES " +      "  ($1, $2)" +      " RETURNING legitimization_serial_id", +      2), +    /* Used in #postgres_update_kyc_requirement_by_row() */ +    GNUNET_PQ_make_prepare ( +      "update_legitimization_requirement", +      "UPDATE legitimizations" +      " SET provider_user_id=$4" +      "    ,provider_legitimization_id=$5" +      "    ,expiration_time=$6" +      " WHERE" +      "      h_payto=$3" +      "  AND legitimization_serial_id=$1" +      "  AND provider_section=$2;", +      6), +    /* Used in #postgres_lookup_kyc_requirement_by_row() */ +    GNUNET_PQ_make_prepare ( +      "lookup_legitimization_by_row", +      "SELECT " +      " provider_section" +      ",h_payto" +      ",expiration_time" +      ",provider_user_id" +      ",provider_legitimization_id" +      " FROM legitimizations" +      " WHERE legitimization_serial_id=$1;", +      1), +    /* Used in #postgres_lookup_kyc_requirement_by_account() */ +    GNUNET_PQ_make_prepare ( +      "lookup_legitimization_by_account", +      "SELECT " +      " legitimization_serial_id" +      ",expiration_time" +      ",provider_user_id" +      ",provider_legitimization_id" +      " FROM legitimizations" +      " WHERE h_payto=$1" +      "   AND provider_section=$2;", +      2), +    /* Used in #postgres_kyc_provider_account_lookup() */ +    GNUNET_PQ_make_prepare ( +      "get_wire_target_by_legitimization_id", +      "SELECT " +      " h_payto" +      " FROM legitimizations" +      " WHERE provider_legitimization_id=$1" +      "   AND provider_section=$2;", +      2), +    /* Used in #postgres_select_satisfied_kyc_processes() */ +    GNUNET_PQ_make_prepare ( +      "get_satisfied_legitimizations", +      "SELECT " +      " provider_section" +      " FROM legitimizations" +      " WHERE h_payto=$1" +      "   AND expiration_time>=$2;", +      2),      GNUNET_PQ_PREPARED_STATEMENT_END    }; @@ -13511,7 +13574,7 @@ struct GetWireFeesContext  /**   * Invoke the callback for each result.   * - * @param cls a `struct MissingWireContext *` + * @param cls a `struct GetWireFeesContext *`   * @param result SQL result   * @param num_results number of rows in @a result   */ @@ -16413,6 +16476,340 @@ postgres_profit_drains_set_finished (  /** + * Insert KYC requirement for @a h_payto account into table. + * + * @param cls closure + * @param provider_section provider that must be checked + * @param h_payto account that must be KYC'ed + * @param[out] legi_row set to legitimization row for this check + * @return database transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_insert_kyc_requirement_for_account ( +  void *cls, +  const char *provider_section, +  const struct TALER_PaytoHashP *h_payto, +  uint64_t *legi_row) +{ +  struct PostgresClosure *pg = cls; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (h_payto), +    GNUNET_PQ_query_param_string (provider_section), +    GNUNET_PQ_query_param_end +  }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_uint64 ("legitimization_serial_id", +                                  legi_row), +    GNUNET_PQ_result_spec_end +  }; + +  return GNUNET_PQ_eval_prepared_singleton_select ( +    pg->conn, +    "insert_legitimization_requirement", +    params, +    rs); +} + + +/** + * Update KYC requirement check with provider-linkage and/or + * expiration data. + * + * @param cls closure + * @param provider_section provider that must be checked + * @param h_payto account that must be KYC'ed + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param expiration how long is this KYC check set to be valid (in the past if invalid) + * @return database transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_update_kyc_requirement_by_row ( +  void *cls, +  uint64_t legi_row, +  const char *provider_section, +  struct TALER_PaytoHashP *h_payto, +  const char *provider_account_id, +  const char *provider_legitimization_id, +  struct GNUNET_TIME_Absolute expiration) +{ +  struct PostgresClosure *pg = cls; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_uint64 (&legi_row), +    GNUNET_PQ_query_param_string (provider_section), +    GNUNET_PQ_query_param_auto_from_type (h_payto), +    GNUNET_PQ_query_param_string (provider_account_id), +    GNUNET_PQ_query_param_string (provider_legitimization_id), +    GNUNET_PQ_query_param_absolute_time (&expiration), +    GNUNET_PQ_query_param_end +  }; + +  return GNUNET_PQ_eval_prepared_non_select ( +    pg->conn, +    "update_legitimization_requirement", +    params); +} + + +/** + * Lookup KYC provider meta data. + * + * @param cls closure + * @param legi_row legitimization row to lookup + * @param[out] provider_section provider that must be checked + * @param[out] h_payto account that must be KYC'ed + * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid) + * @param[out] provider_account_id provider account ID + * @param[out] provider_legitimization_id provider legitimization ID + * @return database transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_lookup_kyc_requirement_by_row ( +  void *cls, +  uint64_t legi_row, +  char **provider_section, +  struct TALER_PaytoHashP *h_payto, +  struct GNUNET_TIME_Absolute *expiration, +  char **provider_account_id, +  char **provider_legitimization_id) +{ +  struct PostgresClosure *pg = cls; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_uint64 (&legi_row), +    GNUNET_PQ_query_param_end +  }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_string ("provider_section", +                                  provider_section), +    GNUNET_PQ_result_spec_auto_from_type ("h_payto", +                                          h_payto), +    GNUNET_PQ_result_spec_absolute_time ("expiration_time", +                                         expiration), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_string ("provider_user_id", +                                    provider_account_id), +      NULL), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_string ("provider_legitimization_id", +                                    provider_legitimization_id), +      NULL), +    GNUNET_PQ_result_spec_end +  }; + +  *provider_account_id = NULL; +  *provider_legitimization_id = NULL; +  return GNUNET_PQ_eval_prepared_singleton_select ( +    pg->conn, +    "lookup_legitimization_by_row", +    params, +    rs); +} + + +/** + * Lookup KYC provider meta data. + * + * @param cls closure + * @param provider_section provider that must be checked + * @param h_payto account that must be KYC'ed + * @param[out] legi_row row with the legitimization data + * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid) + * @param[out] provider_account_id provider account ID + * @param[out] provider_legitimization_id provider legitimization ID + * @return database transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_lookup_kyc_requirement_by_account ( +  void *cls, +  const char *provider_section, +  const struct TALER_PaytoHashP *h_payto, +  uint64_t *legi_row, +  struct GNUNET_TIME_Absolute *expiration, +  char **provider_account_id, +  char **provider_legitimization_id) +{ +  struct PostgresClosure *pg = cls; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (h_payto), +    GNUNET_PQ_query_param_string (provider_section), +    GNUNET_PQ_query_param_end +  }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_uint64 ("legitimization_serial_id", +                                  legi_row), +    GNUNET_PQ_result_spec_absolute_time ("expiration_time", +                                         expiration), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_string ("provider_user_id", +                                    provider_account_id), +      NULL), +    GNUNET_PQ_result_spec_allow_null ( +      GNUNET_PQ_result_spec_string ("provider_legitimization_id", +                                    provider_legitimization_id), +      NULL), +    GNUNET_PQ_result_spec_end +  }; + +  *provider_account_id = NULL; +  *provider_legitimization_id = NULL; +  return GNUNET_PQ_eval_prepared_singleton_select ( +    pg->conn, +    "lookup_legitimization_by_account", +    params, +    rs); +} + + +/** + * Lookup an + * @a h_payto by @a provider_legitimization_id. + * + * @param cls closure + * @param provider_section + * @param provider_legitimization_id legi to look up + * @param[out] h_payto where to write the result + * @return database transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_kyc_provider_account_lookup ( +  void *cls, +  const char *provider_section, +  const char *provider_legitimization_id, +  struct TALER_PaytoHashP *h_payto) +{ +  struct PostgresClosure *pg = cls; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_string (provider_section), +    GNUNET_PQ_query_param_string (provider_legitimization_id), +    GNUNET_PQ_query_param_end +  }; +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_auto_from_type ("h_payto", +                                          h_payto), +    GNUNET_PQ_result_spec_end +  }; + +  return GNUNET_PQ_eval_prepared_singleton_select ( +    pg->conn, +    "get_wire_target_by_legitimization_id", +    params, +    rs); +} + + +/** + * Closure for #get_wire_fees_cb(). + */ +struct GetLegitimizationsContext +{ +  /** +   * Function to call per result. +   */ +  TALER_EXCHANGEDB_SatisfiedProviderCallback cb; + +  /** +   * Closure for @e cb. +   */ +  void *cb_cls; + +  /** +   * Plugin context. +   */ +  struct PostgresClosure *pg; + +  /** +   * Flag set to #GNUNET_OK as long as everything is fine. +   */ +  enum GNUNET_GenericReturnValue status; + +}; + + +/** + * Invoke the callback for each result. + * + * @param cls a `struct GetLegitimizationsContext *` + * @param result SQL result + * @param num_results number of rows in @a result + */ +static void +get_legitimizations_cb (void *cls, +                        PGresult *result, +                        unsigned int num_results) +{ +  struct GetLegitimizationsContext *ctx = cls; + +  for (unsigned int i = 0; i < num_results; i++) +  { +    char *provider_section; +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_string ("provider_section", +                                    &provider_section), +      GNUNET_PQ_result_spec_end +    }; + +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, +                                  rs, +                                  i)) +    { +      GNUNET_break (0); +      ctx->status = GNUNET_SYSERR; +      return; +    } +    ctx->cb (ctx->cb_cls, +             provider_section); +    GNUNET_PQ_cleanup_result (rs); +  } +} + + +/** + * Call us on KYC processes satisfied for the given + * account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param spc function to call for each satisfied KYC process + * @param spc_cls closure for @a spc + * @return transaction status code + */ +static enum GNUNET_DB_QueryStatus +postgres_select_satisfied_kyc_processes ( +  void *cls, +  const struct TALER_PaytoHashP *h_payto, +  TALER_EXCHANGEDB_SatisfiedProviderCallback spc, +  void *spc_cls) +{ +  struct PostgresClosure *pg = cls; +  struct GNUNET_TIME_Absolute now +    = GNUNET_TIME_absolute_get (); +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (h_payto), +    GNUNET_PQ_query_param_absolute_time (&now), +    GNUNET_PQ_query_param_end +  }; +  struct GetLegitimizationsContext ctx = { +    .cb = spc, +    .cb_cls = spc_cls, +    .pg = pg, +    .status = GNUNET_OK +  }; +  enum GNUNET_DB_QueryStatus qs; + +  qs = GNUNET_PQ_eval_prepared_multi_select ( +    pg->conn, +    "get_satisfied_legitimizations", +    params, +    &get_legitimizations_cb, +    &ctx); +  if (GNUNET_OK != ctx.status) +    return GNUNET_DB_STATUS_HARD_ERROR; +  return qs; +} + + +/**   * Initialize Postgres database subsystem.   *   * @param cls a configuration instance @@ -16736,6 +17133,18 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)      = &postgres_get_drain_profit;    plugin->profit_drains_set_finished      = &postgres_profit_drains_set_finished; +  plugin->insert_kyc_requirement_for_account +    = &postgres_insert_kyc_requirement_for_account; +  plugin->update_kyc_requirement_by_row +    = &postgres_update_kyc_requirement_by_row; +  plugin->lookup_kyc_requirement_by_row +    = &postgres_lookup_kyc_requirement_by_row; +  plugin->lookup_kyc_requirement_by_account +    = &postgres_lookup_kyc_requirement_by_account; +  plugin->kyc_provider_account_lookup +    = &postgres_kyc_provider_account_lookup; +  plugin->select_satisfied_kyc_processes +    = &postgres_select_satisfied_kyc_processes;    return plugin;  } diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 26636d44..f085af35 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -5622,6 +5622,110 @@ struct TALER_EXCHANGEDB_Plugin    /** +   * Insert KYC requirement for @a h_payto account into table. +   * +   * @param cls closure +   * @param provider_section provider that must be checked +   * @param h_payto account that must be KYC'ed +   * @param[out] legi_row set to legitimization row for this check +   * @return database transaction status +   */ +  enum GNUNET_DB_QueryStatus +  (*insert_kyc_requirement_for_account)( +    void *cls, +    const char *provider_section, +    const struct TALER_PaytoHashP *h_payto, +    uint64_t *legi_row); + + +  /** +   * Update KYC requirement check with provider-linkage and/or +   * expiration data. +   * +   * @param cls closure +   * @param provider_section provider that must be checked +   * @param h_payto account that must be KYC'ed +   * @param provider_account_id provider account ID +   * @param provider_legitimization_id provider legitimization ID +   * @param expiration how long is this KYC check set to be valid (in the past if invalid) +   * @return database transaction status +   */ +  enum GNUNET_DB_QueryStatus +  (*update_kyc_requirement_by_row)( +    void *cls, +    uint64_t legi_row, +    const char *provider_section, +    struct TALER_PaytoHashP *h_payto, +    const char *provider_account_id, +    const char *provider_legitimization_id, +    struct GNUNET_TIME_Absolute expiration); + + +  /** +   * Lookup KYC provider meta data. +   * +   * @param cls closure +   * @param legi_row legitimization row to lookup +   * @param[out] provider_section provider that must be checked +   * @param[out] h_payto account that must be KYC'ed +   * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid) +   * @param[out] provider_account_id provider account ID +   * @param[out] provider_legitimization_id provider legitimization ID +   * @return database transaction status +   */ +  enum GNUNET_DB_QueryStatus +  (*lookup_kyc_requirement_by_row)( +    void *cls, +    uint64_t legi_row, +    char **provider_section, +    struct TALER_PaytoHashP *h_payto, +    struct GNUNET_TIME_Absolute *expiration, +    char **provider_account_id, +    char **provider_legitimization_id); + + +  /** +   * Lookup KYC provider meta data. +   * +   * @param cls closure +   * @param provider_section provider that must be checked +   * @param h_payto account that must be KYC'ed +   * @param[out] legi_row row with the legitimization data +   * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid) +   * @param[out] provider_account_id provider account ID +   * @param[out] provider_legitimization_id provider legitimization ID +   * @return database transaction status +   */ +  enum GNUNET_DB_QueryStatus +  (*lookup_kyc_requirement_by_account)( +    void *cls, +    const char *provider_section, +    const struct TALER_PaytoHashP *h_payto, +    uint64_t *legi_row, +    struct GNUNET_TIME_Absolute *expiration, +    char **provider_account_id, +    char **provider_legitimization_id); + + +  /** +   * Lookup an +   * @a h_payto by @a provider_legitimization_id. +   * +   * @param cls closure +   * @param provider_section +   * @param provider_legitimization_id legi to look up +   * @param[out] h_payto where to write the result +   * @return database transaction status +   */ +  enum GNUNET_DB_QueryStatus +  (*kyc_provider_account_lookup)( +    void *cls, +    const char *provider_section, +    const char *provider_legitimization_id, +    struct TALER_PaytoHashP *h_payto); + + +  /**     * Call us on KYC processes satisfied for the given     * account.     * diff --git a/src/include/taler_kyclogic_plugin.h b/src/include/taler_kyclogic_plugin.h index 403181bf..bcb132db 100644 --- a/src/include/taler_kyclogic_plugin.h +++ b/src/include/taler_kyclogic_plugin.h @@ -23,10 +23,81 @@  #include <jansson.h>  #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_db_lib.h>  #include "taler_util.h"  /** + * Possible states of a KYC check. + */ +enum TALER_KYCLOGIC_KycStatus +{ + +  /** +   * The provider has passed the customer. +   */ +  TALER_KYCLOGIC_STATUS_SUCCESS = 0, + +  /** +   * Something to do with the user (bit!). +   */ +  TALER_KYCLOGIC_STATUS_USER = 1, + +  /** +   * Something to do with the provider (bit!). +   */ +  TALER_KYCLOGIC_STATUS_PROVIDER = 2, + +  /** +   * The interaction ended in definitive failure. +   * (kind of with both parties). +   */ +  TALER_KYCLOGIC_STATUS_FAILED +    = TALER_KYCLOGIC_STATUS_USER +      | TALER_KYCLOGIC_STATUS_PROVIDER, + +  /** +   * The interaction is still ongoing. +   */ +  TALER_KYCLOGIC_STATUS_PENDING = 4, + +  /** +   * One of the parties hat a temporary failure. +   */ +  TALER_KYCLOGIC_STATUS_ABORTED = 8, + +  /** +   * The interaction with the user is ongoing. +   */ +  TALER_KYCLOGIC_STATUS_USER_PENDING +    = TALER_KYCLOGIC_STATUS_USER +      | TALER_KYCLOGIC_STATUS_PENDING, + +  /** +   * The provider is still checking. +   */ +  TALER_KYCLOGIC_STATUS_PROVIDER_PENDING +    = TALER_KYCLOGIC_STATUS_PROVIDER +      | TALER_KYCLOGIC_STATUS_PENDING, + +  /** +   * The user aborted the check (possibly recoverable). +   */ +  TALER_KYCLOGIC_STATUS_USER_ABORTED +    = TALER_KYCLOGIC_STATUS_USER +      | TALER_KYCLOGIC_STATUS_ABORTED, + +  /** +   * The provider had an (internal) failure. +   */ +  TALER_KYCLOGIC_STATUS_PROVIDER_FAILED +    = TALER_KYCLOGIC_STATUS_PROVIDER +      | TALER_KYCLOGIC_STATUS_ABORTED, + +}; + + +/**   * Plugin-internal specification of the configuration   * of the plugin for a given KYC provider.   */ @@ -37,6 +108,16 @@ struct TALER_KYCLOGIC_ProviderDetails;   */  struct TALER_KYCLOGIC_InitiateHandle; +/** + * Handle for an KYC proof operation. + */ +struct TALER_KYCLOGIC_ProofHandle; + +/** + * Handle for an KYC Web hook operation. + */ +struct TALER_KYCLOGIC_WebhookHandle; +  /**   * Function called with the result of a KYC initiation @@ -58,6 +139,72 @@ typedef void  /** + * Function called with the result of a proof check + * operation. + * + * Note that the "decref" for the @a response + * will be done by the plugin. + * + * @param cls closure + * @param status KYC status + * @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 + */ +typedef void +(*TALER_KYCLOGIC_ProofCallback)( +  void *cls, +  enum TALER_KYCLOGIC_KycStatus status, +  struct GNUNET_TIME_Absolute expiration, +  unsigned int http_status, +  struct MHD_Response *response); + + +/** + * Function called with the result of a webhook + * operation. + * + * Note that the "decref" for the @a response + * will be done by the plugin. + * + * @param cls closure + * @param account_id account the webhook was about + * @param status KYC status + * @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 + */ +typedef void +(*TALER_KYCLOGIC_WebhookCallback)( +  void *cls, +  const struct TALER_PaytoHashP *account_id, +  enum TALER_KYCLOGIC_KycStatus status, +  struct GNUNET_TIME_Absolute expiration, +  unsigned int http_status, +  struct MHD_Response *response); + + +/** + * Function the plugin can use to lookup an + * @a h_payto by @a provider_legitimization_id. + * Must match the `kyc_provider_account_lookup` + * of the exchange's database plugin. + * + * @param cls closure + * @param provider_section + * @param provider_legitimization_id legi to look up + * @param[out] h_payto where to write the result + * @return database transaction status + */ +typedef enum GNUNET_DB_QueryStatus +(*TALER_KYCLOGIC_ProviderLookupCallback)( +  void *cls, +  const char *provider_section, +  const char *provider_legitimization_id, +  struct TALER_PaytoHashP *h_payto); + + +/**   * @brief The plugin API, returned from the plugin's "init" function.   * The argument given to "init" is simply a configuration handle.   */ @@ -101,6 +248,8 @@ struct TALER_KYCLOGIC_Plugin     * @param cls the @e cls of this struct with the plugin-specific state     * @param pd provider configuration details     * @param account_id which account to trigger process for +   * @param cb function to call with the result +   * @param cb_cls closure for @a cb     * @return handle to cancel operation early     */    struct TALER_KYCLOGIC_InitiateHandle * @@ -110,6 +259,7 @@ struct TALER_KYCLOGIC_Plugin                TALER_KYCLOGIC_InitiateCallback cb,                void *cb_cls); +    /**     * Cancel KYC check initiation.     * @@ -118,9 +268,73 @@ struct TALER_KYCLOGIC_Plugin    void    (*initiate_cancel) (struct TALER_KYCLOGIC_InitiateHandle *ih); -  // FIXME: add callback pair for kyc_proof -  // FIXME: add callback pair for kyc_webhook +  /** +   * Check KYC status and return status to human. +   * +   * @param cls the @e cls of this struct with the plugin-specific state +   * @param pd provider configuration details +   * @param account_id which account to trigger process for +   * @param cb function to call with the result +   * @param cb_cls closure for @a cb +   * @return handle to cancel operation early +   */ +  struct TALER_KYCLOGIC_ProofHandle * +  (*proof)(void *cls, +           const struct TALER_KYCLOGIC_ProviderDetails *pd, +           const struct TALER_PaytoHashP *account_id, +           const char *provider_user_id, +           const char *provider_legitimization_id, +           TALER_KYCLOGIC_ProofCallback cb, +           void *cb_cls); + + +  /** +   * Cancel KYC proof. +   * +   * @param[in] ph handle of operation to cancel +   */ +  void +  (*proof_cancel) (struct TALER_KYCLOGIC_ProofHandle *ph); + + +  /** +   * Check KYC status and return result for Webhook. +   * +   * @param cls the @e cls of this struct with the plugin-specific state +   * @param pd provider configuration details +   * @param plc callback to lookup accounts with +   * @param plc_cls closure for @a plc +   * @param http_method HTTP method used for the webhook +   * @param url_path rest of the URL after `/kyc-webhook/` +   * @param connection MHD connection object (for HTTP headers) +   * @param body_size number of bytes in @a body +   * @param body HTTP request body +   * @param cb function to call with the result +   * @param cb_cls closure for @a cb +   * @return handle to cancel operation early +   */ +  struct TALER_KYCLOGIC_InitiateHandle * +  (*webhook)(void *cls, +             const struct TALER_KYCLOGIC_ProviderDetails *pd, +             TALER_KYCLOGIC_ProviderLookupCallback plc, +             void *plc_cls, +             const char *http_method, +             const char *url_path, +             struct MHD_Connection *connection, +             size_t body_size, +             const void *body, +             TALER_KYCLOGIC_WebhookCallback cb, +             void *cb_cls); + + +  /** +   * Cancel KYC webhook execution. +   * +   * @param[in] wh handle of operation to cancel +   */ +  void +  (*webhook_cancel) (struct TALER_KYCLOGIC_WebhookHandle *wh);  }; diff --git a/src/util/exchange_signatures.c b/src/util/exchange_signatures.c index 68c0fdb0..3f590325 100644 --- a/src/util/exchange_signatures.c +++ b/src/util/exchange_signatures.c @@ -454,8 +454,12 @@ struct TALER_ExchangeAccountSetupSuccessPS     */    struct TALER_PaytoHashP h_payto; +  // FIXME: include details on *which* KYC process +  // was satisfied! +    /**     * When was the signature made. +   * FIXME: replace by *expiration* time!     */    struct GNUNET_TIME_TimestampNBO timestamp;  }; | 
