gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: add new endpoints to main dispat


From: gnunet
Subject: [taler-exchange] branch master updated: add new endpoints to main dispatcher
Date: Sat, 21 Jan 2023 23:08:32 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new d131951f add new endpoints to main dispatcher
d131951f is described below

commit d131951fbe09b3415c9976acd11f660d51493086
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat Jan 21 23:08:29 2023 +0100

    add new endpoints to main dispatcher
---
 contrib/gana                                       |   2 +-
 src/exchange/Makefile.am                           |   3 +
 src/exchange/taler-exchange-httpd.c                | 226 ++++++++++++++++++++-
 src/exchange/taler-exchange-httpd.h                |   4 +-
 src/exchange/taler-exchange-httpd_aml-decision.c   |  57 +++---
 src/exchange/taler-exchange-httpd_aml-decision.h   |  45 ++++
 src/exchange/taler-exchange-httpd_management.h     |  26 +++
 .../taler-exchange-httpd_management_aml-officers.c |  21 +-
 .../taler-exchange-httpd_management_partners.c     |  29 ++-
 src/exchangedb/0002-partners.sql                   |   1 +
 src/exchangedb/pg_insert_aml_decision.c            |  12 +-
 src/exchangedb/pg_insert_aml_decision.h            |   9 +-
 src/exchangedb/pg_insert_aml_officer.c             |   8 +-
 src/exchangedb/pg_insert_aml_officer.h             |   9 +-
 src/exchangedb/pg_insert_partner.c                 |  19 +-
 src/include/taler_exchangedb_plugin.h              |  13 +-
 src/lib/exchange_api_add_aml_decision.c            |   2 +-
 src/lib/exchange_api_management_add_partner.c      |  26 +--
 .../exchange_api_management_update_aml_officer.c   |  24 +--
 19 files changed, 419 insertions(+), 117 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index 66228b8a..7884adf9 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 66228b8a4306f028d843d78fbfcca54260539ff9
+Subproject commit 7884adf99ec4d5ccf52b1a5a251b99fb6ab9c2f6
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
index 29596c38..ffcfc5e9 100644
--- a/src/exchange/Makefile.am
+++ b/src/exchange/Makefile.am
@@ -123,6 +123,7 @@ taler_exchange_wirewatch_LDADD = \
 taler_exchange_httpd_SOURCES = \
   taler-exchange-httpd.c taler-exchange-httpd.h \
   taler-exchange-httpd_auditors.c taler-exchange-httpd_auditors.h \
+  taler-exchange-httpd_aml-decision.c taler-exchange-httpd_aml-decision.h \
   taler-exchange-httpd_batch-deposit.c taler-exchange-httpd_batch-deposit.h \
   taler-exchange-httpd_batch-withdraw.c taler-exchange-httpd_batch-withdraw.h \
   taler-exchange-httpd_common_deposit.c taler-exchange-httpd_common_deposit.h \
@@ -139,12 +140,14 @@ taler_exchange_httpd_SOURCES = \
   taler-exchange-httpd_kyc-webhook.c taler-exchange-httpd_kyc-webhook.h \
   taler-exchange-httpd_link.c taler-exchange-httpd_link.h \
   taler-exchange-httpd_management.h \
+  taler-exchange-httpd_management_aml-officers.c \
   taler-exchange-httpd_management_auditors.c \
   taler-exchange-httpd_management_auditors_AP_disable.c \
   taler-exchange-httpd_management_denominations_HDP_revoke.c \
   taler-exchange-httpd_management_drain.c \
   taler-exchange-httpd_management_extensions.c \
   taler-exchange-httpd_management_global_fees.c \
+  taler-exchange-httpd_management_partners.c \
   taler-exchange-httpd_management_post_keys.c \
   taler-exchange-httpd_management_signkey_EP_revoke.c \
   taler-exchange-httpd_management_wire_enable.c \
diff --git a/src/exchange/taler-exchange-httpd.c 
b/src/exchange/taler-exchange-httpd.c
index def4fd4a..5501687f 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -1,6 +1,6 @@
 /*
    This file is part of TALER
-   Copyright (C) 2014-2022 Taler Systems SA
+   Copyright (C) 2014-2023 Taler Systems SA
 
    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
@@ -30,6 +30,7 @@
 #include "taler_kyclogic_lib.h"
 #include "taler_templating_lib.h"
 #include "taler_mhd_lib.h"
+#include "taler-exchange-httpd_aml-decision.h"
 #include "taler-exchange-httpd_auditors.h"
 #include "taler-exchange-httpd_batch-deposit.h"
 #include "taler-exchange-httpd_batch-withdraw.h"
@@ -322,6 +323,187 @@ handle_post_coins (struct TEH_RequestContext *rc,
 }
 
 
+/**
+ * Signature of functions that handle operations
+ * authorized by AML officers.
+ *
+ * @param rc request context
+ * @param officer_pub the public key of the AML officer
+ * @param root uploaded JSON data
+ * @return MHD result code
+ */
+typedef MHD_RESULT
+(*AmlOpPostHandler)(struct TEH_RequestContext *rc,
+                    const struct TALER_AmlOfficerPublicKeyP *officer_pub,
+                    const json_t *root);
+
+
+/**
+ * Handle a "/aml/$OFFICER_PUB/$OP" POST request.  Parses the "officer_pub"
+ * EdDSA key of the officer and demultiplexes based on $OP.
+ *
+ * @param rc request context
+ * @param root uploaded JSON data
+ * @param args array of additional options
+ * @return MHD result code
+ */
+static MHD_RESULT
+handle_post_aml (struct TEH_RequestContext *rc,
+                 const json_t *root,
+                 const char *const args[2])
+{
+  struct TALER_AmlOfficerPublicKeyP officer_pub;
+  static const struct
+  {
+    /**
+     * Name of the operation (args[1])
+     */
+    const char *op;
+
+    /**
+     * Function to call to perform the operation.
+     */
+    AmlOpPostHandler handler;
+
+  } h[] = {
+    {
+      .op = "decision",
+      .handler = &TEH_handler_post_aml_decision
+    },
+    {
+      .op = NULL,
+      .handler = NULL
+    },
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (args[0],
+                                     strlen (args[0]),
+                                     &officer_pub,
+                                     sizeof (officer_pub)))
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_PUB_MALFORMED,
+                                       args[0]);
+  }
+  for (unsigned int i = 0; NULL != h[i].op; i++)
+    if (0 == strcmp (h[i].op,
+                     args[1]))
+      return h[i].handler (rc,
+                           &officer_pub,
+                           root);
+  return r404 (rc->connection,
+               args[1]);
+}
+
+
+/**
+ * Signature of functions that handle operations
+ * authorized by AML officers.
+ *
+ * @param rc request context
+ * @param officer_pub the public key of the AML officer
+ * @param args remaining arguments
+ * @return MHD result code
+ */
+typedef MHD_RESULT
+(*AmlOpGetHandler)(struct TEH_RequestContext *rc,
+                   const struct TALER_AmlOfficerPublicKeyP *officer_pub,
+                   const char *const args[]);
+
+
+/**
+ * Handle a "/aml/$OFFICER_PUB/$OP" GET request.  Parses the "officer_pub"
+ * EdDSA key of the officer, checks the authentication signature, and
+ * demultiplexes based on $OP.
+ *
+ * @param rc request context
+ * @param args array of additional options
+ * @return MHD result code
+ */
+static MHD_RESULT
+handle_get_aml (struct TEH_RequestContext *rc,
+                const char *const args[])
+{
+  struct TALER_AmlOfficerPublicKeyP officer_pub;
+  static const struct
+  {
+    /**
+     * Name of the operation (args[1])
+     */
+    const char *op;
+
+    /**
+     * Function to call to perform the operation.
+     */
+    AmlOpGetHandler handler;
+
+  } h[] = {
+#if FIXME_AML_GET_DECISIONS_NOT_IMPLEMENTED
+    {
+      .op = "decisions",
+      .handler = &TEH_handler_get_aml_decisions
+    },
+    {
+      .op = "decision",
+      .handler = &TEH_handler_get_aml_decision
+    },
+#endif
+    {
+      .op = NULL,
+      .handler = NULL
+    },
+  };
+
+  if (NULL == args[0])
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_PUB_MALFORMED,
+                                       "argument missing");
+  }
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (args[0],
+                                     strlen (args[0]),
+                                     &officer_pub,
+                                     sizeof (officer_pub)))
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_PUB_MALFORMED,
+                                       args[0]);
+  }
+  if (NULL == args[1])
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_NOT_FOUND,
+                                       
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
+                                       "AML GET operations must specify an 
operation identifier");
+  }
+  if (1)   // FIXME: check AML officer GET signature!
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_FORBIDDEN,
+                                       
TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID,
+                                       NULL);
+  }
+  for (unsigned int i = 0; NULL != h[i].op; i++)
+    if (0 == strcmp (h[i].op,
+                     args[1]))
+      return h[i].handler (rc,
+                           &officer_pub,
+                           &args[2]);
+  return r404 (rc->connection,
+               args[1]);
+}
+
+
 /**
  * Signature of functions that handle operations on reserves.
  *
@@ -890,6 +1072,8 @@ handle_post_management (struct TEH_RequestContext *rc,
                                                       &exchange_pub,
                                                       root);
   }
+  /* FIXME-STYLE: all of the following can likely be nicely combined
+     into an array-based dispatcher to deduplicate the logic... */
   if (0 == strcmp (args[0],
                    "keys"))
   {
@@ -967,6 +1151,30 @@ handle_post_management (struct TEH_RequestContext *rc,
     return TEH_handler_management_post_drain (rc->connection,
                                               root);
   }
+  if (0 == strcmp (args[0],
+                   "aml-officers"))
+  {
+    if (NULL != args[1])
+    {
+      GNUNET_break_op (0);
+      return r404 (rc->connection,
+                   "/management/aml-officers/*");
+    }
+    return TEH_handler_management_aml_officers (rc->connection,
+                                                root);
+  }
+  if (0 == strcmp (args[0],
+                   "partners"))
+  {
+    if (NULL != args[1])
+    {
+      GNUNET_break_op (0);
+      return r404 (rc->connection,
+                   "/management/partners/*");
+    }
+    return TEH_handler_management_partners (rc->connection,
+                                            root);
+  }
   GNUNET_break_op (0);
   return r404 (rc->connection,
                "/management/*");
@@ -1289,6 +1497,22 @@ handle_mhd_request (void *cls,
       .nargs = 4,
       .nargs_is_upper_bound = true
     },
+    /* AML endpoints */
+    {
+      .url = "aml",
+      .method = MHD_HTTP_METHOD_GET,
+      .handler.get = &handle_get_aml,
+      .nargs = 4,
+      .nargs_is_upper_bound = true
+    },
+    {
+      .url = "aml",
+      .method = MHD_HTTP_METHOD_POST,
+      .handler.post = &handle_post_aml,
+      .nargs = 2
+    },
+
+
     /* mark end of list */
     {
       .url = NULL
diff --git a/src/exchange/taler-exchange-httpd.h 
b/src/exchange/taler-exchange-httpd.h
index 2be26f14..7715444a 100644
--- a/src/exchange/taler-exchange-httpd.h
+++ b/src/exchange/taler-exchange-httpd.h
@@ -213,7 +213,7 @@ struct TEH_RequestHandler
      *
      * @param rc context for the request
      * @param json uploaded JSON data
-     * @param args array of arguments, needs to be of length @e args_expected
+     * @param args array of arguments, needs to be of length @e nargs
      * @return MHD result code
      */
     MHD_RESULT
@@ -225,7 +225,7 @@ struct TEH_RequestHandler
      * Function to call to handle DELETE requests.
      *
      * @param rc context for the request
-     * @param args array of arguments, needs to be of length @e args_expected
+     * @param args array of arguments, needs to be of length @e nargs
      * @return MHD result code
      */
     MHD_RESULT
diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c 
b/src/exchange/taler-exchange-httpd_aml-decision.c
index c93c1066..4589c8eb 100644
--- a/src/exchange/taler-exchange-httpd_aml-decision.c
+++ b/src/exchange/taler-exchange-httpd_aml-decision.c
@@ -31,27 +31,26 @@
 
 
 MHD_RESULT
-TEH_handler_management_post_aml_decision (
-  struct MHD_Connection *connection,
+TEH_handler_post_aml_decision (
+  struct TEH_RequestContext *rc,
+  const struct TALER_AmlOfficerPublicKeyP *officer_pub,
   const json_t *root)
 {
+  struct MHD_Connection *connection = rc->connection;
   const char *justification;
   struct GNUNET_TIME_Timestamp decision_time;
   struct TALER_Amount new_threshold;
   struct TALER_PaytoHashP h_payto;
   uint32_t new_state32;
   enum TALER_AmlDecisionState new_state;
-  struct TALER_AmlOfficerPublicKeyP officer_pub;
   struct TALER_AmlOfficerSignatureP officer_sig;
   struct GNUNET_JSON_Specification spec[] = {
-    // FIXME: officer_pub is in URL path, not in JSON body!
-    GNUNET_JSON_spec_fixed_auto ("officer_pub",
-                                 &officer_pub),
     GNUNET_JSON_spec_fixed_auto ("officer_sig",
                                  &officer_sig),
     GNUNET_JSON_spec_fixed_auto ("h_payto",
                                  &h_payto),
     TALER_JSON_spec_amount ("new_threshold",
+                            TEH_currency,
                             &new_threshold),
     GNUNET_JSON_spec_string ("justification",
                              &justification),
@@ -76,13 +75,13 @@ TEH_handler_management_post_aml_decision (
   new_state = (enum TALER_AmlDecisionState) new_state32;
   TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
   if (GNUNET_OK !=
-      TALER_exchange_aml_decision_verify (justification,
-                                          decision_time,
-                                          &new_threshold,
-                                          &h_payto,
-                                          new_state,
-                                          &officer_pub,
-                                          &officer_sig))
+      TALER_officer_aml_decision_verify (justification,
+                                         decision_time,
+                                         &new_threshold,
+                                         &h_payto,
+                                         new_state,
+                                         &officer_pub,
+                                         &officer_sig))
   {
     GNUNET_break_op (0);
     return TALER_MHD_reply_with_error (
@@ -97,25 +96,25 @@ TEH_handler_management_post_aml_decision (
     bool invalid_officer;
 
     do {
-      qs = TEH_plugin->add_aml_decision (TEH_plugin->cls,
-                                         justification,
-                                         decision_time,
-                                         &new_threshold,
-                                         &h_payto,
-                                         new_state,
-                                         &officer_pub,
-                                         &officer_sig,
-                                         &invalid_officer,
-                                         &last_date);
+      // FIXME: bound loop?
+      qs = TEH_plugin->insert_aml_decision (TEH_plugin->cls,
+                                            &h_payto,
+                                            &new_threshold,
+                                            new_state,
+                                            decision_time,
+                                            justification,
+                                            &officer_pub,
+                                            &officer_sig,
+                                            &invalid_officer,
+                                            &last_date);
     } while (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     if (qs < 0)
     {
       GNUNET_break (0);
-      *mhd_ret = TALER_MHD_reply_with_error (connection,
-                                             MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                             TALER_EC_GENERIC_DB_STORE_FAILED,
-                                             "add aml_decision");
-      return qs;
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         TALER_EC_GENERIC_DB_STORE_FAILED,
+                                         "add aml_decision");
     }
     if (invalid_officer)
     {
@@ -127,7 +126,7 @@ TEH_handler_management_post_aml_decision (
     }
     if (GNUNET_TIME_timestamp_cmp (last_date,
                                    >,
-                                   validity_start))
+                                   decision_time))
     {
       GNUNET_break_op (0);
       return TALER_MHD_reply_with_error (
diff --git a/src/exchange/taler-exchange-httpd_aml-decision.h 
b/src/exchange/taler-exchange-httpd_aml-decision.h
new file mode 100644
index 00000000..e6e35552
--- /dev/null
+++ b/src/exchange/taler-exchange-httpd_aml-decision.h
@@ -0,0 +1,45 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2023 Taler Systems SA
+
+  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.
+
+  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 Affero General Public License for more 
details.
+
+  You should have received a copy of the GNU Affero General Public License 
along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-exchange-httpd_aml_decision.h
+ * @brief Handle /aml/$OFFICER_PUB/decision requests
+ * @author Christian Grothoff
+ */
+#ifndef TALER_EXCHANGE_HTTPD_AML_DECISION_H
+#define TALER_EXCHANGE_HTTPD_AML_DECISION_H
+
+#include <microhttpd.h>
+#include "taler-exchange-httpd.h"
+
+
+/**
+ * Handle an "/aml/$OFFICER_PUB/decision" request.  Parses the decision
+ * details, checks the signatures and if appropriately authorized excecutes
+ * the decision.
+ *
+ * @param rc request context
+ * @param officer_pub public key of the AML officer who made the request
+ * @param root uploaded JSON data
+ * @return MHD result code
+  */
+MHD_RESULT
+TEH_handler_post_aml_decision (
+  struct TEH_RequestContext *rc,
+  const struct TALER_AmlOfficerPublicKeyP *officer_pub,
+  const json_t *root);
+
+
+#endif
diff --git a/src/exchange/taler-exchange-httpd_management.h 
b/src/exchange/taler-exchange-httpd_management.h
index a5a8b0e7..2fc1fe8d 100644
--- a/src/exchange/taler-exchange-httpd_management.h
+++ b/src/exchange/taler-exchange-httpd_management.h
@@ -174,6 +174,32 @@ TEH_handler_management_post_drain (
   const json_t *root);
 
 
+/**
+ * Handle a POST "/management/aml-officers" request.
+ *
+ * @param connection the MHD connection to handle
+ * @param root uploaded JSON data
+ * @return MHD result code
+ */
+MHD_RESULT
+TEH_handler_management_aml_officers (
+  struct MHD_Connection *connection,
+  const json_t *root);
+
+
+/**
+ * Handle a POST "/management/partners" request.
+ *
+ * @param connection the MHD connection to handle
+ * @param root uploaded JSON data
+ * @return MHD result code
+ */
+MHD_RESULT
+TEH_handler_management_partners (
+  struct MHD_Connection *connection,
+  const json_t *root);
+
+
 /**
  * Initialize extension configuration handling.
  *
diff --git a/src/exchange/taler-exchange-httpd_management_aml-officers.c 
b/src/exchange/taler-exchange-httpd_management_aml-officers.c
index 139ccdb2..b82c18d4 100644
--- a/src/exchange/taler-exchange-httpd_management_aml-officers.c
+++ b/src/exchange/taler-exchange-httpd_management_aml-officers.c
@@ -92,14 +92,15 @@ TEH_handler_management_aml_officers (
     struct GNUNET_TIME_Timestamp last_date;
 
     do {
-      qs = TEH_plugin->set_aml_officer (TEH_plugin->cls,
-                                        &officer_pub,
-                                        officer_name,
-                                        change_date,
-                                        is_active,
-                                        read_only,
-                                        &master_sig,
-                                        &last_date);
+      // FIXME: bound loop!
+      qs = TEH_plugin->insert_aml_officer (TEH_plugin->cls,
+                                           &officer_pub,
+                                           &master_sig,
+                                           officer_name,
+                                           is_active,
+                                           read_only,
+                                           change_date,
+                                           &last_date);
     } while (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     if (qs < 0)
     {
@@ -107,13 +108,13 @@ TEH_handler_management_aml_officers (
       return TALER_MHD_reply_with_error (connection,
                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
                                          TALER_EC_GENERIC_DB_STORE_FAILED,
-                                         "XXX");
+                                         "insert_aml_officer");
     }
     if (GNUNET_TIME_timestamp_cmp (last_date,
                                    >,
                                    change_date))
     {
-      GNUNER_break_op (0);
+      GNUNET_break_op (0);
       return TALER_MHD_reply_with_error (
         connection,
         MHD_HTTP_CONFLICT,
diff --git a/src/exchange/taler-exchange-httpd_management_partners.c 
b/src/exchange/taler-exchange-httpd_management_partners.c
index 5d860120..1c0d4a9a 100644
--- a/src/exchange/taler-exchange-httpd_management_partners.c
+++ b/src/exchange/taler-exchange-httpd_management_partners.c
@@ -51,13 +51,14 @@ TEH_handler_management_partners (
     GNUNET_JSON_spec_string ("partner_base_url",
                              &partner_base_url),
     TALER_JSON_spec_amount ("wad_fee",
+                            TEH_currency,
                             &wad_fee),
     GNUNET_JSON_spec_timestamp ("start_date",
                                 &start_date),
     GNUNET_JSON_spec_timestamp ("end_date",
                                 &start_date),
-    GNUNET_JSON_spec_time_rel ("wad_frequency",
-                               &wad_frequency),
+    GNUNET_JSON_spec_relative_time ("wad_frequency",
+                                    &wad_frequency),
     GNUNET_JSON_spec_end ()
   };
 
@@ -94,14 +95,14 @@ TEH_handler_management_partners (
   {
     enum GNUNET_DB_QueryStatus qs;
 
-    qs = TEH_plugin->add_partner (TEH_plugin->cls,
-                                  &partner_pub,
-                                  start_date,
-                                  end_date,
-                                  wad_frequency,
-                                  &wad_fee,
-                                  partner_base_url,
-                                  &master_sig);
+    qs = TEH_plugin->insert_partner (TEH_plugin->cls,
+                                     &partner_pub,
+                                     start_date,
+                                     end_date,
+                                     wad_frequency,
+                                     &wad_fee,
+                                     partner_base_url,
+                                     &master_sig);
     if (qs < 0)
     {
       GNUNET_break (0);
@@ -110,6 +111,14 @@ TEH_handler_management_partners (
                                          TALER_EC_GENERIC_DB_STORE_FAILED,
                                          "add_partner");
     }
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+    {
+      /* FIXME: check for idempotency! */
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_CONFLICT,
+                                         
TALER_EC_EXCHANGE_MANAGEMENT_ADD_PARTNER_DATA_CONFLICT,
+                                         NULL);
+    }
   }
   return TALER_MHD_reply_static (
     connection,
diff --git a/src/exchangedb/0002-partners.sql b/src/exchangedb/0002-partners.sql
index ff57f8fc..c80f2d74 100644
--- a/src/exchangedb/0002-partners.sql
+++ b/src/exchangedb/0002-partners.sql
@@ -25,6 +25,7 @@ CREATE TABLE partners
   ,wad_fee_frac INT4 NOT NULL
   ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
   ,partner_base_url TEXT NOT NULL
+  ,PRIMARY KEY (partner_master_pub, start_date)
   );
 COMMENT ON TABLE partners
   IS 'exchanges we do wad transfers to';
diff --git a/src/exchangedb/pg_insert_aml_decision.c 
b/src/exchangedb/pg_insert_aml_decision.c
index d046c87f..421628f6 100644
--- a/src/exchangedb/pg_insert_aml_decision.c
+++ b/src/exchangedb/pg_insert_aml_decision.c
@@ -1,6 +1,6 @@
 /*
    This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
+   Copyright (C) 2022, 2023 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
@@ -32,10 +32,12 @@ TEH_PG_insert_aml_decision (
   const struct TALER_PaytoHashP *h_payto,
   const struct TALER_Amount *new_threshold,
   enum TALER_AmlDecisionState new_status,
-  struct GNUNET_TIME_Absolute decision_time,
+  struct GNUNET_TIME_Timestamp decision_time,
   const char *justification,
   const struct TALER_AmlOfficerPublicKeyP *decider_pub,
-  const struct TALER_AmlOfficerSignatureP *decider_sig)
+  const struct TALER_AmlOfficerSignatureP *decider_sig,
+  bool *invalid_officer,
+  struct GNUNET_TIME_Timestamp *last_date)
 {
   struct PostgresClosure *pg = cls;
   uint32_t ns = (uint32_t) new_status;
@@ -43,13 +45,15 @@ TEH_PG_insert_aml_decision (
     GNUNET_PQ_query_param_auto_from_type (h_payto),
     TALER_PQ_query_param_amount (new_threshold),
     GNUNET_PQ_query_param_uint32 (&ns),
-    GNUNET_PQ_query_param_absolute_time (&decision_time),
+    GNUNET_PQ_query_param_timestamp (&decision_time),
     GNUNET_PQ_query_param_string (justification),
     GNUNET_PQ_query_param_auto_from_type (decider_pub),
     GNUNET_PQ_query_param_auto_from_type (decider_sig),
     GNUNET_PQ_query_param_end
   };
 
+  // FIXME: set invalid_officer
+  // FIXME: set last_date!
   PREPARE (pg,
            "insert_aml_decision",
            "INSERT INTO aml_history "
diff --git a/src/exchangedb/pg_insert_aml_decision.h 
b/src/exchangedb/pg_insert_aml_decision.h
index 205c1c74..94f648fb 100644
--- a/src/exchangedb/pg_insert_aml_decision.h
+++ b/src/exchangedb/pg_insert_aml_decision.h
@@ -38,6 +38,9 @@
  * @param justification human-readable text justifying the decision
  * @param decider_pub public key of the staff member
  * @param decider_sig signature of the staff member
+ * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to 
make decisions right now
+ * @param[out] last_date set to the previous decision time;
+ *   the INSERT is not performed if @a last_date is not before @a decision_time
  * @return database transaction status
  */
 enum GNUNET_DB_QueryStatus
@@ -46,10 +49,12 @@ TEH_PG_insert_aml_decision (
   const struct TALER_PaytoHashP *h_payto,
   const struct TALER_Amount *new_threshold,
   enum TALER_AmlDecisionState new_status,
-  struct GNUNET_TIME_Absolute decision_time,
+  struct GNUNET_TIME_Timestamp decision_time,
   const char *justification,
   const struct TALER_AmlOfficerPublicKeyP *decider_pub,
-  const struct TALER_AmlOfficerSignatureP *decider_sig);
+  const struct TALER_AmlOfficerSignatureP *decider_sig,
+  bool *invalid_officer,
+  struct GNUNET_TIME_Timestamp *last_date);
 
 
 #endif
diff --git a/src/exchangedb/pg_insert_aml_officer.c 
b/src/exchangedb/pg_insert_aml_officer.c
index fc2cadef..33e6c86f 100644
--- a/src/exchangedb/pg_insert_aml_officer.c
+++ b/src/exchangedb/pg_insert_aml_officer.c
@@ -1,6 +1,6 @@
 /*
    This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
+   Copyright (C) 2022, 2023 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
@@ -34,7 +34,8 @@ TEH_PG_insert_aml_officer (
   const char *decider_name,
   bool is_active,
   bool read_only,
-  struct GNUNET_TIME_Absolute last_change)
+  struct GNUNET_TIME_Timestamp last_change,
+  struct GNUNET_TIME_Timestamp *previous_change)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
@@ -43,10 +44,11 @@ TEH_PG_insert_aml_officer (
     GNUNET_PQ_query_param_string (decider_name),
     GNUNET_PQ_query_param_bool (is_active),
     GNUNET_PQ_query_param_bool (read_only),
-    GNUNET_PQ_query_param_absolute_time (&last_change),
+    GNUNET_PQ_query_param_timestamp (&last_change),
     GNUNET_PQ_query_param_end
   };
 
+  // FIXME: need to check for previous record!
   PREPARE (pg,
            "insert_aml_staff",
            "INSERT INTO aml_staff "
diff --git a/src/exchangedb/pg_insert_aml_officer.h 
b/src/exchangedb/pg_insert_aml_officer.h
index be034d9f..3c6f5d82 100644
--- a/src/exchangedb/pg_insert_aml_officer.h
+++ b/src/exchangedb/pg_insert_aml_officer.h
@@ -27,7 +27,10 @@
 
 
 /**
- * Insert AML staff record.
+ * Insert AML staff record.  If the time given in
+ * @a last_change is before the previous change in the
+ * database, only @e previous_change is returned and
+ * no actual change is committed to the database.
  *
  * @param cls closure
  * @param decider_pub public key of the staff member
@@ -36,6 +39,7 @@
  * @param is_active true to enable, false to set as inactive
  * @param read_only true to set read-only access
  * @param last_change when was the change made effective
+ * @param[out] previous_change set to the time of the previous change
  * @return database transaction status
  */
 enum GNUNET_DB_QueryStatus
@@ -46,6 +50,7 @@ TEH_PG_insert_aml_officer (
   const char *decider_name,
   bool is_active,
   bool read_only,
-  struct GNUNET_TIME_Absolute last_change);
+  struct GNUNET_TIME_Timestamp last_change,
+  struct GNUNET_TIME_Timestamp *previous_change);
 
 #endif
diff --git a/src/exchangedb/pg_insert_partner.c 
b/src/exchangedb/pg_insert_partner.c
index 567f3776..5abb2c91 100644
--- a/src/exchangedb/pg_insert_partner.c
+++ b/src/exchangedb/pg_insert_partner.c
@@ -28,13 +28,13 @@
 
 enum GNUNET_DB_QueryStatus
 TEH_PG_insert_partner (void *cls,
-                         const struct TALER_MasterPublicKeyP *master_pub,
-                         struct GNUNET_TIME_Timestamp start_date,
-                         struct GNUNET_TIME_Timestamp end_date,
-                         struct GNUNET_TIME_Relative wad_frequency,
-                         const struct TALER_Amount *wad_fee,
-                         const char *partner_base_url,
-                         const struct TALER_MasterSignatureP *master_sig)
+                       const struct TALER_MasterPublicKeyP *master_pub,
+                       struct GNUNET_TIME_Timestamp start_date,
+                       struct GNUNET_TIME_Timestamp end_date,
+                       struct GNUNET_TIME_Relative wad_frequency,
+                       const struct TALER_Amount *wad_fee,
+                       const char *partner_base_url,
+                       const struct TALER_MasterSignatureP *master_sig)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
@@ -61,10 +61,9 @@ TEH_PG_insert_partner (void *cls,
            "  ,master_sig"
            "  ,partner_base_url"
            "  ) VALUES "
-           "  ($1, $2, $3, $4, $5, $6, $7, $8);");
+           "  ($1, $2, $3, $4, $5, $6, $7, $8)"
+           "  ON CONFLICT DO NOTHING;");
   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                              "insert_partner",
                                              params);
 }
-
-
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 146321ea..d6bf798c 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -6602,6 +6602,7 @@ struct TALER_EXCHANGEDB_Plugin
    * @param is_active true to enable, false to set as inactive
    * @param read_only true to set read-only access
    * @param last_change when was the change made effective
+   * @param[out] previous_change when was the previous change made
    * @return database transaction status
    */
   enum GNUNET_DB_QueryStatus
@@ -6612,7 +6613,8 @@ struct TALER_EXCHANGEDB_Plugin
     const char *decider_name,
     bool is_active,
     bool read_only,
-    struct GNUNET_TIME_Absolute last_change);
+    struct GNUNET_TIME_Timestamp last_change,
+    struct GNUNET_TIME_Timestamp *previous_change);
 
 
   /**
@@ -6727,6 +6729,9 @@ struct TALER_EXCHANGEDB_Plugin
    * @param justification human-readable text justifying the decision
    * @param decider_pub public key of the staff member
    * @param decider_sig signature of the staff member
+   * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed 
to make decisions right now
+   * @param[out] last_date set to the previous decision time;
+   *   the INSERT is not performed if @a last_date is not before @a 
decision_time
    * @return database transaction status
    */
   enum GNUNET_DB_QueryStatus
@@ -6735,10 +6740,12 @@ struct TALER_EXCHANGEDB_Plugin
     const struct TALER_PaytoHashP *h_payto,
     const struct TALER_Amount *new_threshold,
     enum TALER_AmlDecisionState new_status,
-    struct GNUNET_TIME_Absolute decision_time,
+    struct GNUNET_TIME_Timestamp decision_time,
     const char *justification,
     const struct TALER_AmlOfficerPublicKeyP *decider_pub,
-    const struct TALER_AmlOfficerSignatureP *decider_sig);
+    const struct TALER_AmlOfficerSignatureP *decider_sig,
+    bool *invalid_officer,
+    struct GNUNET_TIME_Timestamp *last_date);
 
 
 };
diff --git a/src/lib/exchange_api_add_aml_decision.c 
b/src/lib/exchange_api_add_aml_decision.c
index d4b0d125..c6283532 100644
--- a/src/lib/exchange_api_add_aml_decision.c
+++ b/src/lib/exchange_api_add_aml_decision.c
@@ -167,7 +167,7 @@ TALER_EXCHANGE_add_aml_decision (
       sizeof (opus));
     *end = '\0';
     GNUNET_asprintf (&path,
-                     "aml-decision/%s",
+                     "aml/%s/decision",
                      opus);
     wh->url = TALER_url_join (url,
                               path,
diff --git a/src/lib/exchange_api_management_add_partner.c 
b/src/lib/exchange_api_management_add_partner.c
index 264fd664..75fb8aa6 100644
--- a/src/lib/exchange_api_management_add_partner.c
+++ b/src/lib/exchange_api_management_add_partner.c
@@ -66,7 +66,7 @@ struct TALER_EXCHANGE_ManagementAddPartner
 
 /**
  * Function called when we're done processing the
- * HTTP POST /aml-decision/$OFFICER_PUB request.
+ * HTTP POST /management/partners request.
  *
  * @param cls the `struct TALER_EXCHANGE_ManagementAddPartner *`
  * @param response_code HTTP response code, 0 on error
@@ -145,25 +145,9 @@ TALER_EXCHANGE_management_add_partner (
   wh->cb = cb;
   wh->cb_cls = cb_cls;
   wh->ctx = ctx;
-  {
-    char *path;
-    char opus[sizeof (*partner_pub) * 2];
-    char *end;
-
-    end = GNUNET_STRINGS_data_to_string (
-      partner_pub,
-      sizeof (*partner_pub),
-      opus,
-      sizeof (opus));
-    *end = '\0';
-    GNUNET_asprintf (&path,
-                     "management/partners/%s",
-                     opus);
-    wh->url = TALER_url_join (url,
-                              path,
-                              NULL);
-    GNUNET_free (path);
-  }
+  wh->url = TALER_url_join (url,
+                            "management/partners",
+                            NULL);
   if (NULL == wh->url)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -180,6 +164,8 @@ TALER_EXCHANGE_management_add_partner (
                                 end_date),
     GNUNET_JSON_pack_time_rel ("wad_frequency",
                                wad_frequency),
+    GNUNET_JSON_pack_data_auto ("partner_pub",
+                                &partner_pub),
     GNUNET_JSON_pack_data_auto ("master_sig",
                                 &master_sig),
     TALER_JSON_pack_amount ("wad_fee",
diff --git a/src/lib/exchange_api_management_update_aml_officer.c 
b/src/lib/exchange_api_management_update_aml_officer.c
index 96ff5a4c..6e166946 100644
--- a/src/lib/exchange_api_management_update_aml_officer.c
+++ b/src/lib/exchange_api_management_update_aml_officer.c
@@ -144,25 +144,9 @@ TALER_EXCHANGE_management_update_aml_officer (
   wh->cb = cb;
   wh->cb_cls = cb_cls;
   wh->ctx = ctx;
-  {
-    char *path;
-    char opus[sizeof (*officer_pub) * 2];
-    char *end;
-
-    end = GNUNET_STRINGS_data_to_string (
-      officer_pub,
-      sizeof (*officer_pub),
-      opus,
-      sizeof (opus));
-    *end = '\0';
-    GNUNET_asprintf (&path,
-                     "management/aml-officers/%s",
-                     opus);
-    wh->url = TALER_url_join (url,
-                              path,
-                              NULL);
-    GNUNET_free (path);
-  }
+  wh->url = TALER_url_join (url,
+                            "management/aml-officers",
+                            NULL);
   if (NULL == wh->url)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -173,6 +157,8 @@ TALER_EXCHANGE_management_update_aml_officer (
   body = GNUNET_JSON_PACK (
     GNUNET_JSON_pack_string ("officer_name",
                              officer_name),
+    GNUNET_JSON_pack_data_auto ("officer_pub",
+                                officer_pub),
     GNUNET_JSON_pack_data_auto ("master_sig",
                                 master_sig),
     GNUNET_JSON_pack_bool ("is_active",

-- 
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]