From 4724867794c30ab2d61a2f78ad3f8ad919664519 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 5 Aug 2022 13:32:27 +0200 Subject: -first pass at new KYC DB API --- src/exchange/taler-exchange-httpd_kyc-check.c | 3 + src/exchangedb/common-0001.sql | 63 +++- src/exchangedb/exchange-0001-part.sql | 30 ++ src/exchangedb/plugin_exchangedb_postgres.c | 413 +++++++++++++++++++++++++- src/include/taler_exchangedb_plugin.h | 104 +++++++ src/include/taler_kyclogic_plugin.h | 218 +++++++++++++- 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 4a96d4c81..b4ec4197d 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 7ec6ce6a9..ae5d452a2 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 97f5829e6..efff3874c 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 f08c1184a..6ada10ca3 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 */ @@ -16412,6 +16475,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. * @@ -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 26636d441..f085af35e 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -5621,6 +5621,110 @@ struct TALER_EXCHANGEDB_Plugin uint64_t serial); + /** + * 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 403181bf9..bcb132dbc 100644 --- a/src/include/taler_kyclogic_plugin.h +++ b/src/include/taler_kyclogic_plugin.h @@ -23,9 +23,80 @@ #include #include +#include #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 @@ -57,6 +138,72 @@ typedef void const char *error_msg_hint); +/** + * 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 68c0fdb0a..3f590325c 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; }; -- cgit v1.2.3