summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorChristian Blättler <blatc2@bfh.ch>2023-11-21 08:06:00 +0100
committerChristian Grothoff <grothoff@gnunet.org>2023-12-23 00:08:57 +0800
commit094327bc906cdeced19a52c86dc0725aad773997 (patch)
treeb459428305452298749cb90438c7a734a64230d1 /src/backend
parent20632c6a2e293a9799114497d63180a105b37065 (diff)
downloadmerchant-094327bc906cdeced19a52c86dc0725aad773997.tar.gz
merchant-094327bc906cdeced19a52c86dc0725aad773997.tar.bz2
merchant-094327bc906cdeced19a52c86dc0725aad773997.zip
POST /tokenfamilies endpoint
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/Makefile.am10
-rw-r--r--src/backend/taler-merchant-httpd.c41
-rw-r--r--src/backend/taler-merchant-httpd_private-delete-token-families-SLUG.c73
-rw-r--r--src/backend/taler-merchant-httpd_private-delete-token-families-SLUG.h41
-rw-r--r--src/backend/taler-merchant-httpd_private-get-templates.c3
-rw-r--r--src/backend/taler-merchant-httpd_private-get-token-families-SLUG.c104
-rw-r--r--src/backend/taler-merchant-httpd_private-get-token-families-SLUG.h41
-rw-r--r--src/backend/taler-merchant-httpd_private-get-token-families.c85
-rw-r--r--src/backend/taler-merchant-httpd_private-get-token-families.h41
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-products-ID.h2
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-token-families-SLUG.c158
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-token-families-SLUG.h43
-rw-r--r--src/backend/taler-merchant-httpd_private-post-token-families.c229
-rw-r--r--src/backend/taler-merchant-httpd_private-post-token-families.h43
14 files changed, 911 insertions, 3 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 4a25785c..7978258d 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -53,6 +53,8 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-delete-reserves-ID.h \
taler-merchant-httpd_private-delete-templates-ID.c \
taler-merchant-httpd_private-delete-templates-ID.h \
+ taler-merchant-httpd_private-delete-token-families-SLUG.c \
+ taler-merchant-httpd_private-delete-token-families-SLUG.h \
taler-merchant-httpd_private-delete-transfers-ID.c \
taler-merchant-httpd_private-delete-transfers-ID.h \
taler-merchant-httpd_private-delete-webhooks-ID.c \
@@ -89,6 +91,10 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-get-templates.h \
taler-merchant-httpd_private-get-templates-ID.c \
taler-merchant-httpd_private-get-templates-ID.h \
+ taler-merchant-httpd_private-get-token-families.c \
+ taler-merchant-httpd_private-get-token-families.h \
+ taler-merchant-httpd_private-get-token-families-SLUG.c \
+ taler-merchant-httpd_private-get-token-families-SLUG.h \
taler-merchant-httpd_private-get-webhooks.c \
taler-merchant-httpd_private-get-webhooks.h \
taler-merchant-httpd_private-get-webhooks-ID.c \
@@ -105,6 +111,8 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-patch-products-ID.h \
taler-merchant-httpd_private-patch-templates-ID.c \
taler-merchant-httpd_private-patch-templates-ID.h \
+ taler-merchant-httpd_private-patch-token-families-SLUG.c \
+ taler-merchant-httpd_private-patch-token-families-SLUG.h \
taler-merchant-httpd_private-patch-webhooks-ID.c \
taler-merchant-httpd_private-patch-webhooks-ID.h \
taler-merchant-httpd_private-post-account.c \
@@ -131,6 +139,8 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h \
taler-merchant-httpd_private-post-templates.c \
taler-merchant-httpd_private-post-templates.h \
+ taler-merchant-httpd_private-post-token-families.c \
+ taler-merchant-httpd_private-post-token-families.h \
taler-merchant-httpd_private-post-transfers.c \
taler-merchant-httpd_private-post-transfers.h \
taler-merchant-httpd_private-post-webhooks.c \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index 3b78677a..83390887 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -41,6 +41,7 @@
#include "taler-merchant-httpd_private-delete-otp-devices-ID.h"
#include "taler-merchant-httpd_private-delete-reserves-ID.h"
#include "taler-merchant-httpd_private-delete-templates-ID.h"
+#include "taler-merchant-httpd_private-delete-token-families-SLUG.h"
#include "taler-merchant-httpd_private-delete-transfers-ID.h"
#include "taler-merchant-httpd_private-delete-webhooks-ID.h"
#include "taler-merchant-httpd_private-get-accounts.h"
@@ -60,6 +61,8 @@
#include "taler-merchant-httpd_private-get-rewards.h"
#include "taler-merchant-httpd_private-get-templates.h"
#include "taler-merchant-httpd_private-get-templates-ID.h"
+#include "taler-merchant-httpd_private-get-token-families.h"
+#include "taler-merchant-httpd_private-get-token-families-SLUG.h"
#include "taler-merchant-httpd_private-get-transfers.h"
#include "taler-merchant-httpd_private-get-webhooks.h"
#include "taler-merchant-httpd_private-get-webhooks-ID.h"
@@ -69,6 +72,7 @@
#include "taler-merchant-httpd_private-patch-otp-devices-ID.h"
#include "taler-merchant-httpd_private-patch-products-ID.h"
#include "taler-merchant-httpd_private-patch-templates-ID.h"
+#include "taler-merchant-httpd_private-patch-token-families-SLUG.h"
#include "taler-merchant-httpd_private-patch-webhooks-ID.h"
#include "taler-merchant-httpd_private-post-account.h"
#include "taler-merchant-httpd_private-post-instances.h"
@@ -82,6 +86,7 @@
#include "taler-merchant-httpd_private-post-reserves.h"
#include "taler-merchant-httpd_private-post-reserves-ID-authorize-reward.h"
#include "taler-merchant-httpd_private-post-templates.h"
+#include "taler-merchant-httpd_private-post-token-families.h"
#include "taler-merchant-httpd_private-post-transfers.h"
#include "taler-merchant-httpd_private-post-webhooks.h"
#include "taler-merchant-httpd_post-orders-ID-abort.h"
@@ -1300,6 +1305,42 @@ url_handler (void *cls,
.method = MHD_HTTP_METHOD_DELETE,
.handler = &TMH_private_delete_instances_ID_token,
},
+ /* GET /tokenfamilies: */
+ {
+ .url_prefix = "/tokenfamilies",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler = &TMH_private_get_tokenfamilies
+ },
+ /* POST /tokenfamilies: */
+ {
+ .url_prefix = "/tokenfamilies",
+ .method = MHD_HTTP_METHOD_POST,
+ .handler = &TMH_private_post_token_families
+ },
+ /* GET /tokenfamilies/$SLUG/: */
+ {
+ .url_prefix = "/tokenfamilies/",
+ .method = MHD_HTTP_METHOD_GET,
+ .have_id_segment = true,
+ .allow_deleted_instance = true,
+ .handler = &TMH_private_get_tokenfamilies_SLUG
+ },
+ /* DELETE /tokenfamilies/$SLUG/: */
+ {
+ .url_prefix = "/tokenfamilies/",
+ .method = MHD_HTTP_METHOD_DELETE,
+ .have_id_segment = true,
+ .allow_deleted_instance = true,
+ .handler = &TMH_private_delete_token_families_SLUG
+ },
+ /* PATCH /tokenfamilies/$SLUG/: */
+ {
+ .url_prefix = "/tokenfamilies/",
+ .method = MHD_HTTP_METHOD_PATCH,
+ .have_id_segment = true,
+ .allow_deleted_instance = true,
+ .handler = &TMH_private_patch_token_family_SLUG,
+ },
{
.url_prefix = NULL
}
diff --git a/src/backend/taler-merchant-httpd_private-delete-token-families-SLUG.c b/src/backend/taler-merchant-httpd_private-delete-token-families-SLUG.c
new file mode 100644
index 00000000..3418b795
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-delete-token-families-SLUG.c
@@ -0,0 +1,73 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-merchant-httpd_private-delete-token-families-SLUG.c
+ * @brief implement DELETE /tokenfamilies/$SLUG
+ * @author Christian Blättler
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-delete-token-families-SLUG.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * Handle a DELETE "/tokenfamilies/$SLUG" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_delete_token_families_SLUG (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ enum GNUNET_DB_QueryStatus qs;
+
+ (void) rh;
+ GNUNET_assert (NULL != mi);
+ GNUNET_assert (NULL != hc->infix);
+ qs = TMH_db->delete_token_family (TMH_db->cls,
+ mi->settings.id,
+ hc->infix);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "delete_token_family");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "delete_token_family (soft)");
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return TALER_MHD_reply_static (connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
+ }
+ GNUNET_assert (0);
+ return MHD_NO;
+}
+
+
+/* end of taler-merchant-httpd_private-delete-token-families-SLUG.c */
diff --git a/src/backend/taler-merchant-httpd_private-delete-token-families-SLUG.h b/src/backend/taler-merchant-httpd_private-delete-token-families-SLUG.h
new file mode 100644
index 00000000..e8b72fc6
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-delete-token-families-SLUG.h
@@ -0,0 +1,41 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-merchant-httpd_private-delete-token-families-SLUG.h
+ * @brief implement DELETE /tokenfamilies/$SLUG/
+ * @author Christian Blättler
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_TOKEN_FAMILIES_SLUG_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_TOKEN_FAMILIES_SLUG_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a DELETE "/tokenfamilies/$SLUG" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_delete_token_families_SLUG (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+/* end of taler-merchant-httpd_private-delete-token-families-SLUG.h */
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-get-templates.c b/src/backend/taler-merchant-httpd_private-get-templates.c
index e59e47c9..d0bec884 100644
--- a/src/backend/taler-merchant-httpd_private-get-templates.c
+++ b/src/backend/taler-merchant-httpd_private-get-templates.c
@@ -40,8 +40,7 @@ add_template (void *cls,
json_array_append_new (
pa,
GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("template_id",
- template_id),
+ GNUNET_JSON_pack_string ("template_id", template_id),
GNUNET_JSON_pack_string ("template_description",
template_description))));
}
diff --git a/src/backend/taler-merchant-httpd_private-get-token-families-SLUG.c b/src/backend/taler-merchant-httpd_private-get-token-families-SLUG.c
new file mode 100644
index 00000000..d31884da
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-token-families-SLUG.c
@@ -0,0 +1,104 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-merchant-httpd_private-get-token-families-SLUG.c
+ * @brief implement GET /tokenfamilies/$SLUG/
+ * @author Christian Blättler
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-get-token-families-SLUG.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * Handle a GET "/tokenfamilies/$SLUG" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_get_tokenfamilies_SLUG (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ struct TALER_MERCHANTDB_TokenFamilyDetails details = { 0 };
+ enum GNUNET_DB_QueryStatus status;
+
+ GNUNET_assert (NULL != mi);
+ status = TMH_db->lookup_token_family (TMH_db->cls,
+ mi->settings.id,
+ hc->infix,
+ &details);
+ if (0 > status)
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "lookup_token_family");
+ }
+ if (0 == status)
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_PRODUCT_UNKNOWN,
+ hc->infix);
+ }
+ // TODO: Why is this block here? Limiting variable lifetime?
+ {
+ char *kind = NULL;
+ if (TALER_MERCHANTDB_TFK_Subscription == details.kind)
+ {
+ kind = GNUNET_strdup ("subscription");
+ }
+ else if (TALER_MERCHANTDB_TFK_Discount == details.kind)
+ {
+ kind = GNUNET_strdup ("discount");
+ }
+ else
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ // TODO: What error code to use here?
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "invalid_token_family_kind");
+ }
+
+ MHD_RESULT result;
+
+ result = TALER_MHD_REPLY_JSON_PACK (
+ connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_string ("name", details.name),
+ GNUNET_JSON_pack_string ("description", details.description),
+ GNUNET_JSON_pack_object_steal ("description_i18n", details.description_i18n),
+ GNUNET_JSON_pack_timestamp ("valid_after", details.valid_after),
+ GNUNET_JSON_pack_timestamp ("valid_before", details.valid_before),
+ GNUNET_JSON_pack_time_rel ("duration", details.duration),
+ GNUNET_JSON_pack_string ("kind", kind)
+ );
+
+ GNUNET_free (details.name);
+ GNUNET_free (details.description);
+ return result;
+ }
+}
+
+
+/* end of taler-merchant-httpd_private-get-products-SLUG.c */
diff --git a/src/backend/taler-merchant-httpd_private-get-token-families-SLUG.h b/src/backend/taler-merchant-httpd_private-get-token-families-SLUG.h
new file mode 100644
index 00000000..a7b02d8f
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-token-families-SLUG.h
@@ -0,0 +1,41 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-merchant-httpd_private-get-token-families-SLUG.h
+ * @brief implement GET /tokenfamilies/$SLUG/
+ * @author Christian Blättler
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_TOKENFAMILIES_SLUG_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_GET_TOKENFAMILIES_SLUG_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a GET "/tokenfamilies/$SLUG" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_get_tokenfamilies_SLUG (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+/* end of taler-merchant-httpd_private-get-token-families-SLUG.h */
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-get-token-families.c b/src/backend/taler-merchant-httpd_private-get-token-families.c
new file mode 100644
index 00000000..031edd90
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-token-families.c
@@ -0,0 +1,85 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-merchant-httpd_private-get-token-families.c
+ * @brief implement GET /tokenfamilies
+ * @author Christian Blättler
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-get-token-families.h"
+
+
+
+/**
+ * Add token family details to our JSON array.
+ *
+ * @param cls a `json_t *` JSON array to build
+ * @param slug slug of the token family
+ * @param name name of the token family
+ * @param start_time start time of the token family's validity period
+ * @param expiration end time of the token family's validity period
+ */
+static void
+add_token_family (void *cls,
+ const char *slug,
+ const char *name,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Timestamp expiration)
+{
+ json_t *pa = cls;
+
+ GNUNET_assert (0 ==
+ json_array_append_new (
+ pa,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("slug", slug),
+ GNUNET_JSON_pack_string ("name", name),
+ GNUNET_JSON_pack_timestamp ("start_time", start_time),
+ GNUNET_JSON_pack_timestamp ("expiration", expiration))));
+}
+
+
+MHD_RESULT
+TMH_private_get_tokenfamilies (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ json_t *families;
+ enum GNUNET_DB_QueryStatus qs;
+
+ families = json_array ();
+ GNUNET_assert (NULL != families);
+ qs = TMH_db->lookup_token_families (TMH_db->cls,
+ hc->instance->settings.id,
+ &add_token_family,
+ families);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ json_decref (families);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
+ }
+ return TALER_MHD_REPLY_JSON_PACK (connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_array_steal ("token_families",
+ families));
+}
+
+
+/* end of taler-merchant-httpd_private-get-token-families.c */
diff --git a/src/backend/taler-merchant-httpd_private-get-token-families.h b/src/backend/taler-merchant-httpd_private-get-token-families.h
new file mode 100644
index 00000000..a02a42b0
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-get-token-families.h
@@ -0,0 +1,41 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file taler-merchant-httpd_private-get-token-families.h
+ * @brief implement GET /tokenfamilies
+ * @author Christian Blättler
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_TOKENFAMILIES_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_GET_TOKENFAMILIES_H
+
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a GET "/tokenfamilies" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_get_tokenfamilies (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+/* end of taler-merchant-httpd_private-get-token-families.h */
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-patch-products-ID.h b/src/backend/taler-merchant-httpd_private-patch-products-ID.h
index e7f8fcfd..9ce0a7ae 100644
--- a/src/backend/taler-merchant-httpd_private-patch-products-ID.h
+++ b/src/backend/taler-merchant-httpd_private-patch-products-ID.h
@@ -19,7 +19,7 @@
/**
* @file taler-merchant-httpd_private-patch-products-ID.h
- * @brief implementing POST /products request handling
+ * @brief implementing PATCH /products/$ID request handling
* @author Christian Grothoff
*/
#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_PRODUCTS_ID_H
diff --git a/src/backend/taler-merchant-httpd_private-patch-token-families-SLUG.c b/src/backend/taler-merchant-httpd_private-patch-token-families-SLUG.c
new file mode 100644
index 00000000..a5fef59d
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-patch-token-families-SLUG.c
@@ -0,0 +1,158 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation; either version 3,
+ or (at your option) any later version.
+
+ TALER 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 TALER; see the file COPYING. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_private-patch-token-families-SLUG.c
+ * @brief implementing PATCH /tokenfamilies/$SLUG request handling
+ * @author Christian Blättler
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-patch-token-families-SLUG.h"
+#include "taler-merchant-httpd_helper.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * How often do we retry the simple INSERT database transaction?
+ */
+#define MAX_RETRIES 3
+
+/**
+ * Handle a PATCH "/tokenfamilies/$slug" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_patch_token_family_SLUG (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ const char *slug = hc->infix;
+ struct TALER_MERCHANTDB_TokenFamilyDetails details = {0};
+ int64_t total_stock;
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("name",
+ (const char **) &details.name),
+ GNUNET_JSON_spec_string ("description",
+ (const char **) &details.description),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_json ("description_i18n",
+ &details.description_i18n),
+ NULL),
+ GNUNET_JSON_spec_timestamp ("valid_after",
+ &details.valid_after),
+ GNUNET_JSON_spec_timestamp ("valid_before",
+ &details.valid_before),
+ GNUNET_JSON_spec_relative_time ("duration",
+ &details.duration),
+ GNUNET_JSON_spec_end ()
+ };
+
+ GNUNET_assert (NULL != mi);
+ GNUNET_assert (NULL != slug);
+ {
+ enum GNUNET_GenericReturnValue res;
+
+ res = TALER_MHD_parse_json_data (connection,
+ hc->request_body,
+ spec);
+ if (GNUNET_OK != res)
+ return (GNUNET_NO == res)
+ ? MHD_YES
+ : MHD_NO;
+ }
+
+ struct GNUNET_TIME_Relative validity = GNUNET_TIME_absolute_get_difference(
+ details.valid_after.abs_time,
+ details.valid_before.abs_time);
+
+ // Check if start_time is before valid_before
+ if (0 == validity.rel_value_us)
+ {
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "invalid_validity_duration");
+ }
+
+ if (NULL == details.description_i18n)
+ details.description_i18n = json_object ();
+
+ if (! TALER_JSON_check_i18n (details.description_i18n))
+ {
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "description_i18n");
+ }
+
+ qs = TMH_db->update_token_family (TMH_db->cls,
+ mi->settings.id,
+ slug,
+ &details);
+ {
+ MHD_RESULT ret = MHD_NO;
+
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ NULL);
+ break;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "unexpected serialization problem");
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ // TODO: Add error code for token family not found
+ ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ 0,
+ slug);
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ ret = TALER_MHD_reply_static (connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
+ break;
+ }
+ GNUNET_JSON_parse_free (spec);
+ return ret;
+ }
+}
+
+
+/* end of taler-merchant-httpd_private-patch-token-families-SLUG.c */
diff --git a/src/backend/taler-merchant-httpd_private-patch-token-families-SLUG.h b/src/backend/taler-merchant-httpd_private-patch-token-families-SLUG.h
new file mode 100644
index 00000000..87ad86b3
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-patch-token-families-SLUG.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation; either version 3,
+ or (at your option) any later version.
+
+ TALER 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 TALER; see the file COPYING. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_private-patch-token-families-SLUG.h
+ * @brief implementing PATCH /tokenfamilies/$SLUG request handling
+ * @author Christian Blättler
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_TOKEN_FAMILIES_SLUG_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_TOKEN_FAMILIES_SLUG_H
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Handle a PATCH "/tokenfamilies/$slug" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_patch_token_family_SLUG (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+#endif
diff --git a/src/backend/taler-merchant-httpd_private-post-token-families.c b/src/backend/taler-merchant-httpd_private-post-token-families.c
new file mode 100644
index 00000000..6ff25942
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-post-token-families.c
@@ -0,0 +1,229 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation; either version 3,
+ or (at your option) any later version.
+
+ TALER 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 TALER; see the file COPYING. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_private-post-token-families.c
+ * @brief implementing POST /tokenfamilies request handling
+ * @author Christian Blättler
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-post-token-families.h"
+#include "taler-merchant-httpd_helper.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * How often do we retry the simple INSERT database transaction?
+ */
+#define MAX_RETRIES 3
+
+
+/**
+ * Check if the two token families are identical.
+ *
+ * @param tf1 token family to compare
+ * @param tf2 other token family to compare
+ * @return true if they are 'equal', false if not
+ */
+static bool
+token_families_equal (const struct TALER_MERCHANTDB_TokenFamilyDetails *tf1,
+ const struct TALER_MERCHANTDB_TokenFamilyDetails *tf2)
+{
+ return ( (0 == strcmp (tf1->slug,
+ tf2->slug)) &&
+ (0 == strcmp (tf1->name,
+ tf2->name)) &&
+ (0 == strcmp (tf1->description,
+ tf2->description)) &&
+ (1 == json_equal (tf1->description_i18n,
+ tf2->description_i18n)) &&
+ (GNUNET_TIME_timestamp_cmp (tf1->valid_after,
+ ==,
+ tf2->valid_after)) &&
+ (GNUNET_TIME_timestamp_cmp (tf1->valid_before,
+ ==,
+ tf2->valid_before)) &&
+ (GNUNET_TIME_relative_cmp (tf1->duration,
+ ==,
+ tf2->duration)) &&
+ (tf1->kind == tf2->kind) );
+}
+
+
+MHD_RESULT
+TMH_private_post_token_families (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
+{
+ struct TMH_MerchantInstance *mi = hc->instance;
+ struct TALER_MERCHANTDB_TokenFamilyDetails details = { 0 };
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("slug",
+ (const char **) &details.slug),
+ GNUNET_JSON_spec_string ("name",
+ (const char **) &details.name),
+ GNUNET_JSON_spec_string ("description",
+ (const char **) &details.description),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_json ("description_i18n",
+ &details.description_i18n),
+ NULL),
+ GNUNET_JSON_spec_uint32("kind", &details.kind),
+ GNUNET_JSON_spec_timestamp ("valid_after",
+ &details.valid_after),
+ GNUNET_JSON_spec_timestamp ("valid_before",
+ &details.valid_before),
+ GNUNET_JSON_spec_relative_time ("duration",
+ &details.duration),
+ GNUNET_JSON_spec_end ()
+ };
+
+ GNUNET_assert (NULL != mi);
+ {
+ enum GNUNET_GenericReturnValue res;
+
+ res = TALER_MHD_parse_json_data (connection,
+ hc->request_body,
+ spec);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_break_op (0);
+ return (GNUNET_NO == res)
+ ? MHD_YES
+ : MHD_NO;
+ }
+ }
+
+ if (NULL == details.description_i18n)
+ details.description_i18n = json_object ();
+
+ if (! TALER_JSON_check_i18n (details.description_i18n))
+ {
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "description_i18n");
+ }
+
+
+ /* finally, interact with DB until no serialization error */
+ for (unsigned int i = 0; i<MAX_RETRIES; i++)
+ {
+ /* Test if a token family of this id is known */
+ struct TALER_MERCHANTDB_TokenFamilyDetails existing;
+
+ if (GNUNET_OK !=
+ TMH_db->start (TMH_db->cls,
+ "/post tokenfamilies"))
+ {
+ GNUNET_break (0);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_START_FAILED,
+ NULL);
+ }
+ qs = TMH_db->lookup_token_family (TMH_db->cls,
+ mi->settings.id,
+ details.slug,
+ &existing);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ /* Clean up and fail hard */
+ GNUNET_break (0);
+ TMH_db->rollback (TMH_db->cls);
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ /* restart transaction */
+ goto retry;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* Good, we can proceed! */
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* idempotency check: is existing == details? */
+ {
+ bool eq;
+
+ eq = token_families_equal (&details,
+ &existing);
+ TALER_MERCHANTDB_token_family_details_free (&existing);
+ TMH_db->rollback (TMH_db->cls);
+ GNUNET_JSON_parse_free (spec);
+ return eq
+ ? TALER_MHD_reply_static (connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0)
+ // TODO: Use proper error code
+ : TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_CONFLICT,
+ 0,
+ details.slug);
+ }
+ } /* end switch (qs) */
+
+ qs = TMH_db->insert_token_family (TMH_db->cls,
+ mi->settings.id,
+ details.slug,
+ &details);
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ {
+ TMH_db->rollback (TMH_db->cls);
+ break;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ qs = TMH_db->commit (TMH_db->cls);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
+retry:
+ GNUNET_assert (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ TMH_db->rollback (TMH_db->cls);
+ } /* for RETRIES loop */
+ GNUNET_JSON_parse_free (spec);
+ if (qs < 0)
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ ? TALER_EC_GENERIC_DB_SOFT_FAILURE
+ : TALER_EC_GENERIC_DB_COMMIT_FAILED,
+ NULL);
+ }
+ return TALER_MHD_reply_static (connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
+}
+
+
+/* end of taler-merchant-httpd_private-post-token-families.c */
diff --git a/src/backend/taler-merchant-httpd_private-post-token-families.h b/src/backend/taler-merchant-httpd_private-post-token-families.h
new file mode 100644
index 00000000..ada1c7c9
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-post-token-families.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of TALER
+ (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation; either version 3,
+ or (at your option) any later version.
+
+ TALER 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 TALER; see the file COPYING. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file taler-merchant-httpd_private-post-token-families.h
+ * @brief implementing POST /tokenfamilies request handling
+ * @author Christian Blättler
+ */
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_TOKEN_FAMILIES_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_POST_TOKEN_FAMILIES_H
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Create a new token family.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_post_token_families (const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc);
+
+#endif