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 api/testing


From: gnunet
Subject: [taler-anastasis] branch master updated: worked on api/testing
Date: Wed, 27 Nov 2019 21:00:23 +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 b654890  worked on api/testing
b654890 is described below

commit b6548900da185445247c2ef09fc00c0d82537e8d
Author: Dennis Neufeld <address@hidden>
AuthorDate: Tue Nov 26 16:04:21 2019 +0000

    worked on api/testing
---
 src/backend/Makefile.am                 |   3 +
 src/backend/anastasis-httpd.c           |  17 +
 src/backend/anastasis-httpd.h           |   5 +
 src/backend/anastasis-httpd_policy.c    | 686 ++++++++++++++++++++++++++++----
 src/include/anastasis_database_lib.h    |  10 +
 src/include/anastasis_database_plugin.h |  11 +
 src/include/anastasis_service.h         |   2 +-
 src/lib/anastasis_api_policy_store.c    |  12 +-
 src/lib/test_anastasis_api.c            |   4 +-
 src/lib/testing_api_cmd_policy_store.c  |   2 +-
 src/stasis/plugin_anastasis_postgres.c  |  32 ++
 src/stasis/test_anastasis_db.c          |   4 +
 12 files changed, 696 insertions(+), 92 deletions(-)

diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 4198a5a..f0bdbb8 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -22,7 +22,10 @@ anastasis_httpd_LDADD = \
   $(top_builddir)/src/stasis/libanastasisdb.la \
   -lmicrohttpd \
   -ljansson \
+  -ltalermerchant \
   -ltalermhd \
+  -ltalerjson \
+  -ltalerutil \
   -lgnunetcurl \
   -lgnunetrest \
   -lgnunetjson \
diff --git a/src/backend/anastasis-httpd.c b/src/backend/anastasis-httpd.c
index 15b5a09..3c900ad 100644
--- a/src/backend/anastasis-httpd.c
+++ b/src/backend/anastasis-httpd.c
@@ -33,6 +33,11 @@
  */
 #define UNIX_BACKLOG 500
 
+/**
+ * Upload limit to the service, in megabytes.
+ */
+unsigned long long int SH_upload_limit_mb;
+
 /**
  * Should a "Connection: close" header be added to each HTTP response?
  */
@@ -456,6 +461,18 @@ run (void *cls,
                  GNUNET_log_setup ("anastasis-httpd",
                                    "WARNING",
                                    NULL));
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (config,
+                                             "anastasis",
+                                             "UPLOAD_LIMIT_MB",
+                                             &SH_upload_limit_mb))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "anastasis",
+                               "UPLOAD_LIMIT_MB");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
   if (NULL ==
       (db = ANASTASIS_DB_plugin_load (config)))
   {
diff --git a/src/backend/anastasis-httpd.h b/src/backend/anastasis-httpd.h
index f8f2b18..06083ba 100644
--- a/src/backend/anastasis-httpd.h
+++ b/src/backend/anastasis-httpd.h
@@ -132,6 +132,11 @@ struct TM_HandlerContext
  */
 extern struct ANASTASIS_DatabasePlugin *db;
 
+/**
+ * Upload limit to the service, in megabytes.
+ */
+extern unsigned long long SH_upload_limit_mb;
+
 /**
  * Kick MHD to run now, to be called after MHD_resume_connection().
  * Basically, we need to explicitly resume MHD's event loop whenever
diff --git a/src/backend/anastasis-httpd_policy.c 
b/src/backend/anastasis-httpd_policy.c
index de04f0b..d21b34f 100644
--- a/src/backend/anastasis-httpd_policy.c
+++ b/src/backend/anastasis-httpd_policy.c
@@ -22,8 +22,612 @@
  */
 #include "platform.h"
 #include "anastasis-httpd.h"
+#include "anastasis-httpd_policy.h"
+#include "anastasis_service.h"
 #include <gnunet/gnunet_util_lib.h>
 #include <gnunet/gnunet_rest_lib.h>
+#include <taler/taler_json_lib.h>
+#include <taler/taler_merchant_service.h>
+#include <taler/taler_signatures.h>
+
+/**
+ * How long do we hold an HTTP client connection if
+ * we are awaiting payment before giving up?
+ */
+#define CHECK_PAYMENT_TIMEOUT GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_MINUTES, 30)
+
+
+/**
+ * Context for an upload operation.
+ */
+struct PolicyUploadContext
+{
+
+  /**
+   * Context for cleanup logic.
+   */
+  struct TM_HandlerContext hc;
+
+  /**
+   * Signature of the account holder.
+   */
+  struct ANASTASIS_AccountSignatureP account_sig;
+
+  /**
+   * Public key of the account holder.
+   */
+  struct ANASTASIS_AccountPubP account;
+
+  /**
+   * Hash of the previous upload, or zeros if first upload.
+   */
+  struct GNUNET_HashCode old_policy_upload_hash;
+
+  /**
+   * Hash of the upload we are receiving right now (as promised
+   * by the client, to be verified!).
+   */
+  struct GNUNET_HashCode new_policy_upload_hash;
+
+  /**
+   * Hash context for the upload.
+   */
+  struct GNUNET_HashContext *hash_ctx;
+
+  /**
+   * Kept in DLL for shutdown handling while suspended.
+   */
+  struct PolicyUploadContext *next;
+
+  /**
+   * Kept in DLL for shutdown handling while suspended.
+   */
+  struct PolicyUploadContext *prev;
+
+  /**
+   * Used while suspended for resumption.
+   */
+  struct MHD_Connection *con;
+
+  /**
+   * Upload, with as many bytes as we have received so far.
+   */
+  char *upload;
+
+  /**
+   * Used while we are awaiting proposal creation.
+   */
+  struct TALER_MERCHANT_ProposalOperation *po;
+
+  /**
+   * Used while we are waiting payment.
+   */
+  struct TALER_MERCHANT_CheckPaymentOperation *cpo;
+
+  /**
+   * HTTP response code to use on resume, if non-NULL.
+   */
+  struct MHD_Response *resp;
+
+  /**
+   * Order under which the client promised payment, or NULL.
+   */
+  const char *order_id;
+
+  /**
+   * Order ID for the client that we found in our database.
+   */
+  char *existing_order_id;
+
+  /**
+   * Timestamp of the order in @e existing_order_id. Used to
+   * select the most recent unpaid offer.
+   */
+  struct GNUNET_TIME_Absolute existing_order_timestamp;
+
+  /**
+   * Expected total upload size.
+   */
+  size_t upload_size;
+
+  /**
+   * Current offset for the upload.
+   */
+  size_t upload_off;
+
+  /**
+   * HTTP response code to use on resume, if resp is set.
+   */
+  unsigned int response_code;
+
+};
+
+
+/**
+ * Kept in DLL for shutdown handling while suspended.
+ */
+static struct PolicyUploadContext *puc_head;
+
+/**
+ * Kept in DLL for shutdown handling while suspended.
+ */
+static struct PolicyUploadContext *puc_tail;
+
+
+/**
+ * Function called to clean up a backup context.
+ *
+ * @param hc a `struct PolicyUploadContext`
+ */
+static void
+cleanup_ctx (struct TM_HandlerContext *hc)
+{
+  struct PolicyUploadContext *puc = (struct PolicyUploadContext *) hc;
+
+  if (NULL != puc->po)
+    TALER_MERCHANT_proposal_cancel (puc->po);
+  if (NULL != puc->hash_ctx)
+    GNUNET_CRYPTO_hash_context_abort (puc->hash_ctx);
+  if (NULL != puc->resp)
+    MHD_destroy_response (puc->resp);
+  GNUNET_free_non_null (puc->existing_order_id);
+  GNUNET_free_non_null (puc->upload);
+  GNUNET_free (puc);
+}
+
+
+/**
+ * We got some query status from the DB.  Handle the error cases.
+ * May perform asynchronous operations by suspending the connection
+ * if required.
+ *
+ * @param puc connection to handle status for
+ * @param qs query status to handle
+ * @return #MHD_YES or #MHD_NO
+ */
+static int
+handle_database_error (struct PolicyUploadContext *puc,
+                       enum ANASTASIS_DB_QueryStatus qs)
+{
+  switch (qs)
+  {
+  case ANASTASIS_DB_STATUS_OLD_RECOVERY_UPLOAD_MISSMATCH:
+    /* FIXME handle missmatch
+
+    return SH_return_backup (puc->con,
+                             &puc->account,
+                             MHD_HTTP_CONFLICT);
+    */
+    return MHD_YES; //FIXME
+  case ANASTASIS_DB_STATUS_PAYMENT_REQUIRED:
+    /* FIXME: payment handling
+
+    {
+      const char *order_id;
+
+      order_id = MHD_lookup_connection_value (puc->con,
+                                              MHD_GET_ARGUMENT_KIND,
+                                              "paying");
+      if (NULL == order_id)
+      {
+        return begin_payment (puc,
+                              GNUNET_NO);
+      }
+      await_payment (puc,
+                     CHECK_PAYMENT_TIMEOUT,
+                     order_id);
+    }
+    */
+    return MHD_YES;
+  case ANASTASIS_DB_STATUS_HARD_ERROR:
+  case ANASTASIS_DB_STATUS_SOFT_ERROR:
+    GNUNET_break (0);
+    return TALER_MHD_reply_with_error (puc->con,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       TALER_EC_SYNC_DATABASE_FETCH_ERROR,
+                                       "failed to fetch existing record from 
database");
+  case ANASTASIS_DB_STATUS_SUCCESS_NO_RESULTS:
+    GNUNET_assert (0);
+    return MHD_NO;
+  /* intentional fall-through! */
+  case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
+    GNUNET_assert (0);
+    return MHD_NO;
+  }
+  GNUNET_break (0);
+  return MHD_NO;
+}
+
+
+/**
+ * @param connection the MHD connection to handle
+ * @param con_cls the connection's closure
+ * @param url handles a URL of the format "/policy/$ACCOUNT_PUB"
+ * @param recovery_data upload data
+ * @param recovery_data_size number of bytes (left) in @a recovery_data
+ * @return MHD result code
+ */
+int
+AH_handler_policy_POST (struct MHD_Connection *connection,
+                        void **con_cls,
+                        const char *url,
+                        const char *recovery_data,
+                        size_t *recovery_data_size)
+{
+  struct PolicyUploadContext *puc;
+  struct ANASTASIS_AccountPubP accountPubP;
+
+  puc = *con_cls;
+  if (NULL == puc)
+  {
+    /* first call, setup internals */
+    puc = GNUNET_new (struct PolicyUploadContext);
+    puc->hc.cc = &cleanup_ctx;
+    puc->con = connection;
+
+    /* extract publickey from url */
+    GNUNET_assert (0 == strncmp (url,
+                               "/policy/",
+                               strlen ("/policy/")));
+    {
+      const char *account;
+
+      account = &url[strlen ("/policy/")];
+      if (GNUNET_OK !=
+          GNUNET_CRYPTO_eddsa_public_key_from_string (account,
+                                                      strlen (account),
+                                                      &accountPubP.pub))
+      {
+        return TALER_MHD_reply_with_error (connection,
+                                          MHD_HTTP_BAD_REQUEST,
+                                          42 /*FIXME */,
+                                          "account public key malformed");
+      }
+    }
+    puc->account = accountPubP;
+    *con_cls = puc;
+
+    /* no setup 'puc' */
+    {
+      const char *lens;
+      unsigned long len;
+
+      lens = MHD_lookup_connection_value (connection,
+                                          MHD_HEADER_KIND,
+                                          MHD_HTTP_HEADER_CONTENT_LENGTH);
+      if ( (NULL == lens) ||
+           (1 !=
+            sscanf (lens,
+                    "%lu",
+                    &len)) )
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           //FIXME: ANASTASIS error c
+                                           TALER_EC_SYNC_BAD_CONTENT_LENGTH,
+                                           (NULL == lens)
+                                           ? "Content-length value missing"
+                                           : "Content-length value malformed");
+      }
+      if (len / 1024 / 1024 >= SH_upload_limit_mb)
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_PAYLOAD_TOO_LARGE,
+                                           TALER_EC_SYNC_BAD_CONTENT_LENGTH,
+                                           "Content-length value not 
acceptable");
+      }
+      puc->upload = GNUNET_malloc_large (len);
+      if (NULL == puc->upload)
+      {
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                             "malloc");
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_PAYLOAD_TOO_LARGE,
+                                           
TALER_EC_SYNC_OUT_OF_MEMORY_ON_CONTENT_LENGTH,
+                                           "Server out of memory, try again 
later");
+      }
+      puc->upload_size = (size_t) len;
+    }
+    {
+      // Check if header contains if-match
+      const char *im;
+
+      im = MHD_lookup_connection_value (connection,
+                                        MHD_HEADER_KIND,
+                                        MHD_HTTP_HEADER_IF_MATCH);
+      if ( (NULL != im) &&
+           (GNUNET_OK !=
+            GNUNET_STRINGS_string_to_data (im,
+                                           strlen (im),
+                                           &puc->old_policy_upload_hash,
+                                           sizeof 
(&puc->old_policy_upload_hash))) )
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           TALER_EC_SYNC_BAD_IF_MATCH,
+                                           "If-Match does not include a 
base32-encoded SHA-512 hash");
+      }
+    }
+    {
+      // Check if header contains Anastasis-Policy-Signature
+      const char *sig_s;
+
+      sig_s = MHD_lookup_connection_value (connection,
+                                           MHD_HEADER_KIND,
+                                           "Anastasis-Policy-Signature");
+      if ( (NULL == sig_s) ||
+           (GNUNET_OK !=
+            GNUNET_STRINGS_string_to_data (sig_s,
+                                           strlen (sig_s),
+                                           &puc->account_sig,
+                                           sizeof (&puc->account_sig))) )
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           TALER_EC_SYNC_BAD_SYNC_SIGNATURE,
+                                           "Anastasis-Policy-Signature does 
not include a base32-encoded EdDSA signature");
+      }
+    }
+    {
+      // Check if header contains an ETAG
+      const char *etag;
+
+      etag = MHD_lookup_connection_value (connection,
+                                          MHD_HEADER_KIND,
+                                          MHD_HTTP_HEADER_ETAG);
+      if ( (NULL == etag) ||
+           (GNUNET_OK !=
+            GNUNET_STRINGS_string_to_data (etag,
+                                           strlen (etag),
+                                           &puc->new_policy_upload_hash,
+                                           sizeof 
(&puc->new_policy_upload_hash))) )
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           TALER_EC_SYNC_BAD_ETAG,
+                                           "Etag does not include a 
base32-encoded SHA-512 hash");
+      }
+    }
+    /* validate signature */
+    {
+      struct ANASTASIS_UploadSignaturePS usp;
+
+      usp.purpose.size = htonl (sizeof (struct ANASTASIS_UploadSignaturePS));
+      usp.purpose.purpose = htonl (TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD);
+      usp.old_recovery_data_hash = puc->old_policy_upload_hash;
+      usp.new_recovery_data_hash = puc->new_policy_upload_hash;
+      if (GNUNET_OK !=
+          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD,
+                                      &usp.purpose,
+                                      &puc->account_sig.eddsa_sig,
+                                      &accountPubP.pub))
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_FORBIDDEN,
+                                           TALER_EC_SYNC_INVALID_SIGNATURE,
+                                           "Account signature does not match 
upload");
+      }
+    }
+    /* get ready to hash (done here as we may go aANASTASIS for payments next) 
*/
+    puc->hash_ctx = GNUNET_CRYPTO_hash_context_start ();
+
+    /* Check database to see if the transaction is permissable */
+    {
+      struct GNUNET_HashCode hc;
+      enum ANASTASIS_DB_QueryStatus qs;
+
+      qs = db->lookup_account (db->cls,
+                               &accountPubP);
+      if (qs < 0)
+        return handle_database_error (puc,
+                                      qs);
+      if (ANASTASIS_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+        memset (&hc, 0, sizeof (hc));
+      if (0 == GNUNET_memcmp (&hc,
+                              &puc->new_policy_upload_hash))
+      {
+        /* Refuse upload: we already have that backup! */
+        struct MHD_Response *resp;
+        int ret;
+
+        resp = MHD_create_response_from_buffer (0,
+                                                NULL,
+                                                MHD_RESPMEM_PERSISTENT);
+        GNUNET_break (MHD_YES ==
+                      MHD_add_response_header (resp,
+                                               
MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+                                               "*"));
+        ret = MHD_queue_response (connection,
+                                  MHD_HTTP_NOT_MODIFIED,
+                                  resp);
+        MHD_destroy_response (resp);
+        return ret;
+      }
+      if (0 != GNUNET_memcmp (&hc,
+                              &puc->old_policy_upload_hash))
+      {
+        /* Refuse upload: if-none-match failed! */
+        return SH_return_backup (connection,
+                                 accountPubP,
+                                 MHD_HTTP_CONFLICT);
+      }
+    }
+    /* check if the client insists on paying */
+    { /* FIXME handle paying
+      const char *order_req;
+
+      order_req = MHD_lookup_connection_value (connection,
+                                               MHD_GET_ARGUMENT_KIND,
+                                               "pay");
+      if (NULL != order_req)
+        return begin_payment (puc,
+                              GNUNET_YES);
+    } */
+    /* ready to begin! */
+    return MHD_YES;
+  }
+  /* handle upload */
+  // FIXME adapt upload handling
+  if (0 != recovery_data_size)
+  {
+    /* check MHD invariant */
+    GNUNET_assert (puc->upload_off + *recovery_data_size <= puc->upload_size);
+    memcpy (&puc->upload[puc->upload_off],
+            recovery_data,
+            *recovery_data_size);
+    puc->upload_off += *recovery_data_size;
+    GNUNET_CRYPTO_hash_context_read (puc->hash_ctx,
+                                     recovery_data,
+                                     *recovery_data_size);
+    *recovery_data_size = 0;
+    return MHD_YES;
+  }
+  if (NULL != bc->resp)
+  {
+    /* We generated a response asynchronously, queue that */
+    return MHD_queue_response (connection,
+                               bc->response_code,
+                               bc->resp);
+  }
+
+  /* finished with upload, check hash */
+  {
+    struct GNUNET_HashCode our_hash;
+
+    GNUNET_CRYPTO_hash_context_finish (bc->hash_ctx,
+                                       &our_hash);
+    bc->hash_ctx = NULL;
+    if (0 != GNUNET_memcmp (&our_hash,
+                            &bc->new_backup_hash))
+    {
+      GNUNET_break_op (0);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_BAD_REQUEST,
+                                         TALER_EC_SYNC_INVALID_UPLOAD,
+                                         "Data uploaded does not match Etag 
promise");
+    }
+  }
+
+  /* store backup to database */
+  {
+    enum SYNC_DB_QueryStatus qs;
+
+    if (GNUNET_is_zero (&bc->old_backup_hash))
+      qs = db->store_backup_TR (db->cls,
+                                account,
+                                &bc->account_sig,
+                                &bc->new_backup_hash,
+                                bc->upload_size,
+                                bc->upload);
+    else
+      qs = db->update_backup_TR (db->cls,
+                                 account,
+                                 &bc->old_backup_hash,
+                                 &bc->account_sig,
+                                 &bc->new_backup_hash,
+                                 bc->upload_size,
+                                 bc->upload);
+    if (qs < 0)
+      return handle_database_error (bc,
+                                    qs);
+    if (0 == qs)
+    {
+      /* database says nothing actually changed, 304 (could
+         theoretically happen if another equivalent upload succeeded
+         since we last checked!) */
+      struct MHD_Response *resp;
+      int ret;
+
+      resp = MHD_create_response_from_buffer (0,
+                                              NULL,
+                                              MHD_RESPMEM_PERSISTENT);
+      GNUNET_break (MHD_YES ==
+                    MHD_add_response_header (resp,
+                                             
MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+                                             "*"));
+      ret = MHD_queue_response (connection,
+                                MHD_HTTP_NOT_MODIFIED,
+                                resp);
+      MHD_destroy_response (resp);
+      return ret;
+    }
+  }
+
+  /* generate main (204) standard success reply */
+  {
+    struct MHD_Response *resp;
+    int ret;
+
+    resp = MHD_create_response_from_buffer (0,
+                                            NULL,
+                                            MHD_RESPMEM_PERSISTENT);
+    GNUNET_break (MHD_YES ==
+                  MHD_add_response_header (resp,
+                                           
MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+                                           "*"));
+    ret = MHD_queue_response (connection,
+                              MHD_HTTP_NO_CONTENT,
+                              resp);
+    MHD_destroy_response (resp);
+    return ret;
+  }
+  
+  void *recovery_data;
+  const char *paymentIdentifier_str;
+  const struct ANASTASIS_PaymentSecretP *paymentIdentifier;
+  unsigned int version;
+  int ret;
+
+  GNUNET_STRINGS_string_to_data (recovery_data,
+                                 strlen (recovery_data),
+                                 &recovery_data,
+                                 sizeof (recovery_data));
+
+  
+
+    paymentIdentifier_str = MHD_lookup_connection_value (connection,
+                                                         MHD_HEADER_KIND,
+                                                         "Payment-Identifier");
+
+    memcpy (&paymentIdentifier,
+            paymentIdentifier_str,
+            strlen (paymentIdentifier_str) + 1);
+
+    db->store_recovery_document (db->cls,
+                                 &accountPubP,
+                                 recovery_data,
+                                 sizeof (recovery_data),
+                                 paymentIdentifier,
+                                 &version);
+
+  }
+
+  // BUILD reply
+  {
+    struct MHD_Response *response;
+
+    // FIXME: find correct create response
+    response = GNUNET_REST_create_response ("Irgendwas");
+
+    TALER_MHD_add_global_headers (response);
+    GNUNET_break (MHD_YES ==
+                  MHD_add_response_header (response,
+                                           "Anastasis-Version",
+                                           version + ""));
+    ret = MHD_queue_response (connection,
+                              MHD_HTTP_OK,
+                              response);
+    MHD_destroy_response (response);
+  }
+  return ret;
+}
 
 
 /**
@@ -146,85 +750,3 @@ AH_handler_policy_GET (struct MHD_Connection *connection,
   return ret;
 }
 
-/**
- * @param connection the MHD connection to handle
- * @param con_cls the connection's closure
- * @param url handles a URL of the format "/policy/$ACCOUNT_PUB"
- * @param upload_data upload data
- * @param upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
-int
-AH_handler_policy_POST (struct MHD_Connection *connection,
-                        void **con_cls,
-                        const char *url,
-                        const char *upload_data,
-                        size_t *upload_data_size)
-{
-
-  struct ANASTASIS_AccountPubP accountPubP;
-  void *recovery_data;
-  const char *paymentIdentifier_str;
-  const struct ANASTASIS_PaymentSecretP *paymentIdentifier;
-  unsigned int version;
-  int ret;
-
-  GNUNET_STRINGS_string_to_data (upload_data,
-                                 strlen (upload_data),
-                                 &recovery_data,
-                                 sizeof (recovery_data));
-
-  GNUNET_assert (0 == strncmp (url,
-                               "/policy/",
-                               strlen ("/policy/")));
-  {
-    const char *account;
-
-    account = &url[strlen ("/policy/")];
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_eddsa_public_key_from_string (account,
-                                                    strlen (account),
-                                                    &accountPubP.pub))
-    {
-      return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_BAD_REQUEST,
-                                         42 /*FIXME */,
-                                         "account public key malformed");
-    }
-
-    paymentIdentifier_str = MHD_lookup_connection_value (connection,
-                                                         MHD_HEADER_KIND,
-                                                         "Payment-Identifier");
-
-    memcpy (&paymentIdentifier,
-            paymentIdentifier_str,
-            strlen (paymentIdentifier_str) + 1);
-
-    db->store_recovery_document (db->cls,
-                                 &accountPubP,
-                                 recovery_data,
-                                 sizeof (recovery_data),
-                                 paymentIdentifier,
-                                 &version);
-
-  }
-
-  // BUILD reply
-  {
-    struct MHD_Response *response;
-
-    // FIXME: find correct create response
-    response = GNUNET_REST_create_response ("Irgendwas");
-
-    TALER_MHD_add_global_headers (response);
-    GNUNET_break (MHD_YES ==
-                  MHD_add_response_header (response,
-                                           "Anastasis-Version",
-                                           version + ""));
-    ret = MHD_queue_response (connection,
-                              MHD_HTTP_OK,
-                              response);
-    MHD_destroy_response (response);
-  }
-  return ret;
-}
diff --git a/src/include/anastasis_database_lib.h 
b/src/include/anastasis_database_lib.h
index 39a4b54..9a6f253 100644
--- a/src/include/anastasis_database_lib.h
+++ b/src/include/anastasis_database_lib.h
@@ -47,6 +47,16 @@ ANASTASIS_DB_plugin_unload (struct ANASTASIS_DatabasePlugin 
*plugin);
  */
 enum ANASTASIS_DB_QueryStatus
 {
+  /**
+   * Update failed because the old recovery data hash does not match what we 
previously had in the DB.
+   */
+  ANASTASIS_DB_STATUS_OLD_RECOVERY_UPLOAD_MISSMATCH = -4,
+
+  /**
+   * Account is unpaid / does not exist.
+   */
+  ANASTASIS_DB_STATUS_PAYMENT_REQUIRED = -3,
+
   /**
    * A hard error occurred, retrying will not help.
    */
diff --git a/src/include/anastasis_database_plugin.h 
b/src/include/anastasis_database_plugin.h
index e4d59ac..3529ae2 100644
--- a/src/include/anastasis_database_plugin.h
+++ b/src/include/anastasis_database_plugin.h
@@ -28,6 +28,7 @@
 #include <taler/taler_util.h>
 #include <uuid/uuid.h>
 
+
 /**
  * Handle to interact with the database.
  *
@@ -249,5 +250,15 @@ struct ANASTASIS_DatabasePlugin
                    const uuid_t *uuid,
                    void **key_share,
                    size_t *key_share_size);
+
+  /**
+* @param cls closure
+* @param anastasis_pub account identifier
+* @return transaction status
+*/
+enum ANASTASIS_DB_QueryStatus
+(*lookup_account)(void *cls,
+                  const struct
+                  ANASTASIS_AccountPubP *anastasis_pub);
 };
 #endif
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index 89e9664..3a79bdc 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -332,7 +332,7 @@ ANASTASIS_policy_store (struct GNUNET_CURL_Context *ctx,
                         const char *backend_url,
                         const struct
                         ANASTASIS_AccountPrivP *anastasis_priv,
-                        const struct 
+                        const struct
                         GNUNET_HashCode *prev_recovery_data_hash,
                         const void *recovery_data,
                         size_t recovery_data_size,
diff --git a/src/lib/anastasis_api_policy_store.c 
b/src/lib/anastasis_api_policy_store.c
index 4e5130d..701a18a 100644
--- a/src/lib/anastasis_api_policy_store.c
+++ b/src/lib/anastasis_api_policy_store.c
@@ -262,7 +262,7 @@ ANASTASIS_policy_store (struct GNUNET_CURL_Context *ctx,
                         const char *backend_url,
                         const struct
                         ANASTASIS_AccountPrivP *anastasis_priv,
-                        const struct 
+                        const struct
                         GNUNET_HashCode *prev_recovery_data_hash,
                         const void *recovery_data,
                         size_t recovery_data_size,
@@ -371,15 +371,15 @@ ANASTASIS_policy_store (struct GNUNET_CURL_Context *ctx,
 
     GNUNET_CRYPTO_eddsa_key_get_public (&anastasis_priv->priv,
                                         &pub.pub);
-    
+
     acc_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&pub.pub);
     GNUNET_asprintf (&path,
-                    "policy/%s",
-                    acc_pub_str);
+                     "policy/%s",
+                     acc_pub_str);
     GNUNET_free (acc_pub_str);
     pso->url = TALER_url_join (backend_url,
-                              "policy",
-                              pub);
+                               "policy",
+                               pub);
     GNUNET_free (path);
   }
   pso->ctx = ctx;
diff --git a/src/lib/test_anastasis_api.c b/src/lib/test_anastasis_api.c
index c1876fb..9a24054 100644
--- a/src/lib/test_anastasis_api.c
+++ b/src/lib/test_anastasis_api.c
@@ -240,8 +240,8 @@ static void
 run (void *cls,
      struct TALER_TESTING_Interpreter *is)
 {
-  
-  //fill data
+
+  // fill data
   const char *str = "AHV123456789";
   GNUNET_CRYPTO_eddsa_private_key_from_string (str,
                                                sizeof (str),
diff --git a/src/lib/testing_api_cmd_policy_store.c 
b/src/lib/testing_api_cmd_policy_store.c
index e04337f..e8cc863 100644
--- a/src/lib/testing_api_cmd_policy_store.c
+++ b/src/lib/testing_api_cmd_policy_store.c
@@ -40,7 +40,7 @@ struct PolicyStoreState
    */
   const void *recovery_data;
 
-  /** 
+  /**
    * Number of bytes in @e recovery_data
    */
   size_t recovery_data_size;
diff --git a/src/stasis/plugin_anastasis_postgres.c 
b/src/stasis/plugin_anastasis_postgres.c
index e034a0a..66d79b4 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -757,6 +757,37 @@ postgres_get_key_share (void *cls,
                                                    rs);
 }
 
+
+/**
+* @param cls closure
+* @param anastasis_pub account identifier
+* @return transaction status
+*/
+enum ANASTASIS_DB_QueryStatus
+postgres_lookup_account (void *cls,
+                         const struct 
+                         ANASTASIS_AccountPubP *anastasis_pub)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute paid_until;
+  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),
+    GNUNET_PQ_result_spec_end
+  };
+
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "user_select",
+                                                   params,
+                                                   rs);
+}
+
+
 /**
  * Fetch latest recovery document for user.
  *
@@ -1006,6 +1037,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
   plugin->get_key_share = &postgres_get_key_share;
   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->start = &begin_transaction;
   plugin->check_connection = &check_connection;
 
diff --git a/src/stasis/test_anastasis_db.c b/src/stasis/test_anastasis_db.c
index 704b1e2..da458fb 100644
--- a/src/stasis/test_anastasis_db.c
+++ b/src/stasis/test_anastasis_db.c
@@ -186,6 +186,10 @@ run (void *cls)
                                   rel_time,
                                   &paymentSecretP));
 
+  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+          plugin->lookup_account (plugin->cls,
+                                  &accountPubP));
+
   FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->store_truth (plugin->cls,
                                &uuid,

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



reply via email to

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