gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-merchant] branch master updated (cde5619 -> a130158)


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch master updated (cde5619 -> a130158)
Date: Wed, 10 Jan 2018 17:23:54 +0100

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

dold pushed a change to branch master
in repository merchant.

    from cde5619  add session_sig to pay response
     new e06b52d  fill in missing proposal fields
     new a130158  add nonce only when proposal is requested

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/backend/taler-merchant-httpd.c          |  11 +++
 src/backend/taler-merchant-httpd.h          |   6 +-
 src/backend/taler-merchant-httpd_proposal.c | 139 +++++++++++++++++++++++++---
 src/backenddb/plugin_merchantdb_postgres.c  | 107 +++++++++++++++++++++
 src/include/taler_merchantdb_plugin.h       |  33 +++++++
 5 files changed, 281 insertions(+), 15 deletions(-)

diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index f5705c8..2bf927d 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -557,6 +557,17 @@ instances_iterator_cb (void *cls,
   mi = GNUNET_new (struct MerchantInstance);
 
   if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (iic->config, section, "NAME", 
&mi->name))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "NAME");
+    GNUNET_free (mi);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_filename (iic->config,
                                                section,
                                                "KEYFILE",
diff --git a/src/backend/taler-merchant-httpd.h 
b/src/backend/taler-merchant-httpd.h
index 91dc7a2..1e917e7 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -87,6 +87,11 @@ struct MerchantInstance
   char *id;
 
   /**
+   * Legal name of the merchant.
+   */
+  char *name;
+
+  /**
    * File holding the merchant's private key
    */
   char *keyfile;
@@ -130,7 +135,6 @@ struct MerchantInstance
    * Only valid if @e tip_exchange is non-null.
    */
   struct TALER_ReservePrivateKeyP tip_reserve;
-
 };
 
 
diff --git a/src/backend/taler-merchant-httpd_proposal.c 
b/src/backend/taler-merchant-httpd_proposal.c
index f3fee47..c79e2a8 100644
--- a/src/backend/taler-merchant-httpd_proposal.c
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -248,6 +248,41 @@ proposal_put (struct MHD_Connection *connection,
                          json_integer ((json_int_t) 
default_wire_fee_amortization));
   }
 
+  if (NULL == json_object_get (order, "pay_url"))
+  {
+    char *url;
+    url = TMH_make_absolute_backend_url (connection, "pay", NULL);
+    json_object_set_new (order, "pay_url", json_string (url));
+  }
+
+  if (NULL == json_object_get (order, "products"))
+  {
+    // FIXME:  When there is no explicit product,
+    // should we create a singleton product list?
+    json_object_set_new (order, "products", json_object ());
+  }
+
+  const char *instance = json_string_value (json_object_get (order, 
"instance"));
+  if (NULL != instance)
+  {
+    // The frontend either fully specifieds the "merchant" field, or just gives
+    // the backend the "instance" name and lets it fill out.
+    struct MerchantInstance *mi = TMH_lookup_instance (instance);
+    if (NULL == mi)
+    {
+      return TMH_RESPONSE_reply_internal_error (connection,
+                                                
TALER_EC_PROPOSAL_ORDER_PARSE_ERROR,
+                                                "merchant instance not found");
+    }
+    json_t *merchant = json_object ();
+    json_object_set_new (merchant, "instance", json_string (instance));
+    json_object_set_new (merchant, "name", json_string (mi->name));
+    json_object_set_new (merchant, "jurisdiction", json_string ("none"));
+    json_object_set_new (merchant, "address", json_string ("none"));
+    json_object_set_new (order, "merchant", merchant);
+    json_object_del (order, "instance");
+  }
+
   /* extract fields we need to sign separately */
   res = TMH_PARSE_json_data (connection,
                              order,
@@ -322,11 +357,11 @@ proposal_put (struct MHD_Connection *connection,
 
   for (unsigned int i=0;i<MAX_RETRIES;i++)
   {
-    qs = db->insert_contract_terms (db->cls,
-                                   order_id,
-                                   &mi->pubkey,
-                                   timestamp,
-                                   order);
+    qs = db->insert_order (db->cls,
+                           order_id,
+                           &mi->pubkey,
+                           timestamp,
+                           order);
     if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
       break;
   }
@@ -342,12 +377,9 @@ proposal_put (struct MHD_Connection *connection,
                                               "db error: could not store this 
proposal's data into db");
   }
 
-  res = TMH_RESPONSE_reply_json_pack (connection,
-                                      MHD_HTTP_OK,
-                                      "{s:O, s:o s:o}",
-                                      "data", order,
-                                      "sig", GNUNET_JSON_from_data_auto 
(&merchant_sig),
-                                      "hash", GNUNET_JSON_from_data_auto 
(&pdps.hash));
+  res = TMH_RESPONSE_reply_json (connection,
+                                 json_object (),
+                                 MHD_HTTP_OK);
   GNUNET_JSON_parse_free (spec);
   return res;
 }
@@ -423,6 +455,8 @@ MH_handler_proposal_put (struct TMH_RequestHandler *rh,
  * proposal's data related to the transaction id given as the URL's
  * parameter.
  *
+ * Binds the proposal to a nonce.
+ *
  * @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)
@@ -439,6 +473,7 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
 {
   const char *order_id;
   const char *instance;
+  const char *nonce;
   int res;
   enum GNUNET_DB_QueryStatus qs;
   json_t *contract_terms;
@@ -465,6 +500,14 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
                                           TALER_EC_PARAMETER_MISSING,
                                            "order_id");
 
+  nonce = MHD_lookup_connection_value (connection,
+                                       MHD_GET_ARGUMENT_KIND,
+                                       "nonce");
+  if (NULL == nonce)
+    return TMH_RESPONSE_reply_arg_missing (connection,
+                                          TALER_EC_PARAMETER_MISSING,
+                                           "nonce");
+
   qs = db->find_contract_terms (db->cls,
                                &contract_terms,
                                order_id,
@@ -481,9 +524,77 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
                                               "An error occurred while 
retrieving proposal data from db");
   }
   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-    return TMH_RESPONSE_reply_not_found (connection,
-                                         TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
-                                         "unknown transaction id");
+  {
+    qs = db->find_orders (db->cls,
+                          &contract_terms,
+                          order_id,
+                          &mi->pubkey);
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+    {
+      return TMH_RESPONSE_reply_not_found (connection,
+                                           TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
+                                           "unknown order id");
+    }
+    GNUNET_assert (NULL != contract_terms);
+    // FIXME:  now we can delete (merchant_pub, order_id) from the 
merchant_orders table
+    json_object_set_new (contract_terms, "nonce", json_string (nonce));
+
+    struct GNUNET_TIME_Absolute timestamp;
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_absolute_time ("timestamp", &timestamp),
+      GNUNET_JSON_spec_end ()
+    };
+    /* extract fields we need to sign separately */
+    res = TMH_PARSE_json_data (connection, contract_terms, spec);
+    if (GNUNET_NO == res)
+    {
+      return MHD_YES;
+    }
+    if (GNUNET_SYSERR == res)
+    {
+      return TMH_RESPONSE_reply_internal_error (connection,
+                                                
TALER_EC_PROPOSAL_ORDER_PARSE_ERROR,
+                                                "Impossible to parse the 
order");
+    }
+
+    for (unsigned int i=0;i<MAX_RETRIES;i++)
+    {
+      qs = db->insert_contract_terms (db->cls,
+                                      order_id,
+                                      &mi->pubkey,
+                                      timestamp,
+                                      contract_terms);
+      if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+        break;
+    }
+    if (0 > qs)
+    {
+      /* Special report if retries insufficient */
+      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+      /* Always report on hard error as well to enable diagnostics */
+      GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+      return TMH_RESPONSE_reply_internal_error (connection,
+                                                
TALER_EC_PROPOSAL_STORE_DB_ERROR,
+                                                "db error: could not store 
this proposal's data into db");
+    }
+  }
+
+  const char *stored_nonce = json_string_value 
(json_object_get(contract_terms, "nonce"));
+
+  if (NULL == stored_nonce)
+  {
+    GNUNET_break (0);
+    return TMH_RESPONSE_reply_internal_error (connection,
+                                              
TALER_EC_PROPOSAL_ORDER_PARSE_ERROR,
+                                              "existing proposal has non 
nonce");
+  }
+
+  if (0 != strcmp (stored_nonce, nonce))
+  {
+    return TMH_RESPONSE_reply_bad_request (connection,
+                                           TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
+                                           "mismatched nonce");
+  }
 
   res = TMH_RESPONSE_reply_json (connection,
                                  contract_terms,
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 54d532f..5b14d31 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -95,6 +95,16 @@ postgres_initialize (void *cls)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_ExecuteStatement es[] = {
+    /* Orders created by the frontend, not signed or given a nonce yet.
+       The contract terms will change (nonce will be added) when moved to the
+       contract terms table */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_orders ("
+                            "order_id VARCHAR NOT NULL"
+                            ",merchant_pub BYTEA NOT NULL CHECK 
(LENGTH(merchant_pub)=32)"
+                            ",contract_terms BYTEA NOT NULL"
+                            ",timestamp INT8 NOT NULL"
+                            ",PRIMARY KEY (order_id, merchant_pub)"
+                            ");"),
     /* Offers we made to customers */
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS 
merchant_contract_terms ("
                             "order_id VARCHAR NOT NULL"
@@ -313,6 +323,15 @@ postgres_initialize (void *cls)
                             " VALUES "
                             "($1, $2, $3, $4, $5)",
                             5),
+    GNUNET_PQ_make_prepare ("insert_order",
+                            "INSERT INTO merchant_orders"
+                            "(order_id"
+                            ",merchant_pub"
+                            ",timestamp"
+                            ",contract_terms"
+                            " VALUES "
+                            "($1, $2, $3, $4)",
+                            4),
     GNUNET_PQ_make_prepare ("mark_proposal_paid",
                             "UPDATE merchant_contract_terms SET"
                             " paid=TRUE WHERE h_contract_terms=$1"
@@ -388,6 +407,14 @@ postgres_initialize (void *cls)
                             " order_id=$1"
                             " AND merchant_pub=$2",
                             2),
+    GNUNET_PQ_make_prepare ("find_orders",
+                            "SELECT"
+                            " contract_terms"
+                            " FROM merchant_orders"
+                            " WHERE"
+                            " order_id=$1"
+                            " AND merchant_pub=$2",
+                            2),
     GNUNET_PQ_make_prepare ("find_contract_terms_by_date",
                             "SELECT"
                             " contract_terms"
@@ -834,6 +861,47 @@ postgres_find_contract_terms (void *cls,
 
 
 /**
+ * Retrieve order given its order id and the instance's merchant public key.
+ *
+ * @param cls closure
+ * @param[out] contract_terms where to store the retrieved contract terms
+ * @param order id order id used to perform the lookup
+ * @param merchant_pub merchant public key that identifies the instance
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_find_orders (void *cls,
+                      json_t **contract_terms,
+                      const char *order_id,
+                      const struct TALER_MerchantPublicKeyP *merchant_pub)
+{
+  struct PostgresClosure *pg = cls;
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (order_id),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_result_spec_json ("contract_terms",
+                               contract_terms),
+    GNUNET_PQ_result_spec_end
+  };
+
+  *contract_terms = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finding contract term, order_id: '%s', merchant_pub: '%s'.\n",
+              order_id,
+              TALER_B2S (merchant_pub));
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                  "find_orders",
+                                                  params,
+                                                  rs);
+}
+
+
+/**
  * Insert proposal data and its hashcode into db
  *
  * @param cls closure
@@ -881,6 +949,43 @@ postgres_insert_contract_terms (void *cls,
 
 
 /**
+ * Insert order into the DB.
+ *
+ * @param cls closure
+ * @param order_id identificator of the proposal being stored
+ * @param merchant_pub merchant's public key
+ * @param timestamp timestamp of this proposal data
+ * @param contract_terms proposal data to store
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_insert_order (void *cls,
+                       const char *order_id,
+                       const struct TALER_MerchantPublicKeyP *merchant_pub,
+                       struct GNUNET_TIME_Absolute timestamp,
+                       const json_t *contract_terms)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (order_id),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_absolute_time (&timestamp),
+    TALER_PQ_query_param_json (contract_terms),
+    GNUNET_PQ_query_param_end
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "inserting order: order_id: %s, merchant_pub: %s.\n",
+              order_id,
+              TALER_B2S (merchant_pub));
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                            "insert_order",
+                                            params);
+}
+
+
+/**
  * Mark contract terms as payed.  Needed by /history as only payed
  * contracts must be shown.
  *
@@ -3250,6 +3355,8 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->find_deposits_by_wtid = &postgres_find_deposits_by_wtid;
   plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid;
   plugin->insert_contract_terms = &postgres_insert_contract_terms;
+  plugin->insert_order = &postgres_insert_order;
+  plugin->find_orders = &postgres_find_orders;
   plugin->find_contract_terms = &postgres_find_contract_terms;
   plugin->find_contract_terms_history = &postgres_find_contract_terms_history;
   plugin->find_contract_terms_by_date = &postgres_find_contract_terms_by_date;
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 228fa90..85cadd8 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -184,6 +184,23 @@ struct TALER_MERCHANTDB_Plugin
   int
   (*initialize) (void *cls);
 
+  /**
+   * Insert order into db.
+   *
+   * @param cls closure
+   * @param order_id alphanumeric string that uniquely identifies the proposal
+   * @param merchant_pub merchant's public key
+   * @param timestamp timestamp of this proposal data
+   * @param contract_terms proposal data to store
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*insert_order) (void *cls,
+                   const char *order_id,
+                   const struct TALER_MerchantPublicKeyP *merchant_pub,
+                   struct GNUNET_TIME_Absolute timestamp,
+                   const json_t *contract_terms);
+
 
   /**
    * Insert proposal data into db; the routine will internally hash and
@@ -238,6 +255,22 @@ struct TALER_MERCHANTDB_Plugin
                          const char *order_id,
                          const struct TALER_MerchantPublicKeyP *merchant_pub);
 
+  /**
+   * Retrieve order given its order id and the instance's merchant public key.
+   *
+   * @param cls closure
+   * @param[out] contract_terms where to store the retrieved contract terms
+   * @param order id order id used to perform the lookup
+   * @param merchant_pub merchant public key that identifies the instance
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*find_orders) (void *cls,
+                  json_t **contract_terms,
+                  const char *order_id,
+                  const struct TALER_MerchantPublicKeyP *merchant_pub);
+
+
 
   /**
    * Retrieve proposal data given its hashcode

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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