[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-anastasis] 01/04: Worked on truth api
From: |
gnunet |
Subject: |
[taler-anastasis] 01/04: Worked on truth api |
Date: |
Wed, 22 Jan 2020 12:46:09 +0100 |
This is an automated email from the git hooks/post-receive script.
dennis-neufeld pushed a commit to branch master
in repository anastasis.
commit 7346322d1eb18b070f0443897e9debd620c0e602
Author: Dennis Neufeld <address@hidden>
AuthorDate: Tue Jan 21 16:04:35 2020 +0000
Worked on truth api
---
src/include/anastasis_service.h | 8 +-
src/include/anastasis_testing_lib.h | 72 +++++-
src/lib/Makefile.am | 2 +
src/lib/anastasis_api_truth_store.c | 36 ++-
src/lib/test_anastasis_api.c | 14 +-
src/lib/testing_api_cmd_policy_store.c | 7 -
src/lib/testing_api_cmd_truth_store.c | 427 +++++++++++++++++++++++++++++++++
src/stasis/Datenbank-Schema.xml | 2 +-
8 files changed, 547 insertions(+), 21 deletions(-)
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index e314bd0..ff8b677 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -463,7 +463,7 @@ ANASTASIS_key_share_lookup (struct GNUNET_CURL_Context *ctx,
*/
void
ANASTASIS_key_share_lookup_cancel (struct
- ANASTASIS_TruthLookupOperation *klo);
+ ANASTASIS_TruthLookupOperation *tlo);
/**
* Handle for a POST /truth operation.
@@ -485,13 +485,15 @@ typedef void
unsigned int http_status,
const struct ANASTASIS_UploadDetails *up);
/**
- * Store Truth, does a POST /policy/$UUID
+ * Store Truth, does a POST /truth/$UUID
*
* @param ctx the CURL context used to connect to the backend
* @param backend_url backend's base URL, including final "/"
* @param truth_uuid Identfication of the Truth Upload
* @param prev_truth_data_hash hash of the previous truth upload, NULL for the
first upload ever
* @param truth_data contains the data which is stored on the Server in JSON
Format
+ * @param payment_requested
+ * @param paid_order_id
* @param cb callback processing the response from /truth
* @param cb_cls closure for cb
* @return handle for the operation
@@ -504,6 +506,8 @@ ANASTASIS_truth_store (struct GNUNET_CURL_Context *ctx,
const struct
GNUNET_HashCode *prev_truth_data_hash,
json_t *truth_data,
+ int payment_requested,
+ const char *paid_order_id,
ANASTASIS_TruthStoreCallback cb,
void *cb_cls);
diff --git a/src/include/anastasis_testing_lib.h
b/src/include/anastasis_testing_lib.h
index dde2b37..76a2e2b 100644
--- a/src/include/anastasis_testing_lib.h
+++ b/src/include/anastasis_testing_lib.h
@@ -256,8 +256,8 @@ enum ANASTASIS_TESTING_PolicyStoreOption
* @param priv private account identifier
* @param pub account identifier
* @param payment_id payment identifier
- * @param policy_data recovery data to post
- * @param policy_data_size size of recovery/policy data
+ * @param policy_data recovery data to post /policy
+ * @param policy_data_size size of recovery data
* @return the command
*/
struct TALER_TESTING_Command
@@ -275,7 +275,7 @@ ANASTASIS_TESTING_cmd_policy_store (const char *label,
*
* @param label command label
* @param ANASTASIS_url base URL of the ANASTASIS serving
- * the policy store request.
+ * the policy lookup request.
* @param http_status expected HTTP status.
* @param upload_ref reference to upload command
* @return the command
@@ -286,4 +286,70 @@ ANASTASIS_TESTING_cmd_policy_lookup (const char *label,
unsigned int http_status,
const char *upload_ref);
+
+/**
+ * Types of options for performing the upload. Used as a bitmask.
+ */
+enum ANASTASIS_TESTING_TruthStoreOption
+{
+ /**
+ * Do everything by the book.
+ */
+ ANASTASIS_TESTING_TSO_NONE = 0,
+
+ /**
+ * Use random hash for previous upload instead of correct
+ * previous hash.
+ */
+ ANASTASIS_TESTING_TSO_PREV_HASH_WRONG = 1,
+
+ /**
+ * Request payment.
+ */
+ ANASTASIS_TESTING_TSO_REQUEST_PAYMENT = 2,
+
+ /**
+ * Reference payment order ID from linked previous upload.
+ */
+ ANASTASIS_TESTING_TSO_REFERENCE_ORDER_ID = 4
+
+};
+
+/**
+ * Make the "truth store" command.
+ *
+ * @param label command label
+ * @param anastasis_url base URL of the anastasis serving
+ * the truth store request.
+ * @param http_status expected HTTP status.
+ * @param truth_data recovery data to post /truth
+ * @param truth_data_size size of truth data
+ * @return the command
+ */
+struct TALER_TESTING_Command
+ANASTASIS_TESTING_cmd_truth_store (const char *label,
+ const char *anastasis_url,
+ const char *prev_upload,
+ unsigned int http_status,
+ enum
+ ANASTASIS_TESTING_TruthStoreOption tso,
+ const void *truth_data,
+ size_t truth_data_size);
+
+/**
+ * Make the "truth lookup" command.
+ *
+ * @param label command label
+ * @param ANASTASIS_url base URL of the ANASTASIS serving
+ * the truth lookup request.
+ * @param http_status expected HTTP status.
+ * @param upload_ref reference to upload command
+ * @return the command
+ */
+struct TALER_TESTING_Command
+ANASTASIS_TESTING_cmd_truth_lookup (const char *label,
+ const char *ANASTASIS_url,
+ unsigned int http_status,
+ const char *upload_ref);
+
#endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index e893b22..d41e1c0 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -17,6 +17,7 @@ libanastasisrest_la_LDFLAGS = \
libanastasisrest_la_SOURCES = \
anastasis_api_salt.c \
anastasis_api_policy_store.c \
+ anastasis_api_truth_store.c \
anastasis_api_policy_lookup.c \
anastasis_api_curl_defaults.c anastasis_api_curl_defaults.h
libanastasisrest_la_LIBADD = \
@@ -51,6 +52,7 @@ libanastasistesting_la_LDFLAGS = \
-no-undefined
libanastasistesting_la_SOURCES = \
testing_api_cmd_policy_store.c \
+ testing_api_cmd_truth_store.c \
testing_api_cmd_policy_lookup.c \
testing_api_helpers.c \
testing_api_trait_account_pub.c \
diff --git a/src/lib/anastasis_api_truth_store.c
b/src/lib/anastasis_api_truth_store.c
index 41d3a21..24322b8 100644
--- a/src/lib/anastasis_api_truth_store.c
+++ b/src/lib/anastasis_api_truth_store.c
@@ -65,6 +65,11 @@ struct ANASTASIS_TruthStoreOperation
*/
void *cb_cls;
+ /**
+ * Payment URI we received from the service, or NULL.
+ */
+ char *pay_uri;
+
/**
* Hash of the data we are uploading.
*/
@@ -234,13 +239,15 @@ handle_header (char *buffer,
/**
- * Store Truth, does a POST /policy/$UUID
+ * Store Truth, does a POST /truth/$UUID
*
* @param ctx the CURL context used to connect to the backend
* @param backend_url backend's base URL, including final "/"
* @param truth_uuid Identfication of the Truth Upload
* @param prev_truth_data_hash hash of the previous truth upload, NULL for the
first upload ever
* @param truth_data contains the data which is stored on the Server in JSON
Format
+ * @param payment_requested
+ * @param paid_order_id
* @param cb callback processing the response from /truth
* @param cb_cls closure for cb
* @return handle for the operation
@@ -253,6 +260,8 @@ ANASTASIS_truth_store (struct GNUNET_CURL_Context *ctx,
const struct
GNUNET_HashCode *prev_truth_data_hash,
json_t *truth_data,
+ int payment_requested,
+ const char *paid_order_id,
ANASTASIS_TruthStoreCallback cb,
void *cb_cls)
{
@@ -337,6 +346,7 @@ ANASTASIS_truth_store (struct GNUNET_CURL_Context *ctx,
tso->cb = cb;
tso->cb_cls = cb_cls;
eh = ANASTASIS_curl_easy_get_ (tso->url);
+ /*
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_POSTFIELDS,
@@ -353,11 +363,25 @@ ANASTASIS_truth_store (struct GNUNET_CURL_Context *ctx,
curl_easy_setopt (eh,
CURLOPT_HEADERDATA,
tso));
- tso->job = GNUNET_CURL_job_add_raw (ctx,
- eh,
- job_headers,
- &handle_truth_store_finished,
- tso);
+ */
+ if (GNUNET_OK !=
+ TALER_curl_easy_post (ctx,
+ eh,
+ truth_data))
+ {
+ GNUNET_break (0);
+ curl_easy_cleanup (eh);
+ json_decref (truth_data);
+ GNUNET_free (tso->url);
+ GNUNET_free (tso);
+ return NULL;
+ }
+ json_decref (truth_data);
+ tso->job = GNUNET_CURL_job_add2 (ctx,
+ eh,
+ job_headers,
+ &handle_truth_store_finished,
+ tso);
curl_slist_free_all (job_headers);
return tso;
}
diff --git a/src/lib/test_anastasis_api.c b/src/lib/test_anastasis_api.c
index 1203a6d..2ac0bad 100644
--- a/src/lib/test_anastasis_api.c
+++ b/src/lib/test_anastasis_api.c
@@ -253,6 +253,8 @@ run (void *cls,
TALER_TESTING_cmd_end ()
};
+
+
struct TALER_TESTING_Command policy[] = {
// FIXME: Code for policy handling
@@ -301,6 +303,13 @@ run (void *cls,
struct TALER_TESTING_Command truth[] = {
// FIXME: Code for truth handling
+ ANASTASIS_TESTING_cmd_truth_store ("truth-strore-1",
+ anastasis_url,
+ NULL,
+ MHD_HTTP_NO_CONTENT,
+ ANASTASIS_TESTING_TSO_NONE,
+ "Test-2",
+ strlen ("Test-2")),
TALER_TESTING_cmd_end ()
};
@@ -309,11 +318,12 @@ run (void *cls,
TALER_TESTING_cmd_batch ("pay",
pay),
+ TALER_TESTING_cmd_batch ("truth",
+ truth),
+
TALER_TESTING_cmd_batch ("policy",
policy),
- TALER_TESTING_cmd_batch ("truth",
- truth),
/**
* End the suite. Fixme: better to have a label for this
diff --git a/src/lib/testing_api_cmd_policy_store.c
b/src/lib/testing_api_cmd_policy_store.c
index 606ccbf..cfb4cf1 100644
--- a/src/lib/testing_api_cmd_policy_store.c
+++ b/src/lib/testing_api_cmd_policy_store.c
@@ -364,13 +364,6 @@ policy_store_run (void *cls,
&pss->anastasis_pub.pub);
GNUNET_free (priv);
}
- /*{
- // generate nonce
- GNUNET_CRYPTO_random_block
- (GNUNET_CRYPTO_QUALITY_WEAK,
- &pss->nonce,
- sizeof (pss->nonce));
- }*/
{
// hash recovery data
GNUNET_CRYPTO_hash (pss->recovery_data,
diff --git a/src/lib/testing_api_cmd_truth_store.c
b/src/lib/testing_api_cmd_truth_store.c
new file mode 100644
index 0000000..ba9be35
--- /dev/null
+++ b/src/lib/testing_api_cmd_truth_store.c
@@ -0,0 +1,427 @@
+/*
+ This file is part of ANASTASIS
+ Copyright (C) 2014-2019 Taler Systems SA
+
+ ANASTASIS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or
+ (at your option) any later version.
+
+ ANASTASIS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with ANASTASIS; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file lib/testing_api_cmd_truth_store.c
+ * @brief command to execute the anastasis backend service.
+ * @author Dennis Neufeld
+ */
+
+#include "platform.h"
+#include "anastasis_service.h"
+#include "anastasis_testing_lib.h"
+#include <taler/taler_util.h>
+#include <taler/taler_testing_lib.h>
+
+/**
+ * State for a "truth store" CMD.
+ */
+struct TruthStoreState
+{
+
+ /**
+ * The policy data.
+ */
+ const json_t *truth_data;
+
+ /**
+ * Expected status code.
+ */
+ unsigned int http_status;
+
+ /**
+ * Hash of the previous upload (maybe bogus if
+ * #ANASTASIS_TESTING_UO_PREV_HASH_WRONG is set in @e uo).
+ * Maybe all zeros if there was no previous upload.
+ */
+ struct GNUNET_HashCode prev_hash;
+
+ struct ANASTASIS_UuidP truth_uuid;
+
+ /**
+ * Hash of the current upload.
+ */
+ struct GNUNET_HashCode curr_hash;
+
+ /**
+ * The /truth POST operation handle.
+ */
+ struct ANASTASIS_TruthStoreOperation *tso;
+
+ /**
+ * The nonce.
+ */
+ struct GNUNET_CRYPTO_EddsaPublicKey nonce;
+
+ /**
+ * URL of the anastasis backend.
+ */
+ const char *anastasis_url;
+
+ /**
+ * The interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * Previous upload, or NULL for none. Used to calculate what THIS
+ * upload is based on.
+ */
+ const char *prev_upload;
+
+ /**
+ * Last upload, or NULL for none, usually same as @e prev_upload.
+ * Used to check the response on #MHD_HTTP_CONFLICT.
+ */
+ const char *last_upload;
+
+ /**
+ * Payment order ID we got back, if any. Otherwise NULL.
+ */
+ char *payment_order_id;
+
+ /**
+ * Payment order ID we are to provide in the request, may be NULL.
+ */
+ const char *payment_order_req;
+
+ /**
+ * Options for how we are supposed to do the upload.
+ */
+ enum ANASTASIS_TESTING_TruthStoreOption tsopt;
+};
+
+/**
+ * Function called with the results of a #truth_store().
+ *
+ * @param cls closure
+ * @param ec Taler error code
+ * @param http_status HTTP status of the request
+ * @param ud details about the upload operation
+ */
+static void
+truth_store_cb (void *cls,
+ enum ANASTASIS_ErrorCode ec,
+ unsigned int http_status,
+ const struct ANASTASIS_UploadDetails *ud)
+{
+ struct TruthStoreState *tss = cls;
+ tss->tso = NULL;
+ if (http_status != tss->http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u to command %s in %s:%u\n",
+ http_status,
+ tss->is->commands[tss->is->ip].label,
+ __FILE__,
+ __LINE__);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ if (NULL != ud)
+ {
+ switch (ud->us)
+ {
+ case ANASTASIS_US_SUCCESS:
+ if (0 != GNUNET_memcmp (&tss->curr_hash,
+ ud->details.curr_backup_hash))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ break;
+ case ANASTASIS_US_PAYMENT_REQUIRED:
+ {
+ /* FIXME: Payment required handling */
+ const char *m;
+
+ if (0 != strncmp (ud->details.payment_request,
+ "taler://pay/http",
+ strlen ("taler://pay/http")))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Did not find `%s' in `%s'\n",
+ "/-/-/",
+ ud->details.payment_request);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ m = strstr (ud->details.payment_request, "/-/-/");
+ if (NULL == m)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Did not find `%s' in `%s'\n",
+ "/-/-/",
+ ud->details.payment_request);
+ TALER_TESTING_interpreter_fail (tss->is);
+ /* NOTE: The above is a simplifying assumption for the
+ test-logic, hitting this code merely means that
+ the assumptions for the test (i.e. no instance) are
+ not satisfied, it is not inherently the case that
+ the above token must appear in the payment request!
+
+ So if you hit this, you might just want to modify
+ the code here to handle this better! */return;
+ }
+ tss->payment_order_id = GNUNET_strdup (&m[strlen ("/-/-/")]);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Order ID from Anastasis service is `%s'\n",
+ tss->payment_order_id);
+
+ memset (&tss->curr_hash,
+ 0,
+ sizeof (struct GNUNET_HashCode));
+ }
+ break;
+ case ANASTASIS_US_CONFLICTING_POLICY:
+ {
+ const struct TALER_TESTING_Command *ref;
+ const struct GNUNET_HashCode *h;
+
+ ref = TALER_TESTING_interpreter_lookup_command
+ (tss->is,
+ tss->last_upload);
+ GNUNET_assert (NULL != ref);
+ GNUNET_assert (GNUNET_OK ==
+ ANASTASIS_TESTING_get_trait_hash (ref,
+
ANASTASIS_TESTING_TRAIT_HASH_CURRENT,
+ &h));
+ if (0 != GNUNET_memcmp (h,
+ &ud->details.recovered_backup.
+ existing_backup_hash))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ }
+ case ANASTASIS_US_HTTP_ERROR:
+ break;
+ case ANASTASIS_US_CLIENT_ERROR:
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ case ANASTASIS_US_SERVER_ERROR:
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ }
+ TALER_TESTING_interpreter_next (tss->is);
+}
+
+
+/**
+ * Run a "truth store" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command currently being run.
+ * @param is interpreter state.
+ */
+static void
+truth_store_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct TruthStoreState *tss = cls;
+ tss->is = is;
+ if (NULL != tss->prev_upload)
+ {
+ const struct TALER_TESTING_Command *ref;
+
+ ref = TALER_TESTING_interpreter_lookup_command
+ (is,
+ tss->prev_upload);
+ if (NULL == ref)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ {
+ const struct GNUNET_HashCode *h;
+
+ if (GNUNET_OK !=
+ ANASTASIS_TESTING_get_trait_hash (ref,
+
ANASTASIS_TESTING_TRAIT_HASH_CURRENT,
+ &h))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ tss->prev_hash = *h;
+ }
+ if (0 != (ANASTASIS_TESTING_TSO_REFERENCE_ORDER_ID & tss->tsopt))
+ {
+ {
+ const char *order_id;
+
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_order_id (ref,
+ 0,
+ &order_id))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ tss->payment_order_req = order_id;
+ if (NULL == tss->payment_order_req)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+ }
+ }
+ }
+ {
+ // hash truth data
+ GNUNET_CRYPTO_hash (tss->truth_data,
+ sizeof (tss->truth_data),
+ &tss->curr_hash);
+ }
+ tss->tso = ANASTASIS_truth_store (is->ctx,
+ tss->anastasis_url,
+ &tss->truth_uuid,
+ ( ( (NULL != tss->prev_upload) &&
+ (0 != GNUNET_is_zero (
+ &tss->prev_hash)) ) ||
+ (0 !=
+ (ANASTASIS_TESTING_TSO_PREV_HASH_WRONG
+ & tss->tsopt)) )
+ ? &tss->prev_hash
+ : NULL,
+ tss->truth_data,
+ (0 !=
+ (ANASTASIS_TESTING_TSO_REQUEST_PAYMENT
+ & tss->tsopt)),
+ tss->payment_order_req,
+ &truth_store_cb,
+ tss);
+ if (NULL == tss->tso)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (tss->is);
+ return;
+ }
+}
+
+
+/**
+ * Free the state of a "truth store" CMD, and possibly
+ * cancel it if it did not complete.
+ *
+ * @param cls closure.
+ * @param cmd command being freed.
+ */
+static void
+truth_store_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct TruthStoreState *tss = cls;
+
+ if (NULL != tss->tso)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command '%s' did not complete (truth post)\n",
+ cmd->label);
+ ANASTASIS_truth_store_cancel (tss->tso);
+ tss->tso = NULL;
+ }
+
+ GNUNET_free_non_null ((void *) tss->payment_order_id);
+ GNUNET_free (tss);
+}
+
+
+/**
+ * Offer internal data to other commands.
+ *
+ * @param cls closure
+ * @param ret[out] result (could be anything)
+ * @param trait name of the trait
+ * @param index index number of the object to extract.
+ * @return #GNUNET_OK on success
+ */
+static int
+truth_store_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct TruthStoreState *tss = cls;
+ struct TALER_TESTING_Trait traits[] = {
+ ANASTASIS_TESTING_make_trait_hash (ANASTASIS_TESTING_TRAIT_HASH_CURRENT,
+ &tss->curr_hash),
+ TALER_TESTING_make_trait_order_id (0,
+ tss->payment_order_id),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+}
+
+
+/**
+ * Make the "truth store" command.
+ *
+ * @param label command label
+ * @param anastasis_url base URL of the anastasis serving
+ * the truth store request.
+ * @param http_status expected HTTP status.
+ * @param tso truth store options
+ * @param truth_data recovery data to post /truth
+ * @param truth_data_size size of truth data
+ * @return the command
+ */
+struct TALER_TESTING_Command
+ANASTASIS_TESTING_cmd_truth_store (const char *label,
+ const char *anastasis_url,
+ const char *prev_upload,
+ unsigned int http_status,
+ enum
+ ANASTASIS_TESTING_TruthStoreOption tso,
+ const void *truth_data,
+ size_t truth_data_size)
+{
+ struct TruthStoreState *tss;
+
+ tss = GNUNET_new (struct TruthStoreState);
+ tss->truth_data = truth_data;
+ tss->http_status = http_status;
+ tss->tsopt = tso;
+ tss->anastasis_url = anastasis_url;
+ tss->prev_upload = prev_upload;
+
+ struct TALER_TESTING_Command cmd = {
+ .cls = tss,
+ .label = label,
+ .run = &truth_store_run,
+ .cleanup = &truth_store_cleanup,
+ .traits = &truth_store_traits
+ };
+
+ return cmd;
+}
\ No newline at end of file
diff --git a/src/stasis/Datenbank-Schema.xml b/src/stasis/Datenbank-Schema.xml
index 127ee0e..3ee4c6c 100644
--- a/src/stasis/Datenbank-Schema.xml
+++ b/src/stasis/Datenbank-Schema.xml
@@ -1 +1 @@
-<mxfile host="www.draw.io" modified="2019-10-03T08:37:23.905Z"
agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101
Firefox/69.0" etag="6BT0RyXbdwZ2IaOkdOjM" version="12.0.2" pages="1"><diagram
id="UF0pCA7TQTvobU7b0bed"
name="Seite-1">7V1bb+MoFP41kXYfduRrLo9J2rlop6uqTXdnniJq0wSNYyxMpsn8+gUbEjvYGzfxrVraqgpXA+f7DocDOAN7vtl9IiBa32EfBgPL8HcD+2ZgWeORy/7ziH0aMXInacSKID+NMo8Rj+gXFJGGiN0iH8a5jBTjgKIoH+nhMIQezcUBQvBrPtsLDvJPjcAKKhGPHgjU2H+QT9ci1hxOjgmfIVqtxaPH1ihN2ACZWfQkXgMfv
[...]
\ No newline at end of file
+<mxfile host="www.draw.io" modified="2020-01-21T14:38:26.927Z"
agent="Mozilla/5.0 (X11; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0"
etag="20YrHRmXfagVxyJTmXK6" version="12.5.5"><diagram id="UF0pCA7TQTvobU7b0bed"
name="Seite-1">7V1bb6M4FP41kXYfdsQ1SR+TTOeina6qNp2deYpccBNrCEbGmSbz69cGO0AMHVouIVq3lRpfwT7f+Xx8fCAje7HdfyQg2txgHwYjy/D3I/v9yLJMxzTYP55zSHMmYyfNWBPki0pZxj36BUWmaLfeIR/GhYoU44CiqJjp4TCEHi3kAULwc7HaEw6KV43AGioZ9x4I1Nx/kU83ItccX2UFnyBab8Slp9YkLdgCWVmMJN4AHz/nsuzrkb0gGNP003a/g
[...]
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
address@hidden.