gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] 162/277: implement GET /reserves/RPUB


From: gnunet
Subject: [taler-merchant] 162/277: implement GET /reserves/RPUB
Date: Sun, 05 Jul 2020 20:51:15 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

commit 915480618b84f281aaa9bac3f711cf6e5fd555c1
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun May 31 20:34:39 2020 +0200

    implement GET /reserves/RPUB
---
 src/backend/Makefile.am                            |   2 +
 src/backend/taler-merchant-httpd.c                 |   8 +
 .../taler-merchant-httpd_private-get-reserves-ID.c | 305 +++++++++------------
 .../taler-merchant-httpd_private-get-reserves-ID.h |  22 +-
 .../taler-merchant-httpd_private-get-tips-ID.c     |   5 +-
 5 files changed, 154 insertions(+), 188 deletions(-)

diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 8960b15..e70a188 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -47,6 +47,8 @@ taler_merchant_httpd_SOURCES = \
     taler-merchant-httpd_private-get-orders.h \
   taler-merchant-httpd_private-get-reserves.c \
     taler-merchant-httpd_private-get-reserves.h \
+  taler-merchant-httpd_private-get-reserves-ID.c \
+    taler-merchant-httpd_private-get-reserves-ID.h \
   taler-merchant-httpd_private-get-transfers.c \
     taler-merchant-httpd_private-get-transfers.h \
   taler-merchant-httpd_private-patch-instances-ID.c \
diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index 3a43f8e..9a71440 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -41,6 +41,7 @@
 #include "taler-merchant-httpd_private-get-orders.h"
 // #include "taler-merchant-httpd_private-get-orders-ID.h"
 #include "taler-merchant-httpd_private-get-reserves.h"
+#include "taler-merchant-httpd_private-get-reserves-ID.h"
 #include "taler-merchant-httpd_private-get-tips-ID.h"
 #include "taler-merchant-httpd_private-get-transfers.h"
 #include "taler-merchant-httpd_private-patch-instances-ID.h"
@@ -872,6 +873,13 @@ url_handler (void *cls,
       .method = MHD_HTTP_METHOD_GET,
       .handler = &TMH_private_get_reserves
     },
+    /* GET /reserves: */
+    {
+      .url_prefix = "/reserves",
+      .have_id_segment = true,
+      .method = MHD_HTTP_METHOD_GET,
+      .handler = &TMH_private_get_reserves_ID
+    },
     /* POST /transfers: */
     {
       .url_prefix = "/transfers",
diff --git a/src/backend/taler-merchant-httpd_private-get-reserves-ID.c 
b/src/backend/taler-merchant-httpd_private-get-reserves-ID.c
index f7aa0ab..d77a7bf 100644
--- a/src/backend/taler-merchant-httpd_private-get-reserves-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-reserves-ID.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2018 Taler Systems SA
+  (C) 2018, 2020 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
@@ -14,10 +14,9 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file backend/taler-merchant-httpd_tip-query.c
- * @brief implement API for authorizing tips to be paid to visitors
+ * @file backend/taler-merchant-httpd_private-get-reserves-ID.c
+ * @brief implement GET /reserves/$RESERVE_PUB endpoint
  * @author Christian Grothoff
- * @author Florian Dold
  */
 #include "platform.h"
 #include <jansson.h>
@@ -26,223 +25,185 @@
 #include "taler-merchant-httpd.h"
 #include "taler-merchant-httpd_mhd.h"
 #include "taler-merchant-httpd_exchanges.h"
-#include "taler-merchant-httpd_tip-query.h"
-#include "taler-merchant-httpd_tip-reserve-helper.h"
+#include "taler-merchant-httpd_private-get-reserves-ID.h"
 
 
 /**
- * Maximum number of retries for database operations.
+ * Closure for handle_reserve_details().
  */
-#define MAX_RETRIES 5
-
-
-/**
- * Internal per-request state for processing tip queries.
- */
-struct TipQueryContext
+struct GetReserveContext
 {
   /**
-   * This field MUST be first for handle_mhd_completion_callback() to work
-   * when it treats this struct as a `struct TM_HandlerContext`.
-   */
-  struct TM_HandlerContext hc;
-
-  /**
-   * Merchant instance to use.
+   * Connection we are handling.
    */
-  const char *instance;
+  struct MHD_Connection *connection;
 
   /**
-   * Context for checking the tipping reserve's status.
+   * Value to return from the callback.
    */
-  struct TMH_CheckTipReserve ctr;
+  MHD_RESULT res;
 
   /**
-   * #GNUNET_YES if the tip query has already been processed
-   * and we can queue the response.
+   * Should we return details about tips?
    */
-  int processed;
-
+  bool tips;
 };
 
 
 /**
- * Custom cleanup routine for a `struct TipQueryContext`.
+ * Callback with reserve details.
  *
- * @param hc the `struct TMH_JsonParseContext` to clean up.
+ * @param cls closure with a `struct GetReserveContext`
+ * @param creation_time time when the reserve was setup
+ * @param expiration_time time when the reserve will be closed by the exchange
+ * @param merchant_initial_amount initial amount that the merchant claims to 
have filled the
+ *           reserve with
+ * @param exchange_initial_amount initial amount that the exchange claims to 
have received
+ * @param picked_up_amount total of tips that were picked up from this reserve
+ * @param committed_amount total of tips that the merchant committed to, but 
that were not
+ *           picked up yet
+ * @param tips_length length of the @a tips array
+ * @param tips information about the tips created by this reserve
  */
 static void
-cleanup_tqc (struct TM_HandlerContext *hc)
+handle_reserve_details (void *cls,
+                        struct GNUNET_TIME_Absolute creation_time,
+                        struct GNUNET_TIME_Absolute expiration_time,
+                        const struct TALER_Amount *merchant_initial_amount,
+                        const struct TALER_Amount *exchange_initial_amount,
+                        const struct TALER_Amount *picked_up_amount,
+                        const struct TALER_Amount *committed_amount,
+                        unsigned int tips_length,
+                        const struct TALER_MERCHANTDB_TipDetails *tips)
 {
-  struct TipQueryContext *tqc = (struct TipQueryContext *) hc;
-
-  TMH_check_tip_reserve_cleanup (&tqc->ctr);
-  GNUNET_free (tqc);
-}
-
+  struct GetReserveContext *ctx = cls;
+  json_t *tips_json;
 
-/**
- * We've been resumed after processing the reserve data from the
- * exchange without error. Generate the final response.
- *
- * @param tqc context for which to generate the response.
- */
-static int
-generate_final_response (struct TipQueryContext *tqc)
-{
-  struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
-  struct TALER_Amount amount_available;
-
-  GNUNET_CRYPTO_eddsa_key_get_public (&tqc->ctr.reserve_priv.eddsa_priv,
-                                      &reserve_pub);
-  if (0 >
-      TALER_amount_subtract (&amount_available,
-                             &tqc->ctr.amount_deposited,
-                             &tqc->ctr.amount_withdrawn))
+  if (tips)
   {
-    char *a1;
-    char *a2;
+    tips_json = json_array ();
+    GNUNET_assert (NULL != tips_json);
 
-    GNUNET_break_op (0);
-    a1 = TALER_amount_to_string (&tqc->ctr.amount_deposited);
-    a2 = TALER_amount_to_string (&tqc->ctr.amount_withdrawn);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "amount overflow, deposited %s but withdrawn %s\n",
-                a1,
-                a2);
-    GNUNET_free (a2);
-    GNUNET_free (a1);
-    return TALER_MHD_reply_with_error (
-      tqc->ctr.connection,
-      MHD_HTTP_INTERNAL_SERVER_ERROR,
-      TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_INCONSISTENT,
-      "Exchange returned invalid reserve history (amount overflow)");
+    for (unsigned int i = 0; i<tips_length; i++)
+    {
+      GNUNET_assert (0 ==
+                     json_array_append_new (
+                       tips_json,
+                       json_pack ("{s:o,s:o,s:I}",
+                                  "tip_id",
+                                  GNUNET_JSON_from_data_auto (
+                                    &tips[i].tip_id),
+                                  "total_amount",
+                                  TALER_JSON_from_amount (
+                                    &tips[i].total_amount),
+                                  "reason",
+                                  tips[i].reason)));
+    }
   }
-  return TALER_MHD_reply_json_pack (
-    tqc->ctr.connection,
+  else
+  {
+    tips_json = NULL;
+  }
+  ctx->res = TALER_MHD_reply_json_pack (
+    ctx->connection,
     MHD_HTTP_OK,
-    "{s:o, s:o, s:o, s:o, s:o}",
-    "reserve_pub",
-    GNUNET_JSON_from_data_auto (&reserve_pub),
-    "reserve_expiration",
-    GNUNET_JSON_from_time_abs (tqc->ctr.reserve_expiration),
-    "amount_authorized",
-    TALER_JSON_from_amount (&tqc->ctr.amount_authorized),
-    "amount_picked_up",
-    TALER_JSON_from_amount (&tqc->ctr.amount_withdrawn),
-    "amount_available",
-    TALER_JSON_from_amount (&amount_available));
+    "{s:o, s:o, s:o, s:o, s:o, s:o, s:o?}",
+    "creation_time", GNUNET_JSON_from_time_abs (creation_time),
+    "expiration_time", GNUNET_JSON_from_time_abs (expiration_time),
+    "merchant_initial_amount", TALER_JSON_from_amount 
(merchant_initial_amount),
+    "exchange_initial_amount", TALER_JSON_from_amount 
(exchange_initial_amount),
+    "pickup_amount", TALER_JSON_from_amount (picked_up_amount),
+    "committed_amount", TALER_JSON_from_amount (committed_amount),
+    "tips", tips_json);
 }
 
 
 /**
- * Handle a "/tip-query" request.
+ * Manages a GET /reserves/$RESERVE_PUB call.
  *
  * @param rh context of the handler
  * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @param mi merchant backend instance, never NULL
+ * @param[in,out] hc context with further information about the request
  * @return MHD result code
  */
 MHD_RESULT
-MH_handler_tip_query (struct TMH_RequestHandler *rh,
-                      struct MHD_Connection *connection,
-                      void **connection_cls,
-                      const char *upload_data,
-                      size_t *upload_data_size,
-                      struct MerchantInstance *mi)
+TMH_private_get_reserves_ID (const struct TMH_RequestHandler *rh,
+                             struct MHD_Connection *connection,
+                             struct TMH_HandlerContext *hc)
 {
-  struct TipQueryContext *tqc;
-
-  if (NULL == *connection_cls)
+  struct TALER_ReservePublicKeyP reserve_pub;
+  bool tips;
+
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (hc->infix,
+                                     strlen (hc->infix),
+                                     &reserve_pub,
+                                     sizeof (reserve_pub)))
   {
-    tqc = GNUNET_new (struct TipQueryContext);
-    tqc->hc.cc = &cleanup_tqc;
-    tqc->ctr.connection = connection;
-    *connection_cls = tqc;
-  }
-  else
-  {
-    tqc = *connection_cls;
-  }
-
-  if (0 != tqc->ctr.response_code)
-  {
-    MHD_RESULT res;
-
-    /* We are *done* processing the request, just queue the response (!) */
-    if (UINT_MAX == tqc->ctr.response_code)
-    {
-      GNUNET_break (0);
-      return MHD_NO; /* hard error */
-    }
-    res = MHD_queue_response (connection,
-                              tqc->ctr.response_code,
-                              tqc->ctr.response);
-    MHD_destroy_response (tqc->ctr.response);
-    tqc->ctr.response = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Queueing response (%u) for /tip-query (%s).\n",
-                (unsigned int) tqc->ctr.response_code,
-                res ? "OK" : "FAILED");
-    return res;
-  }
-
-  if (GNUNET_YES == tqc->processed)
-  {
-    /* We've been here before, so TMH_check_tip_reserve() must have
-       finished and left the result for us. Finish processing. */
-    return generate_final_response (tqc);
+    /* tip_id has wrong encoding */
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_PARAMETER_MALFORMED,
+                                       "reserve_pub malformed");
   }
-
-  if (NULL == mi->tip_exchange)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Instance `%s' not configured for tipping\n",
-                mi->id);
-    return TALER_MHD_reply_with_error (
-      connection,
-      MHD_HTTP_PRECONDITION_FAILED,
-      TALER_EC_TIP_QUERY_INSTANCE_DOES_NOT_TIP,
-      "exchange for tipping not configured for the instance");
+    const char *tstr;
+
+    tstr = MHD_lookup_connection_value (connection,
+                                        MHD_GET_ARGUMENT_KIND,
+                                        "tips");
+    tips = (NULL != tstr)
+           ? 0 == strcasecmp (tstr, "yes")
+           : false;
   }
-  tqc->ctr.reserve_priv = mi->tip_reserve;
-
   {
+    struct GetReserveContext ctx = {
+      .connection = connection,
+      .tips = tips
+    };
     enum GNUNET_DB_QueryStatus qs;
 
-    for (unsigned int i = 0; i<MAX_RETRIES; i++)
+    TMH_db->preflight (TMH_db->cls);
+    qs = TMH_db->lookup_reserve (TMH_db->cls,
+                                 hc->instance->settings.id,
+                                 &reserve_pub,
+                                 tips,
+                                 &handle_reserve_details,
+                                 &ctx);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
     {
-      db->preflight (db->cls);
-      qs = db->get_authorized_tip_amount (db->cls,
-                                          &tqc->ctr.reserve_priv,
-                                          &tqc->ctr.amount_authorized);
-      if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+      unsigned int response_code;
+      enum TALER_ErrorCode ec;
+
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        ec = TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN;
+        response_code = MHD_HTTP_NOT_FOUND;
         break;
-    }
-    if (0 > qs)
-    {
-      GNUNET_break (0);
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        ec = TALER_EC_TIP_PICKUP_DB_ERROR_SOFT;
+        response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+        break;
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        ec = TALER_EC_TIP_PICKUP_DB_ERROR_HARD;
+        response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+        break;
+      default:
+        GNUNET_break (0);
+        ec = TALER_EC_INTERNAL_LOGIC_ERROR;
+        response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+        break;
+      }
       return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                         TALER_EC_TIP_QUERY_DB_ERROR,
-                                         "Merchant database error");
-    }
-    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-    {
-      /* we'll set amount_authorized to zero later once
-         we know the currency */
-      tqc->ctr.none_authorized = GNUNET_YES;
+                                         response_code,
+                                         ec,
+                                         "Could not determine exchange URL for 
the given tip id");
     }
+    return ctx.res;
   }
-
-  tqc->processed = GNUNET_YES;
-  TMH_check_tip_reserve (&tqc->ctr,
-                         mi->tip_exchange);
-  return MHD_YES;
 }
 
 
-/* end of taler-merchant-httpd_tip-query.c */
+/* end of taler-merchant-httpd_private-get-reserves-ID.c */
diff --git a/src/backend/taler-merchant-httpd_private-get-reserves-ID.h 
b/src/backend/taler-merchant-httpd_private-get-reserves-ID.h
index 3123486..4b9fa06 100644
--- a/src/backend/taler-merchant-httpd_private-get-reserves-ID.h
+++ b/src/backend/taler-merchant-httpd_private-get-reserves-ID.h
@@ -14,32 +14,26 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file backend/taler-merchant-httpd_tip-query.h
+ * @file backend/taler-merchant-httpd_private-get-reserves-ID.h
  * @brief headers for /tip-query handler
  * @author Florian Dold
  */
-#ifndef TALER_MERCHANT_HTTPD_TIP_QUERY_H
-#define TALER_MERCHANT_HTTPD_TIP_QUERY_H
+#ifndef TALER_MERCHANT_HTTPD_GET_RESERVES_ID_H
+#define TALER_MERCHANT_HTTPD_GET_RESERVES_ID_H
 #include <microhttpd.h>
 #include "taler-merchant-httpd.h"
 
 /**
- * Manages a /tip-query call.
+ * Manages a GET /reserves/$RESERVE_PUB call.
  *
  * @param rh context of the handler
  * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @param mi merchant backend instance, never NULL
+ * @param[in,out] hc context with further information about the request
  * @return MHD result code
  */
 MHD_RESULT
-MH_handler_tip_query (struct TMH_RequestHandler *rh,
-                      struct MHD_Connection *connection,
-                      void **connection_cls,
-                      const char *upload_data,
-                      size_t *upload_data_size,
-                      struct MerchantInstance *mi);
+TMH_private_get_reserves_ID (const struct TMH_RequestHandler *rh,
+                             struct MHD_Connection *connection,
+                             struct TMH_HandlerContext *hc);
 
 #endif
diff --git a/src/backend/taler-merchant-httpd_private-get-tips-ID.c 
b/src/backend/taler-merchant-httpd_private-get-tips-ID.c
index fc9ef06..59de1b6 100644
--- a/src/backend/taler-merchant-httpd_private-get-tips-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-tips-ID.c
@@ -72,8 +72,9 @@ TMH_private_get_tips_ID (const struct TMH_RequestHandler *rh,
     pstr = MHD_lookup_connection_value (connection,
                                         MHD_GET_ARGUMENT_KIND,
                                         "pickups");
-    fpu = (NULL != pstr) ? 0 == strcasecmp (pstr, "yes") :
-          false;
+    fpu = (NULL != pstr)
+          ? 0 == strcasecmp (pstr, "yes")
+          : false;
   }
   db->preflight (db->cls);
   qs = db->lookup_tip_details (db->cls,

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