gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant] branch master updated: -starting work on /kyc handler


From: gnunet
Subject: [taler-merchant] branch master updated: -starting work on /kyc handler
Date: Sat, 09 Oct 2021 16:18:46 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new 91d76e78 -starting work on /kyc handler
91d76e78 is described below

commit 91d76e7861149af36a8875bbb0811dda4e0485c4
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat Oct 9 16:18:44 2021 +0200

    -starting work on /kyc handler
---
 contrib/merchant-backoffice                        |   2 +-
 src/backend/Makefile.am                            |   2 +
 src/backend/taler-merchant-httpd.c                 |  19 +-
 src/backend/taler-merchant-httpd_get-orders-ID.c   |   4 +-
 src/backend/taler-merchant-httpd_helper.c          |   4 +-
 ...r-merchant-httpd_private-get-instances-ID-kyc.c |  84 +++++++
 ...r-merchant-httpd_private-get-instances-ID-kyc.h |  59 +++++
 src/backenddb/Makefile.am                          |   4 +-
 src/backenddb/drop0001.sql                         |  12 +-
 src/backenddb/drop0002.sql                         |  32 ---
 src/backenddb/merchant-0001.sql                    |   2 +-
 src/backenddb/merchant-0003.sql                    |  52 +++++
 src/backenddb/plugin_merchantdb_postgres.c         | 250 ++++++++++++++++++++-
 src/backenddb/test_merchantdb.c                    | 152 +++++++++++--
 src/include/taler_merchantdb_plugin.h              |  99 ++++++--
 15 files changed, 698 insertions(+), 79 deletions(-)

diff --git a/contrib/merchant-backoffice b/contrib/merchant-backoffice
index 182cdfff..824aa7a8 160000
--- a/contrib/merchant-backoffice
+++ b/contrib/merchant-backoffice
@@ -1 +1 @@
-Subproject commit 182cdfffa1d4b6f2bb3543d30cfa7509e73bda03
+Subproject commit 824aa7a80b4c2e63d23985751f34c9492d396a36
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index da825d3b..073fff5e 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -48,6 +48,8 @@ taler_merchant_httpd_SOURCES = \
     taler-merchant-httpd_private-get-instances.h \
   taler-merchant-httpd_private-get-instances-ID.c \
     taler-merchant-httpd_private-get-instances-ID.h \
+  taler-merchant-httpd_private-get-instances-ID-kyc.c \
+    taler-merchant-httpd_private-get-instances-ID-kyc.h \
   taler-merchant-httpd_private-get-products.c \
     taler-merchant-httpd_private-get-products.h \
   taler-merchant-httpd_private-get-products-ID.c \
diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index e031c2ba..feb90b28 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -39,6 +39,7 @@
 #include "taler-merchant-httpd_private-delete-transfers-ID.h"
 #include "taler-merchant-httpd_private-get-instances.h"
 #include "taler-merchant-httpd_private-get-instances-ID.h"
+#include "taler-merchant-httpd_private-get-instances-ID-kyc.h"
 #include "taler-merchant-httpd_private-get-products.h"
 #include "taler-merchant-httpd_private-get-products-ID.h"
 #include "taler-merchant-httpd_private-get-orders.h"
@@ -147,7 +148,7 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
 char *TMH_default_auth;
 
 
-int
+enum GNUNET_GenericReturnValue
 TMH_check_auth (const char *token,
                 const struct GNUNET_ShortHashCode *salt,
                 const struct GNUNET_HashCode *hash)
@@ -646,6 +647,16 @@ url_handler (void *cls,
       /* Body should be pretty small. */
       .max_upload = 1024 * 1024
     },
+    /* POST /kyc: */
+    {
+      .url_prefix = "/instances/",
+      .url_suffix = "kyc",
+      .method = MHD_HTTP_METHOD_GET,
+      .skip_instance = true,
+      .default_only = true,
+      .have_id_segment = true,
+      .handler = &TMH_private_get_instances_default_ID_kyc,
+    },
     {
       NULL
     }
@@ -685,6 +696,12 @@ url_handler (void *cls,
       /* Body should be pretty small. */
       .max_upload = 1024 * 1024,
     },
+    /* GET /kyc: */
+    {
+      .url_prefix = "/kyc",
+      .method = MHD_HTTP_METHOD_GET,
+      .handler = &TMH_private_get_instances_ID_kyc,
+    },
     /* GET /products: */
     {
       .url_prefix = "/products",
diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c 
b/src/backend/taler-merchant-httpd_get-orders-ID.c
index 0025a6ce..dbb5ef10 100644
--- a/src/backend/taler-merchant-httpd_get-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_get-orders-ID.c
@@ -427,7 +427,7 @@ TMH_make_order_status_url (struct MHD_Connection *con,
                              "?token=");
     GNUNET_buffer_write_data_encoded (&buf,
                                       (char *) claim_token,
-                                      sizeof (struct TALER_ClaimTokenP));
+                                      sizeof (*claim_token));
     num_qp++;
   }
 
@@ -454,7 +454,7 @@ TMH_make_order_status_url (struct MHD_Connection *con,
                                "?h_contract=");
     GNUNET_buffer_write_data_encoded (&buf,
                                       (char *) h_contract,
-                                      sizeof (struct GNUNET_HashCode));
+                                      sizeof (*h_contract));
   }
 
   return GNUNET_buffer_reap_str (&buf);
diff --git a/src/backend/taler-merchant-httpd_helper.c 
b/src/backend/taler-merchant-httpd_helper.c
index 2427b1e0..f4129e0e 100644
--- a/src/backend/taler-merchant-httpd_helper.c
+++ b/src/backend/taler-merchant-httpd_helper.c
@@ -315,9 +315,7 @@ TMH_taxes_array_valid (const json_t *taxes)
 struct TMH_WireMethod *
 TMH_setup_wire_account (const char *payto_uri)
 {
-  // FIXME: avoid use of huge 512-bit salt!?
-  // Seems 128-bit should suffice, right?
-  struct GNUNET_HashCode salt;
+  struct TALER_WireSalt salt;
   struct TMH_WireMethod *wm;
 
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c 
b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c
new file mode 100644
index 00000000..a87b4162
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c
@@ -0,0 +1,84 @@
+/*
+  This file is part of GNU Taler
+  (C) 2021 Taler Systems SA
+
+  GNU 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 Foundation; either version 3,
+  or (at your option) any later version.
+
+  GNU Taler is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not,
+  see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_private-get-instances-ID-kyc.c
+ * @brief implementing GET /instances/$ID/kyc request handling
+ * @kycor Christian Grothoff
+ * @kycor Florian Dold
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-get-instances-ID-kyc.h"
+#include "taler-merchant-httpd_helper.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * Check the KYC status of an instance.
+ *
+ * @param mi instance to check KYC status of
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+static MHD_RESULT
+get_instances_ID_kyc (struct TMH_MerchantInstance *mi,
+                      struct MHD_Connection *connection,
+                      struct TMH_HandlerContext *hc)
+{
+  GNUNET_break (0);
+  return MHD_NO;
+}
+
+
+MHD_RESULT
+TMH_private_get_instances_ID_kyc (const struct TMH_RequestHandler *rh,
+                                    struct MHD_Connection *connection,
+                                    struct TMH_HandlerContext *hc)
+{
+  struct TMH_MerchantInstance *mi = hc->instance;
+
+  return get_instances_ID_kyc (mi,
+                               connection,
+                               hc);
+}
+
+
+MHD_RESULT
+TMH_private_get_instances_default_ID_kyc (const struct TMH_RequestHandler *rh,
+                                            struct MHD_Connection *connection,
+                                            struct TMH_HandlerContext *hc)
+{
+  struct TMH_MerchantInstance *mi;
+
+  mi = TMH_lookup_instance (hc->infix);
+  if (NULL == mi)
+  {
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_NOT_FOUND,
+                                       
TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
+                                       hc->infix);
+  }
+  return get_instances_ID_kyc (mi,
+                               connection,
+                               hc);
+}
+
+
+/* end of taler-merchant-httpd_private-get-instances-ID-kyc.c */
diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.h 
b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.h
new file mode 100644
index 00000000..58762c86
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.h
@@ -0,0 +1,59 @@
+/*
+  This file is part of GNU Taler
+  (C) 2021 Taler Systems SA
+
+  GNU 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 Foundation; either version 3,
+  or (at your option) any later version.
+
+  GNU Taler is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not,
+  see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_private-get-instances-ID-kyc.h
+ * @brief implements GET /instances/$ID/kyc request handling
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_INSTANCES_ID_KYC_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_GET_INSTANCES_ID_KYC_H
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Change the instance's kyc settings.
+ * This is the handler called using the instance's own kycentication.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_get_instances_ID_kyc (const struct TMH_RequestHandler *rh,
+                                  struct MHD_Connection *connection,
+                                  struct TMH_HandlerContext *hc);
+
+
+/**
+ * Change the instance's kyc settings.
+ * This is the handler called using the default instance's kycentication.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_get_instances_default_ID_kyc (const struct TMH_RequestHandler *rh,
+                                          struct MHD_Connection *connection,
+                                          struct TMH_HandlerContext *hc);
+
+#endif
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
index 300af69f..8adc1d76 100644
--- a/src/backenddb/Makefile.am
+++ b/src/backenddb/Makefile.am
@@ -14,8 +14,8 @@ sql_DATA = \
   merchant-0000.sql \
   merchant-0001.sql \
   merchant-0002.sql \
-  drop0001.sql \
-  drop0002.sql
+  merchant-0003.sql \
+  drop0001.sql
 
 if HAVE_POSTGRESQL
 if HAVE_GNUNETPQ
diff --git a/src/backenddb/drop0001.sql b/src/backenddb/drop0001.sql
index aec588da..4a028bab 100644
--- a/src/backenddb/drop0001.sql
+++ b/src/backenddb/drop0001.sql
@@ -1,6 +1,6 @@
 --
 -- This file is part of TALER
--- Copyright (C) 2014--2020 Taler Systems SA
+-- Copyright (C) 2014--2021 Taler Systems SA
 --
 -- TALER is free software; you can redistribute it and/or modify it under the
 -- terms of the GNU General Public License as published by the Free Software
@@ -54,5 +54,15 @@ DROP TABLE IF EXISTS merchant_tip_pickup_signatures CASCADE;
 -- Unregister patch (0001.sql)
 SELECT _v.unregister_patch('merchant-0001');
 
+-- Unregister patch (0002.sql)
+SELECT _v.unregister_patch('merchant-0002');
+
+DROP TABLE IF EXISTS merchant_kyc CASCADE;
+
+-- Unregister patch (0003.sql)
+SELECT _v.unregister_patch('merchant-0003');
+
+
+
 -- And we're out of here...
 COMMIT;
diff --git a/src/backenddb/drop0002.sql b/src/backenddb/drop0002.sql
deleted file mode 100644
index a90a4304..00000000
--- a/src/backenddb/drop0002.sql
+++ /dev/null
@@ -1,32 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2021 Taler Systems SA
---
--- TALER is free software; you can redistribute it and/or modify it under the
--- terms of the GNU General Public License as published by the Free Software
--- Foundation; either version 3, or (at your option) any later version.
---
--- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
--- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
--- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License along with
--- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
---
-
--- Everything in one big transaction
-BEGIN;
-
--- This script DROPs all of the tables we create, including the
--- versioning schema!
---
--- Unlike the other SQL files, it SHOULD be updated to reflect the
--- latest requirements for dropping tables.
-
--- Drops for 0002.sql
-
--- Unregister patch (0002.sql)
-SELECT _v.unregister_patch('merchant-0002');
-
--- And we're out of here...
-COMMIT;
diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql
index ed728ab6..9e769067 100644
--- a/src/backenddb/merchant-0001.sql
+++ b/src/backenddb/merchant-0001.sql
@@ -97,7 +97,7 @@ CREATE TABLE IF NOT EXISTS merchant_accounts
   ,merchant_serial BIGINT NOT NULL
      REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
   ,h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)
-  ,salt BYTEA NOT NULL CHECK (LENGTH(salt)=64)
+  ,salt BYTEA NOT NULL CHECK (LENGTH(salt)=64) -- FIXME: eventually migrate to 
16-bit salt value here! #7032
   ,payto_uri VARCHAR NOT NULL
   ,active BOOLEAN NOT NULL
   ,UNIQUE (merchant_serial,payto_uri)
diff --git a/src/backenddb/merchant-0003.sql b/src/backenddb/merchant-0003.sql
new file mode 100644
index 00000000..00c77656
--- /dev/null
+++ b/src/backenddb/merchant-0003.sql
@@ -0,0 +1,52 @@
+--
+-- This file is part of TALER
+-- Copyright (C) 2021 Taler Systems SA
+--
+-- TALER is free software; you can redistribute it and/or modify it under the
+-- terms of the GNU General Public License as published by the Free Software
+-- Foundation; either version 3, or (at your option) any later version.
+--
+-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License along with
+-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+--
+
+-- This file includes migrations up to 0.8.5.
+-- All migrations after that release should
+-- to into a different file.
+
+-- Everything in one big transaction
+BEGIN;
+
+-- Check patch versioning is in place.
+SELECT _v.register_patch('merchant-0003', NULL, NULL);
+
+CREATE TABLE IF NOT EXISTS merchant_kyc
+(kyc_serial_id BIGSERIAL UNIQUE
+,kyc_timestamp INT8 NOT NULL
+,kyc_ok BOOLEAN NOT NULL DEFAULT (false)
+,exchange_kyc_serial INT8 NOT NULL DEFAULT(0)
+,account_serial INT8 NOT NULL
+  REFERENCES merchant_accounts (account_serial) ON DELETE CASCADE
+,exchange_url VARCHAR NOT NULL
+,PRIMARY KEY (account_serial,exchange_url)
+);
+COMMENT ON TABLE merchant_kyc
+  IS 'Status of the KYC process of a merchant account at an exchange';
+COMMENT ON COLUMN merchant_kyc.kyc_timestamp
+  IS 'Last time we checked our KYC status at the exchange. Useful to re-check 
if the status is very stale.';
+COMMENT ON COLUMN merchant_kyc.exchange_kyc_serial
+  IS 'Number to use in the KYC-endpoints of the exchange to check the KYC 
status or begin the KYC process. 0 if we do not know it yet.';
+COMMENT ON COLUMN merchant_kyc.kyc_ok
+  IS 'true if the KYC check was passed successfully';
+COMMENT ON COLUMN merchant_kyc.account_serial
+  IS 'Which bank account of the merchant is the KYC status for';
+COMMENT ON COLUMN merchant_kyc.exchange_url
+  IS 'Which exchange base URL is this KYC status valid for';
+
+
+-- Complete transaction
+COMMIT;
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 45f02757..838a6897 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -111,7 +111,7 @@ struct PostgresClosure
  * @param cls the `struct PostgresClosure` with the plugin-specific state
  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
  */
-static int
+static enum GNUNET_GenericReturnValue
 postgres_drop_tables (void *cls)
 {
   struct PostgresClosure *pc = cls;
@@ -135,7 +135,7 @@ postgres_drop_tables (void *cls)
  * @param cls the `struct PostgresClosure` with the plugin-specific state
  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
  */
-static int
+static enum GNUNET_GenericReturnValue
 postgres_create_tables (void *cls)
 {
   struct PostgresClosure *pc = cls;
@@ -261,7 +261,7 @@ check_connection (struct PostgresClosure *pg)
  *             must point to a constant
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 postgres_start (void *cls,
                 const char *name)
 {
@@ -297,7 +297,7 @@ postgres_start (void *cls,
  *             must point to a constant
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 postgres_start_read_committed (void *cls,
                                const char *name)
 {
@@ -820,6 +820,210 @@ postgres_insert_account (
 }
 
 
+/**
+ * Closure for kyc_status_cb().
+ */
+struct KycStatusContext
+{
+  /**
+   * Function to call with results.
+   */
+  TALER_MERCHANTDB_KycCallback kyc_cb;
+
+  /**
+   * Closure for @e kyc_cb.
+   */
+  void *kyc_cb_cls;
+
+  /**
+   * Filter, NULL to not filter.
+   */
+  const struct GNUNET_HashCode *h_wire;
+
+  /**
+   * Filter, NULL to not filter.
+   */
+  const char *exchange_url;
+
+  /**
+   * Number of results found.
+   */
+  unsigned int count;
+
+  /**
+   * Set to true on failure(s).
+   */
+  bool failure;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about accounts.
+ *
+ * @param[in,out] cls of type `struct KycStatusContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+kyc_status_cb (void *cls,
+               PGresult *result,
+               unsigned int num_results)
+{
+  struct KycStatusContext *ksc = cls;
+
+  for (unsigned int i = 0; i < num_results; i++)
+  {
+    struct GNUNET_HashCode h_wire;
+    uint64_t kyc_serial;
+    char *exchange_url;
+    char *payto_uri;
+    struct GNUNET_TIME_Absolute last_check;
+    uint8_t kyc_ok;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("h_wire",
+                                            &h_wire),
+      GNUNET_PQ_result_spec_uint64 ("exchange_kyc_serial",
+                                    &kyc_serial),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      GNUNET_PQ_result_spec_string ("exchange_url",
+                                    &exchange_url),
+      GNUNET_PQ_result_spec_absolute_time ("kyc_timestamp",
+                                           &last_check),
+      GNUNET_PQ_result_spec_auto_from_type ("kyc_ok",
+                                            &kyc_ok),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ksc->failure = true;
+      return;
+    }
+    if ( (NULL != ksc->exchange_url) &&
+         (0 != strcmp (ksc->exchange_url,
+                       exchange_url)) )
+    {
+      GNUNET_PQ_cleanup_result (rs);
+      continue;
+    }
+    if ( (NULL != ksc->h_wire) &&
+         (0 != GNUNET_memcmp (ksc->h_wire,
+                              &h_wire)) )
+    {
+      GNUNET_PQ_cleanup_result (rs);
+      continue;
+    }
+    ksc->count++;
+    ksc->kyc_cb (ksc->kyc_cb_cls,
+                 &h_wire,
+                 kyc_serial,
+                 payto_uri,
+                 exchange_url,
+                 last_check,
+                 0 != kyc_ok);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
+/**
+ * Check an instance's account's KYC status.
+ *
+ * @param cls closure
+ * @param merchant_id merchant backend instance ID
+ * @param h_wire hash of the wire account to check,
+ *        NULL to check all accounts of the merchant
+ * @param exchange_url base URL of the exchange to check,
+ *        NULL to check all exchanges
+ * @param kyc_cb KYC status callback to invoke
+ * @param kyc_cb_cls closure for @a kyc_cb
+ * @return database result code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_account_kyc_get_status (void *cls,
+                                 const char *merchant_id,
+                                 const struct GNUNET_HashCode *h_wire,
+                                 const char *exchange_url,
+                                 TALER_MERCHANTDB_KycCallback kyc_cb,
+                                 void *kyc_cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct KycStatusContext ksc = {
+    .kyc_cb = kyc_cb,
+    .kyc_cb_cls = kyc_cb_cls,
+    .exchange_url = exchange_url,
+    .h_wire = h_wire
+  };
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (merchant_id),
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  check_connection (pg);
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "lookup_kyc_status",
+                                             params,
+                                             &kyc_status_cb,
+                                             &ksc);
+  if (ksc.failure)
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  if (0 > qs)
+    return qs;
+  return ksc.count;
+}
+
+
+/**
+ * Update an instance's account's KYC status.
+ *
+ * @param cls closure
+ * @param merchant_id merchant backend instance ID
+ * @param h_wire hash of the wire account to check
+ * @param exchange_url base URL of the exchange to check
+ * @param exchange_kyc_serial serial number for our account at the exchange (0 
if unknown)
+ * @param kyc_ok current KYC status (true for satisfied)
+ * @return database result code
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_account_kyc_set_status (
+  void *cls,
+  const char *merchant_id,
+  const struct GNUNET_HashCode *h_wire,
+  const char *exchange_url,
+  uint64_t exchange_kyc_serial,
+  bool kyc_ok)
+{
+  struct PostgresClosure *pg = cls;
+  uint8_t ok = kyc_ok;
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (merchant_id),
+    GNUNET_PQ_query_param_auto_from_type (h_wire),
+    GNUNET_PQ_query_param_string (exchange_url),
+    GNUNET_PQ_query_param_uint64 (&exchange_kyc_serial),
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_auto_from_type (&ok),
+    GNUNET_PQ_query_param_end
+  };
+
+  check_connection (pg);
+  (void) GNUNET_TIME_round_abs (&now);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "upsert_account_kyc",
+                                             params);
+}
+
+
 /**
  * Delete private key of an instance from our database.
  *
@@ -6637,6 +6841,40 @@ postgres_connect (void *cls)
                             " FROM merchant_instances"
                             " WHERE merchant_id=$2",
                             2),
+    /* for postgres_account_kyc_set_status */
+    GNUNET_PQ_make_prepare ("upsert_account_kyc",
+                            "INSERT INTO merchant_kyc"
+                            "(kyc_timestamp"
+                            ",kyc_ok"
+                            ",exchange_kyc_serial"
+                            ",account_serial"
+                            ",exchange_url)"
+                            " SELECT $5, $6, $4, account_serial, $3"
+                            " FROM merchant_instances"
+                            " JOIN merchant_accounts USING (merchant_serial)"
+                            " WHERE merchant_id=$1"
+                            "  AND h_wire=$2"
+                            " ON CONFLICT(account_serial,exchange_url) DO "
+                            "UPDATE"
+                            " SET exchange_kyc_serial=$4"
+                            "    ,kyc_ok=$6",
+                            6),
+    /* for postgres_account_kyc_get_status */
+    GNUNET_PQ_make_prepare ("lookup_kyc_status",
+                            "SELECT"
+                            " h_wire"
+                            ",exchange_kyc_serial"
+                            ",payto_uri"
+                            ",exchange_url"
+                            ",kyc_timestamp"
+                            ",kyc_ok"
+                            " FROM merchant_instances"
+                            " JOIN merchant_accounts"
+                            "   USING (merchant_serial)"
+                            " JOIN merchant_kyc"
+                            "   USING (account_serial)"
+                            " WHERE merchant_instances.merchant_id=$1",
+                            1),
     /* for postgres_insert_account() */
     GNUNET_PQ_make_prepare ("insert_account",
                             "INSERT INTO merchant_accounts"
@@ -9091,6 +9329,10 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->lookup_instance_auth = &postgres_lookup_instance_auth;
   plugin->insert_instance = &postgres_insert_instance;
   plugin->insert_account = &postgres_insert_account;
+  plugin->account_kyc_set_status
+    = &postgres_account_kyc_set_status;
+  plugin->account_kyc_get_status
+    = &postgres_account_kyc_get_status;
   plugin->delete_instance_private_key = &postgres_delete_instance_private_key;
   plugin->purge_instance = &postgres_purge_instance;
   plugin->update_instance = &postgres_update_instance;
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index 818172d9..9fd159d8 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -37,8 +37,11 @@ static int result;
  */
 static struct TALER_MERCHANTDB_Plugin *plugin;
 
+/**
+ * @param test 0 on success, non-zero on failure
+ */
 #define TEST_WITH_FAIL_CLAUSE(test, on_fail) \
-  if (0 != (test)) \
+  if ((test)) \
   { \
     GNUNET_break (0); \
     on_fail \
@@ -53,6 +56,9 @@ static struct TALER_MERCHANTDB_Plugin *plugin;
     return 1; \
   }
 
+/**
+ * @param __test 0 on success, non-zero on failure
+ */
 #define TEST_RET_ON_FAIL(__test) \
   TEST_WITH_FAIL_CLAUSE (__test, \
                          return 1; \
@@ -145,8 +151,9 @@ make_account (struct TALER_MERCHANTDB_AccountDetails 
*account)
 {
   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
                                     &account->h_wire);
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &account->salt);
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
+                              &account->salt,
+                              sizeof (account->salt));
   account->payto_uri = "payto://x-taler-bank/bank.demo.taler.net/4";
   account->active = true;
 }
@@ -249,10 +256,10 @@ static int
 check_accounts_equal (const struct TALER_MERCHANTDB_AccountDetails *a,
                       const struct TALER_MERCHANTDB_AccountDetails *b)
 {
-  if ((0 != GNUNET_CRYPTO_hash_cmp (&a->h_wire,
-                                    &b->h_wire)) ||
-      (0 != GNUNET_CRYPTO_hash_cmp (&a->salt,
-                                    &b->salt)) ||
+  if ((0 != GNUNET_memcmp (&a->h_wire,
+                           &b->h_wire)) ||
+      (0 != GNUNET_memcmp (&a->salt,
+                           &b->salt)) ||
       (0 != strcmp (a->payto_uri,
                     b->payto_uri)) ||
       (a->active != b->active))
@@ -6647,6 +6654,119 @@ test_lookup_orders_all_filters (void)
 }
 
 
+static void
+kyc_status_ok (void *cls,
+               const struct GNUNET_HashCode *h_wire,
+               uint64_t exchange_kyc_serial,
+               const char *payto_uri,
+               const char *exchange_url,
+               struct GNUNET_TIME_Absolute last_check,
+               bool kyc_ok)
+{
+  bool *fail = cls;
+
+  if (kyc_ok)
+    *fail = false;
+}
+
+
+static void
+kyc_status_fail (void *cls,
+                 const struct GNUNET_HashCode *h_wire,
+                 uint64_t exchange_kyc_serial,
+                 const char *payto_uri,
+                 const char *exchange_url,
+                 struct GNUNET_TIME_Absolute last_check,
+                 bool kyc_ok)
+{
+  bool *fail = cls;
+
+  if (! kyc_ok)
+    *fail = false;
+}
+
+
+/**
+ * Function that tests the KYC table.
+ *
+ * @return 0 on success, 1 otherwise.
+ */
+static int
+test_kyc (void)
+{
+  struct InstanceData instance;
+  struct TALER_MERCHANTDB_AccountDetails account;
+  bool fail;
+
+  make_instance ("test_kyc",
+                 &instance);
+  make_account (&account);
+  TEST_RET_ON_FAIL (test_insert_instance (&instance,
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (test_insert_account (&instance,
+                                         &account,
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+                    plugin->account_kyc_set_status (plugin->cls,
+                                                    instance.instance.id,
+                                                    &account.h_wire,
+                                                    "https://exchange.net/";,
+                                                    1LLU,
+                                                    false));
+  TEST_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+                    plugin->account_kyc_set_status (plugin->cls,
+                                                    instance.instance.id,
+                                                    &account.h_wire,
+                                                    "https://exchange2.com/";,
+                                                    1LLU,
+                                                    false));
+  TEST_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+                    plugin->account_kyc_set_status (plugin->cls,
+                                                    instance.instance.id,
+                                                    &account.h_wire,
+                                                    "https://exchange.net/";,
+                                                    1LLU,
+                                                    true));
+  fail = true;
+  TEST_RET_ON_FAIL (1 !=
+                    plugin->account_kyc_get_status (plugin->cls,
+                                                    instance.instance.id,
+                                                    &account.h_wire,
+                                                    "https://exchange.net/";,
+                                                    &kyc_status_ok,
+                                                    &fail));
+  TEST_RET_ON_FAIL (fail);
+  fail = true;
+  TEST_RET_ON_FAIL (1 !=
+                    plugin->account_kyc_get_status (plugin->cls,
+                                                    instance.instance.id,
+                                                    NULL,
+                                                    "https://exchange2.com/";,
+                                                    &kyc_status_fail,
+                                                    &fail));
+  TEST_RET_ON_FAIL (fail);
+  fail = true;
+  TEST_RET_ON_FAIL (2 !=
+                    plugin->account_kyc_get_status (plugin->cls,
+                                                    instance.instance.id,
+                                                    NULL,
+                                                    NULL,
+                                                    &kyc_status_fail,
+                                                    &fail));
+  TEST_RET_ON_FAIL (fail);
+  fail = true;
+  TEST_RET_ON_FAIL (2 !=
+                    plugin->account_kyc_get_status (plugin->cls,
+                                                    instance.instance.id,
+                                                    NULL,
+                                                    NULL,
+                                                    &kyc_status_ok,
+                                                    &fail));
+  TEST_RET_ON_FAIL (fail);
+  return 0;
+}
+
+
 /**
  * Function that runs all tests.
  *
@@ -6663,7 +6783,7 @@ run_tests (void)
   TEST_RET_ON_FAIL (test_tips ());
   TEST_RET_ON_FAIL (test_refunds ());
   TEST_RET_ON_FAIL (test_lookup_orders_all_filters ());
-
+  TEST_RET_ON_FAIL (test_kyc ());
   return 0;
 }
 
@@ -6703,14 +6823,16 @@ run (void *cls)
   plugin->preflight (plugin->cls);
 
   result = run_tests ();
-
-  /* Test dropping tables */
-  if (GNUNET_OK != plugin->drop_tables (plugin->cls))
+  if (0 == result)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Dropping tables failed\n");
-    result = 77;
-    return;
+    /* Test dropping tables */
+    if (GNUNET_OK != plugin->drop_tables (plugin->cls))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Dropping tables failed\n");
+      result = 77;
+      return;
+    }
   }
 
   TALER_MERCHANTDB_plugin_unload (plugin);
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 97079680..90681ac6 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -46,7 +46,7 @@ struct TALER_MERCHANTDB_AccountDetails
   /**
    * Salt value used for hashing @e payto_uri.
    */
-  struct GNUNET_HashCode salt;
+  struct TALER_WireSalt salt;
 
   /**
    * Actual account address as a payto://-URI.
@@ -381,6 +381,29 @@ typedef void
   bool pending);
 
 
+/**
+ * Function called from ``account_kyc_get_status``
+ * with KYC status information for this merchant.
+ *
+ * @param cls closure
+ * @param h_wire hash of the wire account
+ * @param exchange_kyc_serial serial number for the KYC process at the 
exchange, 0 if unknown
+ * @param payto_uri payto:// URI of the merchant's bank account
+ * @param exchange_url base URL of the exchange for which this is a status
+ * @param last_check when did we last get an update on our KYC status from the 
exchange
+ * @param kyc_ok true if we satisfied the KYC requirements
+ */
+typedef void
+(*TALER_MERCHANTDB_KycCallback)(
+  void *cls,
+  const struct GNUNET_HashCode *h_wire,
+  uint64_t exchange_kyc_serial,
+  const char *payto_uri,
+  const char *exchange_url,
+  struct GNUNET_TIME_Absolute last_check,
+  bool kyc_ok);
+
+
 /**
  * Results from trying to increase a refund.
  */
@@ -695,8 +718,8 @@ struct TALER_MERCHANTDB_Plugin
    *
    * @param cls closure
    */
-  int
-  (*connect) (void *cls);
+  enum GNUNET_GenericReturnValue
+  (*connect)(void *cls);
 
   /**
    * Drop merchant tables. Used for testcases and to reset the DB.
@@ -704,8 +727,8 @@ struct TALER_MERCHANTDB_Plugin
    * @param cls closure
    * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
    */
-  int
-  (*drop_tables) (void *cls);
+  enum GNUNET_GenericReturnValue
+  (*drop_tables)(void *cls);
 
   /**
    * Initialize merchant tables
@@ -713,8 +736,8 @@ struct TALER_MERCHANTDB_Plugin
    * @param cls closure
    * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
    */
-  int
-  (*create_tables) (void *cls);
+  enum GNUNET_GenericReturnValue
+  (*create_tables)(void *cls);
 
   /**
    * Register callback to be invoked on events of type @a es.
@@ -776,9 +799,9 @@ struct TALER_MERCHANTDB_Plugin
    *             must point to a constant
    * @return #GNUNET_OK on success
    */
-  int
-  (*start) (void *cls,
-            const char *name);
+  enum GNUNET_GenericReturnValue
+  (*start)(void *cls,
+           const char *name);
 
   /**
    * Start a transaction with isolation level 'read committed'.
@@ -788,9 +811,9 @@ struct TALER_MERCHANTDB_Plugin
    *             must point to a constant
    * @return #GNUNET_OK on success
    */
-  int
-  (*start_read_committed) (void *cls,
-                           const char *name);
+  enum GNUNET_GenericReturnValue
+  (*start_read_committed)(void *cls,
+                          const char *name);
 
   /**
    * Roll back the current transaction of a database connection.
@@ -928,10 +951,10 @@ struct TALER_MERCHANTDB_Plugin
    * @return database result code
    */
   enum GNUNET_DB_QueryStatus
-  (*update_instance_auth)(void *cls,
-                          const char *merchant_id,
-                          const struct
-                          TALER_MERCHANTDB_InstanceAuthSettings *ias);
+  (*update_instance_auth)(
+    void *cls,
+    const char *merchant_id,
+    const struct TALER_MERCHANTDB_InstanceAuthSettings *ias);
 
   /**
    * Set an instance's account in our database to "inactive".
@@ -960,6 +983,48 @@ struct TALER_MERCHANTDB_Plugin
                       const char *merchant_id,
                       const struct GNUNET_HashCode *h_wire);
 
+
+  /**
+   * Check an instance's account's KYC status.
+   *
+   * @param cls closure
+   * @param merchant_id merchant backend instance ID
+   * @param h_wire hash of the wire account to check,
+   *        NULL to check all accounts of the merchant
+   * @param exchange_url base URL of the exchange to check,
+   *        NULL to check all exchanges
+   * @param kyc_cb KYC status callback to invoke
+   * @param kyc_cb_cls closure for @a kyc_cb
+   * @return database result code
+   */
+  enum GNUNET_DB_QueryStatus
+  (*account_kyc_get_status)(void *cls,
+                            const char *merchant_id,
+                            const struct GNUNET_HashCode *h_wire,
+                            const char *exchange_url,
+                            TALER_MERCHANTDB_KycCallback kyc_cb,
+                            void *kyc_cb_cls);
+
+  /**
+   * Update an instance's account's KYC status.
+   *
+   * @param cls closure
+   * @param merchant_id merchant backend instance ID
+   * @param h_wire hash of the wire account to check
+   * @param exchange_url base URL of the exchange to check
+   * @param exchange_kyc_serial serial number for our account at the exchange 
(0 if unknown)
+   * @param kyc_ok current KYC status (true for satisfied)
+   * @return database result code
+   */
+  enum GNUNET_DB_QueryStatus
+  (*account_kyc_set_status)(void *cls,
+                            const char *merchant_id,
+                            const struct GNUNET_HashCode *h_wire,
+                            const char *exchange_url,
+                            uint64_t exchange_kyc_serial,
+                            bool kyc_ok);
+
+
   /**
    * Lookup all of the products the given instance has configured.
    *

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]