gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: Worked on policy upload. Still


From: gnunet
Subject: [taler-anastasis] branch master updated: Worked on policy upload. Still not working...
Date: Thu, 23 Jan 2020 11:48:41 +0100

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

dennis-neufeld pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new 98eed9d  Worked on policy upload. Still not working...
98eed9d is described below

commit 98eed9df77d7d5eee4481725bc57fbc4c641b316
Author: Dennis Neufeld <address@hidden>
AuthorDate: Thu Jan 23 10:48:37 2020 +0000

    Worked on policy upload. Still not working...
---
 src/backend/anastasis-httpd_policy_upload.c |  89 ++++---
 src/include/anastasis_database_plugin.h     |  63 ++---
 src/include/anastasis_service.h             |   3 +-
 src/lib/anastasis_api_policy_store.c        |  16 +-
 src/lib/testing_api_cmd_policy_store.c      |  18 +-
 src/stasis/plugin_anastasis_postgres.c      | 391 ++++++++++++++++++++++++----
 src/stasis/test_anastasis_db.c              |  18 +-
 src/stasis/test_anastasis_db_postgres.conf  |   3 +
 8 files changed, 446 insertions(+), 155 deletions(-)

diff --git a/src/backend/anastasis-httpd_policy_upload.c 
b/src/backend/anastasis-httpd_policy_upload.c
index 149e21d..5fb7a0f 100644
--- a/src/backend/anastasis-httpd_policy_upload.c
+++ b/src/backend/anastasis-httpd_policy_upload.c
@@ -298,7 +298,8 @@ proposal_cb (void *cls,
   qs = db->record_payment (db->cls,
                            &puc->account,
                            post_counter,
-                           &puc->payment_identifier);
+                           &puc->payment_identifier,
+                           &AH_annual_fee);
   if (0 >= qs)
   {
     GNUNET_break (0);
@@ -315,6 +316,35 @@ proposal_cb (void *cls,
   puc->response_code = MHD_HTTP_PAYMENT_REQUIRED;
 }
 
+/**
+ * Function called on all pending payments for the right
+ * account.
+ *
+ * @param cls closure, our `struct BackupContext`
+ * @param timestamp for how long have we been waiting
+ * @param order_id order id in the backend
+ * @param amount how much is the order for
+ */
+static void
+ongoing_payment_cb (void *cls,
+                    struct GNUNET_TIME_Absolute timestamp,
+                    const char *order_id,
+                    const struct TALER_Amount *amount)
+{
+  struct PolicyUploadContext *puc = cls;
+
+  (void) amount;
+  if (0 != TALER_amount_cmp (amount,
+                             &AH_annual_fee))
+    return; /* can't re-use, fees changed */
+  if ( (NULL == puc->existing_order_id) ||
+       (puc->existing_order_timestamp.abs_value_us < timestamp.abs_value_us) )
+  {
+    GNUNET_free_non_null (puc->existing_order_id);
+    puc->existing_order_id = GNUNET_strdup (order_id);
+    puc->existing_order_timestamp = timestamp;
+  }
+}
 
 /**
  * Callback to process a GET /check-payment request
@@ -438,9 +468,10 @@ begin_payment (struct PolicyUploadContext *puc,
   enum ANASTASIS_DB_QueryStatus qs;
   const char *order_id;
 
-  qs = db->lookup_expired_payment_by_account (db->cls,
-                                              &puc->account,
-                                              puc);
+  qs = db->lookup_pending_payments_by_account (db->cls,
+                                               &puc->account,
+                                               &ongoing_payment_cb,
+                                               puc);
   if (qs < 0)
   {
     struct MHD_Response *resp;
@@ -455,29 +486,6 @@ begin_payment (struct PolicyUploadContext *puc,
     return ret;
   }
 
-  if (NULL == puc->order_id)
-  {
-    // generate new payment identifier
-    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                                &puc->payment_identifier,
-                                sizeof (
-                                  struct ANASTASIS_PaymentSecretP));
-
-    order_id = GNUNET_STRINGS_data_to_string_alloc (&puc->payment_identifier,
-                                                    sizeof(
-                                                      struct
-                                                      
ANASTASIS_PaymentSecretP));
-  }
-
-  if (qs == ANASTASIS_DB_STATUS_NO_RESULTS)
-  {
-    // create new user
-    qs = db->increment_lifetime (db->cls,
-                                 &puc->account,
-                                 &puc->payment_identifier,
-                                 GNUNET_TIME_UNIT_ZERO);
-  }
-
   if (NULL != puc->existing_order_id)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -488,6 +496,16 @@ begin_payment (struct PolicyUploadContext *puc,
                    puc->existing_order_id);
     return MHD_YES;
   }
+  // generate new payment identifier
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              &puc->payment_identifier,
+                              sizeof (
+                                struct ANASTASIS_PaymentSecretP));
+
+  order_id = GNUNET_STRINGS_data_to_string_alloc (&puc->payment_identifier,
+                                                  sizeof(
+                                                    struct
+                                                    ANASTASIS_PaymentSecretP));
 
   GNUNET_CONTAINER_DLL_insert (puc_head,
                                puc_tail,
@@ -508,8 +526,6 @@ begin_payment (struct PolicyUploadContext *puc,
                                       &proposal_cb,
                                       puc);
 
-  puc->existing_order_id = order_id;
-
   AH_trigger_curl ();
   json_decref (order);
   return MHD_YES;
@@ -540,13 +556,13 @@ handle_database_error (struct PolicyUploadContext *puc,
                                        "Cannot update, unknown previous 
recovery document");
   case ANASTASIS_DB_STATUS_PAYMENT_REQUIRED:
     {
-      char *order_id;
+      const char *order_id;
 
       order_id = MHD_lookup_connection_value (puc->con,
                                               MHD_GET_ARGUMENT_KIND,
                                               "paying");
 
-      if ((NULL == order_id) || GNUNET_is_zero (order_id))
+      if (NULL == order_id)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                     "Payment required, starting payment process\n");
@@ -793,15 +809,8 @@ AH_handler_policy_post (struct MHD_Connection *connection,
       if (qs < 0)
         return handle_database_error (puc,
                                       qs);
-      if (qs == ANASTASIS_DB_STATUS_NO_RESULTS)
-      {
+      if (ANASTASIS_DB_STATUS_NO_RESULTS == qs)
         memset (&hc, 0, sizeof (hc));
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "User not known. Payment required to create new 
account\n");
-        qs = ANASTASIS_DB_STATUS_PAYMENT_REQUIRED;
-        return handle_database_error (puc,
-                                      qs);
-      }
       if (0 == GNUNET_memcmp (&hc,
                               &puc->new_policy_upload_hash))
       {
@@ -945,6 +954,7 @@ AH_handler_policy_post (struct MHD_Connection *connection,
       ret = MHD_queue_response (connection,
                                 MHD_HTTP_NOT_MODIFIED,
                                 resp);
+      GNUNET_break (MHD_YES == ret);
       MHD_destroy_response (resp);
       return ret;
     }
@@ -962,6 +972,7 @@ AH_handler_policy_post (struct MHD_Connection *connection,
     ret = MHD_queue_response (connection,
                               MHD_HTTP_NO_CONTENT,
                               resp);
+    GNUNET_break (MHD_YES == ret);
     MHD_destroy_response (resp);
     return ret;
   }
diff --git a/src/include/anastasis_database_plugin.h 
b/src/include/anastasis_database_plugin.h
index f2798d7..df0a68c 100644
--- a/src/include/anastasis_database_plugin.h
+++ b/src/include/anastasis_database_plugin.h
@@ -311,27 +311,30 @@ struct ANASTASIS_DatabasePlugin
                     ANASTASIS_AccountPubP *anastasis_pub);
 
   /**
-   * Lookup pending payments by account.
-   *
-   * @param cls closure
-   * @param account_pub account to look for pending payment under
-   */
-  enum ANASTASIS_DB_QueryStatus
-  (*lookup_expired_payment_by_account)(void *cls,
-                                       const struct
-                                       ANASTASIS_AccountPubP *account_pub,
-                                       void *it_cls);
-
-/**
- * Increment account lifetime.
+ * Lookup pending payments by account.
  *
  * @param cls closure
- * @param account_pub which account received a payment
- * @param payment_identifier proof of payment, must be unique and match 
pending payment
- * @param lifetime for how long is the account now paid (increment)
- * @return transaction status
+ * @param anastasis_pub account to look for pending payment under
+ * @param it iterator to call on all pending payments
+ * @param it_cls closure for @a it
  */
   enum ANASTASIS_DB_QueryStatus
+  (*lookup_pending_payments_by_account)(void *cls,
+                                        const struct
+                                        ANASTASIS_AccountPubP *anastasis_pub,
+                                        ANASTASIS_DB_PaymentPendingIterator it,
+                                        void *it_cls);
+
+  /**
+   * Increment account lifetime.
+   *
+   * @param cls closure
+   * @param account_pub which account received a payment
+   * @param payment_identifier proof of payment, must be unique and match 
pending payment
+   * @param lifetime for how long is the account now paid (increment)
+   * @return transaction status
+   */
+  enum ANASTASIS_DB_QueryStatus
   (*increment_lifetime)(void *cls,
                         const struct ANASTASIS_AccountPubP *anastasis_pub,
                         const struct
@@ -339,21 +342,23 @@ struct ANASTASIS_DatabasePlugin
                         struct GNUNET_TIME_Relative lifetime);
 
 
-/**
- * Store payment. Used to begin a payment, not indicative
- * that the payment actually was made. (That is done
- * when we increment the account's lifetime.)
- *
- * @param cls closure
- * @param anastasis_pub anastasis's public key
- * @param post_counter how many uploads does @a amount pay for
- * @param payment_secret payment secret which the user must provide with every 
upload
- * @return transaction status
- */
+  /**
+   * Store payment. Used to begin a payment, not indicative
+   * that the payment actually was made. (That is done
+   * when we increment the account's lifetime.)
+   *
+   * @param cls closure
+   * @param anastasis_pub anastasis's public key
+   * @param post_counter how many uploads does @a amount pay for
+   * @param payment_secret payment secret which the user must provide with 
every upload
+   * @param amount how much we asked for
+   * @return transaction status
+   */
   enum ANASTASIS_DB_QueryStatus
   (*record_payment)(void *cls,
                     const struct ANASTASIS_AccountPubP *anastasis_pub,
                     uint32_t post_counter,
-                    const struct ANASTASIS_PaymentSecretP *payment_secret);
+                    const struct ANASTASIS_PaymentSecretP *payment_secret,
+                    const struct TALER_Amount *amount);
 };
 #endif
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index a568491..f02b762 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -398,8 +398,7 @@ ANASTASIS_policy_store (struct GNUNET_CURL_Context *ctx,
                         const void *recovery_data,
                         size_t recovery_data_size,
                         int payment_requested,
-                        const struct
-                        ANASTASIS_PaymentSecretP paymentSecretP,
+                        const char *payment_order_id,
                         ANASTASIS_PolicyStoreCallback cb,
                         void *cb_cls);
 
diff --git a/src/lib/anastasis_api_policy_store.c 
b/src/lib/anastasis_api_policy_store.c
index f0acabd..de226e5 100644
--- a/src/lib/anastasis_api_policy_store.c
+++ b/src/lib/anastasis_api_policy_store.c
@@ -276,8 +276,7 @@ ANASTASIS_policy_store (struct GNUNET_CURL_Context *ctx,
                         const void *recovery_data,
                         size_t recovery_data_size,
                         int payment_requested,
-                        const struct
-                        ANASTASIS_PaymentSecretP paymentSecretP,
+                        const char *paid_order_id,
                         ANASTASIS_PolicyStoreCallback cb,
                         void *cb_cls)
 {
@@ -369,15 +368,11 @@ ANASTASIS_policy_store (struct GNUNET_CURL_Context *ctx,
       job_headers = ext;
     }
     /* Setup Payment-Identifier header */
-    if (NULL != &paymentSecretP)
+    if (NULL != paid_order_id)
     {
-      val = GNUNET_STRINGS_data_to_string_alloc (&paymentSecretP,
-                                                 sizeof (struct
-                                                         
ANASTASIS_PaymentSecretP));
       GNUNET_asprintf (&hdr,
                        "Payment-Identifier: %s",
-                       val);
-      GNUNET_free (val);
+                       paid_order_id);
 
       ext = curl_slist_append (job_headers,
                                hdr);
@@ -410,10 +405,6 @@ ANASTASIS_policy_store (struct GNUNET_CURL_Context *ctx,
                      acc_pub_str);
     GNUNET_free (acc_pub_str);
 
-    char *paid_order_id;
-    paid_order_id = GNUNET_STRINGS_data_to_string_alloc (&paymentSecretP,
-                                                         sizeof (struct
-                                                                 
ANASTASIS_PaymentSecretP));
     pso->url = (GNUNET_YES == payment_requested)
               ? TALER_url_join (backend_url,
                                 path,
@@ -431,7 +422,6 @@ ANASTASIS_policy_store (struct GNUNET_CURL_Context *ctx,
                                 : NULL,
                                 paid_order_id,
                                 NULL);
-    GNUNET_free_non_null (paid_order_id);
     GNUNET_free (path);
   }
   pso->ctx = ctx;
diff --git a/src/lib/testing_api_cmd_policy_store.c 
b/src/lib/testing_api_cmd_policy_store.c
index 6204f2c..5830ff8 100644
--- a/src/lib/testing_api_cmd_policy_store.c
+++ b/src/lib/testing_api_cmd_policy_store.c
@@ -336,18 +336,6 @@ policy_store_run (void *cls,
           TALER_TESTING_interpreter_fail (pss->is);
           return;
         }
-
-        if (GNUNET_OK !=
-            GNUNET_STRINGS_string_to_data (order_id,
-                                           strlen (order_id),
-                                           &pss->payment_id,
-                                           sizeof (struct
-                                                   ANASTASIS_PaymentSecretP)))
-        {
-          GNUNET_break (0);
-          TALER_TESTING_interpreter_fail (pss->is);
-          return;
-        }
       }
     }
   }
@@ -389,7 +377,7 @@ policy_store_run (void *cls,
                                      (0 !=
                                       (ANASTASIS_TESTING_PSO_REQUEST_PAYMENT
                                        & pss->psopt)),
-                                     pss->payment_id,
+                                     pss->payment_order_req,
                                      &policy_store_cb,
                                      pss);
   if (NULL == pss->pso)
@@ -423,7 +411,7 @@ policy_store_cleanup (void *cls,
     pss->pso = NULL;
   }
 
-  GNUNET_free_non_null ((void *) pss->payment_order_id);
+  GNUNET_free_non_null (pss->payment_order_id);
   GNUNET_free (pss);
 }
 
@@ -447,6 +435,8 @@ policy_store_traits (void *cls,
   struct TALER_TESTING_Trait traits[] = {
     ANASTASIS_TESTING_make_trait_hash (ANASTASIS_TESTING_TRAIT_HASH_CURRENT,
                                        &pss->curr_hash),
+    ANASTASIS_TESTING_make_trait_hash (ANASTASIS_TESTING_TRAIT_HASH_PREVIOUS,
+                                       &pss->prev_hash),
     ANASTASIS_TESTING_make_trait_account_pub (0,
                                               &pss->anastasis_pub),
     ANASTASIS_TESTING_make_trait_account_priv (0,
diff --git a/src/stasis/plugin_anastasis_postgres.c 
b/src/stasis/plugin_anastasis_postgres.c
index 65029d1..bc8228c 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -57,6 +57,11 @@ struct PostgresClosure
    */
   const char *transaction_name;
 
+  /**
+   * Currency we accept payments in.
+   */
+  char *currency;
+
 };
 
 
@@ -214,50 +219,167 @@ commit_transaction (void *cls)
   return qs;
 }
 
-
 /**
- * Lookup pending payments by account.
+ * Function called to perform "garbage collection" on the
+ * database, expiring records we no longer require.  Deletes
+ * all user records that are not paid up (and by cascade deletes
+ * the associated recovery documents). Also deletes expired
+ * truth and financial records older than @a fin_expire.
  *
  * @param cls closure
- * @param anastasis_pub account to look for pending payment under
- * @param it iterator to call on all pending payments
- * @param it_cls closure for @a it
+ * @param expire_backups backups older than the given time stamp should be 
garbage collected
+ * @param expire_pending_payments payments still pending from since before
+ *            this value should be garbage collected
+ * @return transaction status
  */
 static enum ANASTASIS_DB_QueryStatus
-postgres_lookup_expired_payment_by_account (void *cls,
-                                            const struct
-                                            ANASTASIS_AccountPubP 
*anastasis_pub,
-                                            void *it_cls)
+postgres_gc (void *cls,
+             struct GNUNET_TIME_Absolute expire_backups,
+             struct GNUNET_TIME_Absolute expire_pending_payments)
 {
-  struct GNUNET_TIME_Absolute paid_until;
-  struct GNUNET_TIME_Relative time_remaining;
   struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    TALER_PQ_query_param_absolute_time (&expire_backups),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_QueryParam params2[] = {
+    TALER_PQ_query_param_absolute_time (&expire_pending_payments),
+    GNUNET_PQ_query_param_end
+  };
   enum ANASTASIS_DB_QueryStatus qs;
 
-  /* Check if user has paid */
+  check_connection (pg);
+  postgres_preflight (pg);
+  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                           "gc_accounts",
+                                           params);
+  if (qs < 0)
+    return qs;
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "gc_pending_payments",
+                                             params2);
+}
+
+
+/**
+ * Closure for #payment_by_account_cb.
+ */
+struct PaymentIteratorContext
+{
+  /**
+   * Function to call on each result
+   */
+  ANASTASIS_DB_PaymentPendingIterator it;
+
+  /**
+   * Closure for @e it.
+   */
+  void *it_cls;
+
+  /**
+   * Plugin context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Query status to return.
+   */
+  enum GNUNET_DB_QueryStatus qs;
+
+};
+
+
+/**
+ * Helper function for #postgres_lookup_pending_payments_by_account().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PaymentIteratorContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+payment_by_account_cb (void *cls,
+                       PGresult *result,
+                       unsigned int num_results)
+{
+  struct PaymentIteratorContext *pic = cls;
+  for (unsigned int i = 0; i < num_results; i++)
   {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_end
-    };
+    struct GNUNET_TIME_Absolute timestamp;
+    struct ANASTASIS_PaymentSecretP payment_identifier;
+    struct TALER_Amount amount;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_result_spec_absolute_time ("paid_until",
-                                          &paid_until),
+      GNUNET_PQ_result_spec_absolute_time ("timestamp",
+                                           &timestamp),
+      GNUNET_PQ_result_spec_auto_from_type ("payment_identifier",
+                                            &payment_identifier),
+      TALER_PQ_result_spec_amount ("amount",
+                                   pic->pg->currency,
+                                   &amount),
       GNUNET_PQ_result_spec_end
     };
 
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "user_select",
-                                                   params,
-                                                   rs);
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      pic->qs = GNUNET_DB_STATUS_HARD_ERROR;
+      return;
+    }
+    const char *order_id;
+    order_id = GNUNET_STRINGS_data_to_string_alloc (&payment_identifier,
+                                                    sizeof (struct
+                                                            
ANASTASIS_PaymentSecretP));
+    pic->qs = i + 1;
+    pic->it (pic->it_cls,
+             timestamp,
+             order_id,
+             &amount);
+    GNUNET_PQ_cleanup_result (rs);
   }
+}
 
-  if (qs == ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT)
-  {
-    time_remaining = GNUNET_TIME_absolute_get_remaining (paid_until);
-    if (GNUNET_TIME_round_rel (&time_remaining) == 0)
-      return ANASTASIS_DB_STATUS_PAYMENT_REQUIRED;
-  }
+/**
+ * Lookup pending payments by account.
+ *
+ * @param cls closure
+ * @param anastasis_pub account to look for pending payment under
+ * @param it iterator to call on all pending payments
+ * @param it_cls closure for @a it
+ */
+static enum ANASTASIS_DB_QueryStatus
+postgres_lookup_pending_payments_by_account (void *cls,
+                                             const struct
+                                             ANASTASIS_AccountPubP *
+                                             anastasis_pub,
+                                             
ANASTASIS_DB_PaymentPendingIterator
+                                             it,
+                                             void *it_cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+    GNUNET_PQ_query_param_end
+  };
+  struct PaymentIteratorContext pic = {
+    .it = it,
+    .it_cls = it_cls,
+    .pg = pg
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  check_connection (pg);
+  postgres_preflight (pg);
+  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+                                             "payments_select_by_account",
+                                             params,
+                                             &payment_by_account_cb,
+                                             &pic);
+  if (qs > 0)
+    return pic.qs;
   GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
   return qs;
 }
@@ -344,7 +466,7 @@ postgres_store_recovery_document (void *cls,
       GNUNET_PQ_query_param_end
     };
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("paid_until",
+      GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
                                             &ed),
       GNUNET_PQ_result_spec_end
     };
@@ -556,13 +678,31 @@ postgres_increment_lifetime (void *cls,
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
 
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (payment_identifier),
+      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+      GNUNET_PQ_query_param_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "payment_done",
+                                             params);
+    if (0 >= qs)
+    {
+      /* payment made before, or unknown, or error => no further action! */
+      rollback (pg);
+      return qs;
+    }
+  }
+
   {
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
       GNUNET_PQ_query_param_end
     };
     struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_result_spec_absolute_time ("paid_until",
+      TALER_PQ_result_spec_absolute_time ("expiration_date",
                                           &expiration),
       GNUNET_PQ_result_spec_end
     };
@@ -598,7 +738,7 @@ postgres_increment_lifetime (void *cls,
     break;
   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     {
-      // user exists, update paid_until
+      // user exists, update expiration_date
       struct GNUNET_PQ_QueryParam params[] = {
         GNUNET_PQ_query_param_absolute_time (&expiration),
         GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
@@ -653,7 +793,6 @@ postgres_increment_lifetime (void *cls,
   }
 }
 
-
 /**
  * Store payment. Used to begin a payment, not indicative
  * that the payment actually was made. (That is done
@@ -663,20 +802,24 @@ postgres_increment_lifetime (void *cls,
  * @param anastasis_pub anastasis's public key
  * @param post_counter how many uploads does @a amount pay for
  * @param payment_secret payment secret which the user must provide with every 
upload
+ * @param amount how much we asked for
  * @return transaction status
  */
 static enum ANASTASIS_DB_QueryStatus
 postgres_record_payment (void *cls,
                          const struct ANASTASIS_AccountPubP *anastasis_pub,
                          uint32_t post_counter,
-                         const struct ANASTASIS_PaymentSecretP *payment_secret)
+                         const struct ANASTASIS_PaymentSecretP *payment_secret,
+                         const struct TALER_Amount *amount)
 {
   struct PostgresClosure *pg = cls;
   enum ANASTASIS_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_TIME_Absolute expiration;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
     GNUNET_PQ_query_param_uint32 (&post_counter),
+    TALER_PQ_query_param_amount (amount),
     GNUNET_PQ_query_param_auto_from_type (payment_secret),
     GNUNET_PQ_query_param_absolute_time (&now),
     GNUNET_PQ_query_param_end
@@ -684,6 +827,73 @@ postgres_record_payment (void *cls,
 
   check_connection (pg);
   postgres_preflight (pg);
+
+  // because of constraint at user_id, first we have to verify
+  // if user exists, otherwise we have to create one
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      TALER_PQ_result_spec_absolute_time ("expiration_date",
+                                          &expiration),
+      GNUNET_PQ_result_spec_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "user_select",
+                                                   params,
+                                                   rs);
+  }
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    rollback (pg);
+    return ANASTASIS_DB_STATUS_HARD_ERROR;
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    rollback (pg);
+    return ANASTASIS_DB_STATUS_SOFT_ERROR;
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    {
+      // create new user
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+        GNUNET_PQ_query_param_absolute_time (&now),
+        GNUNET_PQ_query_param_end
+      };
+      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "user_insert",
+                                               params);
+    }
+    break;
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    // handle case below
+    break;
+  default:
+    GNUNET_break (0);
+    return ANASTASIS_DB_STATUS_HARD_ERROR;
+  }
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    rollback (pg);
+    return ANASTASIS_DB_STATUS_HARD_ERROR;
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    rollback (pg);
+    GNUNET_break (0);
+    return ANASTASIS_DB_STATUS_SOFT_ERROR;
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    GNUNET_break (0);
+    rollback (pg);
+    return ANASTASIS_DB_STATUS_NO_RESULTS;
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    break;
+  default:
+    GNUNET_break (0);
+    return ANASTASIS_DB_STATUS_HARD_ERROR;
+  }
+
   qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                            "payment_insert",
                                            params);
@@ -894,15 +1104,15 @@ postgres_lookup_account (void *cls,
                          ANASTASIS_AccountPubP *anastasis_pub)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute paid_until;
+  struct GNUNET_TIME_Absolute expiration_date;
   enum ANASTASIS_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_result_spec_absolute_time ("paid_until",
-                                        &paid_until),
+    TALER_PQ_result_spec_absolute_time ("expiration_date",
+                                        &expiration_date),
     GNUNET_PQ_result_spec_end
   };
 
@@ -913,7 +1123,22 @@ postgres_lookup_account (void *cls,
                                                  rs);
 
   GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
-  return qs;
+
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    return ANASTASIS_DB_STATUS_HARD_ERROR;
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    GNUNET_break (0);
+    return ANASTASIS_DB_STATUS_SOFT_ERROR;
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    return ANASTASIS_DB_STATUS_PAYMENT_REQUIRED;
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
+  default:
+    GNUNET_break (0);
+    return ANASTASIS_DB_STATUS_HARD_ERROR;
+  }
 }
 
 
@@ -1067,7 +1292,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
        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 anastasis_truth"
-                            "( truth_id UUID PRIMARY KEY NOT NULL,"
+                            "(truth_id UUID PRIMARY KEY NOT NULL,"
                             " key_share_data BYTEA NOT NULL,"
                             " method VARCHAR,"
                             " nonce BYTEA NOT NULL,"
@@ -1079,14 +1304,17 @@ libanastasis_plugin_db_postgres_init (void *cls)
                             ");"),
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS anastasis_user"
                             "( user_id BYTEA PRIMARY KEY 
CHECK(LENGTH(user_id)=32),"
-                            "  paid_until TIMESTAMP NOT NULL"
+                            "  expiration_date TIMESTAMP NOT NULL"
                             ");"),
     GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS anastasis_payment"
-                            "( payment_id BIGSERIAL PRIMARY KEY,"
-                            "  user_id BYTEA NOT NULL REFERENCES 
anastasis_user(user_id),"
-                            "  post_counter INTEGER,"
-                            "  payment_identifier BYTEA NOT NULL 
CHECK(LENGTH(payment_identifier)=32),"
-                            "  transaction_time TIMESTAMP NOT NULL DEFAULT 
NOW()"
+                            "(payment_id BIGSERIAL PRIMARY KEY,"
+                            " user_id BYTEA NOT NULL REFERENCES 
anastasis_user(user_id),"
+                            " post_counter INTEGER,"
+                            " amount_val INT8 NOT NULL," /* amount we were 
paid */
+                            " amount_frac INT4 NOT NULL,"
+                            " payment_identifier BYTEA NOT NULL 
CHECK(LENGTH(payment_identifier)=32),"
+                            " timestamp TIMESTAMP NOT NULL DEFAULT NOW(),"
+                            " paid BOOLEAN NOT NULL DEFAULT FALSE"
                             ");"),
     GNUNET_PQ_make_execute (
       "CREATE TABLE IF NOT EXISTS anastasis_recoverydocument"
@@ -1103,7 +1331,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
     GNUNET_PQ_make_prepare ("user_insert",
                             "INSERT INTO anastasis_user "
                             "(user_id"
-                            ",paid_until"
+                            ",expiration_date"
                             ") VALUES "
                             "($1, $2);",
                             2),
@@ -1112,7 +1340,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
                             0),
     GNUNET_PQ_make_prepare ("user_select",
                             "SELECT"
-                            " paid_until "
+                            " expiration_date "
                             "FROM anastasis_user"
                             " WHERE user_id=$1"
                             " FOR UPDATE;",
@@ -1120,18 +1348,64 @@ libanastasis_plugin_db_postgres_init (void *cls)
     GNUNET_PQ_make_prepare ("user_update",
                             "UPDATE anastasis_user"
                             " SET "
-                            " paid_until=$1"
+                            " expiration_date=$1"
                             " WHERE user_id=$2;",
                             2),
     GNUNET_PQ_make_prepare ("payment_insert",
                             "INSERT INTO anastasis_payment "
                             "(user_id"
                             ",post_counter"
+                            ",amount_val"
+                            ",amount_frac"
                             ",payment_identifier"
-                            ",transaction_time"
+                            ",timestamp"
                             ") VALUES "
-                            "($1, $2, $3, $4);",
+                            "($1, $2, $3, $4, $5, $6);",
                             4),
+    GNUNET_PQ_make_prepare ("payment_done",
+                            "UPDATE anastasis_payment "
+                            "SET"
+                            " paid=TRUE "
+                            "WHERE"
+                            "  payment_identifier=$1"
+                            " AND"
+                            "  user_id=$2"
+                            " AND"
+                            "  paid=FALSE;",
+                            2),
+    GNUNET_PQ_make_prepare ("payments_select",
+                            "SELECT"
+                            " user_id"
+                            ",payment_identifier"
+                            ",amount_val"
+                            ",amount_frac"
+                            " FROM anastasis_payment"
+                            " WHERE paid=FALSE;",
+                            0),
+    GNUNET_PQ_make_prepare ("payments_select_by_account",
+                            "SELECT"
+                            " timestamp"
+                            ",payment_identifier"
+                            ",amount_val"
+                            ",amount_frac"
+                            " FROM anastasis_payment"
+                            " WHERE"
+                            "  paid=FALSE"
+                            " AND"
+                            "  user_id=$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("gc_accounts",
+                            "DELETE FROM anastasis_user "
+                            "WHERE"
+                            " expiration_date < $1;",
+                            1),
+    GNUNET_PQ_make_prepare ("gc_pending_payments",
+                            "DELETE FROM anastasis_payment "
+                            "WHERE"
+                            "  paid=FALSE"
+                            " AND"
+                            "  timestamp < $1;",
+                            1),
     GNUNET_PQ_make_prepare ("truth_insert",
                             "INSERT INTO anastasis_truth "
                             "(truth_id"
@@ -1244,6 +1518,19 @@ libanastasis_plugin_db_postgres_init (void *cls)
     GNUNET_free (pg);
     return NULL;
   }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "taler",
+                                             "CURRENCY",
+                                             &pg->currency))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "taler",
+                               "CURRENCY");
+    GNUNET_PQ_disconnect (pg->conn);
+    GNUNET_free (pg);
+    return NULL;
+  }
   plugin = GNUNET_new (struct ANASTASIS_DatabasePlugin);
   plugin->cls = pg;
   plugin->drop_tables = &postgres_drop_tables;
@@ -1258,8 +1545,8 @@ libanastasis_plugin_db_postgres_init (void *cls)
   plugin->get_latest_recovery_document = 
&postgres_get_latest_recovery_document;
   plugin->get_recovery_document = &postgres_get_recovery_document;
   plugin->lookup_account = &postgres_lookup_account;
-  plugin->lookup_expired_payment_by_account =
-    &postgres_lookup_expired_payment_by_account;
+  plugin->lookup_pending_payments_by_account =
+    &postgres_lookup_pending_payments_by_account;
   plugin->increment_lifetime = &postgres_increment_lifetime;
   plugin->start = &begin_transaction;
   plugin->check_connection = &check_connection;
@@ -1271,7 +1558,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
 /**
  * Shutdown Postgres database subsystem.
  *
- * @param cls a `struct ANASTASIS_DB_Plugin`
+ * @param cls a `struct ANASTASIS_DB_STATUS_Plugin`
  * @return NULL (always)
  */
 void *
diff --git a/src/stasis/test_anastasis_db.c b/src/stasis/test_anastasis_db.c
index a394c16..1df178b 100644
--- a/src/stasis/test_anastasis_db.c
+++ b/src/stasis/test_anastasis_db.c
@@ -166,6 +166,7 @@ static void
 run (void *cls)
 {
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+  struct TALER_Amount amount;
 
   if (NULL == (plugin = ANASTASIS_DB_plugin_load (cfg)))
   {
@@ -245,6 +246,17 @@ run (void *cls)
   struct GNUNET_TIME_Relative rel_time;
   rel_time = GNUNET_TIME_UNIT_MONTHS;
 
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:1",
+                                         &amount));
+
+  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+          plugin->record_payment (plugin->cls,
+                                  &accountPubP,
+                                  post_counter,
+                                  &paymentSecretP,
+                                  &amount));
+
   FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->increment_lifetime (plugin->cls,
                                       &accountPubP,
@@ -255,12 +267,6 @@ run (void *cls)
           plugin->lookup_account (plugin->cls,
                                   &accountPubP));
 
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->record_payment (plugin->cls,
-                                  &accountPubP,
-                                  post_counter,
-                                  &paymentSecretP));
-
   FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->store_truth (plugin->cls,
                                &uuid,
diff --git a/src/stasis/test_anastasis_db_postgres.conf 
b/src/stasis/test_anastasis_db_postgres.conf
index f91dea1..b00e4e8 100644
--- a/src/stasis/test_anastasis_db_postgres.conf
+++ b/src/stasis/test_anastasis_db_postgres.conf
@@ -2,6 +2,9 @@
 #The DB plugin to use
 DB = postgres
 
+[taler]
+CURRENCY = EUR
+
 [anastasisdb-postgres]
 #The connection string the plugin has to use for connecting to the database
 CONFIG = postgres:///anastasischeck

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



reply via email to

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