merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit 590e22e63779f18c2dc79f1226439e248d9d11e6
parent 867b0b85d31d8eeba341acd262913096e3bf4021
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat, 27 Dec 2025 12:59:09 +0100

basic REST API for product groups

Diffstat:
Msrc/backend/Makefile.am | 38++++++++++++++++++++++++++++++++++++++
Msrc/backend/taler-merchant-httpd.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-delete-group-ID.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-delete-group-ID.h | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-delete-report-ID.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-delete-report-ID.h | 40++++++++++++++++++++++++++++++++++++++++
Dsrc/backend/taler-merchant-httpd_private-delete-report.c | 76----------------------------------------------------------------------------
Dsrc/backend/taler-merchant-httpd_private-delete-report.h | 40----------------------------------------
Asrc/backend/taler-merchant-httpd_private-get-groups.c | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-get-groups.h | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-patch-group-ID.c | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-patch-group-ID.h | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-post-groups.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_private-post-groups.h | 41+++++++++++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_insert_product_group.c | 1+
Msrc/include/taler_merchantdb_plugin.h | 3++-
16 files changed, 788 insertions(+), 117 deletions(-)

diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am @@ -22,6 +22,7 @@ bin_PROGRAMS = \ taler-merchant-httpd \ taler-merchant-kyccheck \ taler-merchant-reconciliation \ + taler-merchant-report-generator \ taler-merchant-webhook \ taler-merchant-wirewatch @@ -234,6 +235,24 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_qr.h \ taler-merchant-httpd_spa.c \ taler-merchant-httpd_spa.h \ + taler-merchant-httpd_private-delete-report-ID.c \ + taler-merchant-httpd_private-delete-report-ID.h \ + taler-merchant-httpd_private-get-report-ID.c \ + taler-merchant-httpd_private-get-report-ID.h \ + taler-merchant-httpd_private-get-reports.c \ + taler-merchant-httpd_private-get-reports.h \ + taler-merchant-httpd_private-patch-report-ID.c \ + taler-merchant-httpd_private-patch-report-ID.h \ + taler-merchant-httpd_private-post-reports.c \ + taler-merchant-httpd_private-post-reports.h \ + taler-merchant-httpd_private-delete-group-ID.c \ + taler-merchant-httpd_private-delete-group-ID.h \ + taler-merchant-httpd_private-get-groups.c \ + taler-merchant-httpd_private-get-groups.h \ + taler-merchant-httpd_private-patch-group-ID.c \ + taler-merchant-httpd_private-patch-group-ID.h \ + taler-merchant-httpd_private-post-groups.c \ + taler-merchant-httpd_private-post-groups.h \ taler-merchant-httpd_statics.c \ taler-merchant-httpd_statics.h @@ -313,6 +332,25 @@ taler_merchant_reconciliation_CFLAGS = \ $(AM_CFLAGS) +taler_merchant_report_generator_SOURCES = \ + taler-merchant-report-generator.c +taler_merchant_report_generator_LDADD = \ + $(top_builddir)/src/backenddb/libtalermerchantdb.la \ + $(top_builddir)/src/util/libtalermerchantutil.la \ + -ltalerexchange \ + -ltalerjson \ + -ltalerutil \ + -ltalerpq \ + -lgnunetpq \ + -lgnunetjson \ + -lgnunetcurl \ + -lgnunetutil \ + -lcurl \ + $(XLIB) +taler_merchant_report_generator_CFLAGS = \ + $(AM_CFLAGS) + + taler_merchant_webhook_SOURCES = \ taler-merchant-webhook.c diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c @@ -112,6 +112,15 @@ #include "taler-merchant-httpd_spa.h" #include "taler-merchant-httpd_statics.h" #include "taler-merchant-httpd_terms.h" +#include "taler-merchant-httpd_private-delete-report-ID.h" +#include "taler-merchant-httpd_private-get-report-ID.h" +#include "taler-merchant-httpd_private-get-reports.h" +#include "taler-merchant-httpd_private-patch-report-ID.h" +#include "taler-merchant-httpd_private-post-reports.h" +#include "taler-merchant-httpd_private-get-groups.h" +#include "taler-merchant-httpd_private-post-groups.h" +#include "taler-merchant-httpd_private-patch-group-ID.h" +#include "taler-merchant-httpd_private-delete-group-ID.h" #ifdef HAVE_DONAU_DONAU_SERVICE_H #include "taler-merchant-httpd_private-get-donau-instances.h" @@ -2158,6 +2167,70 @@ url_handler (void *cls, /* Body should be pretty small. */ .max_upload = 1024 * 1024 }, + + /* Reports endpoints */ + { + .url_prefix = "reports", + .method = MHD_HTTP_METHOD_GET, + .permission = "reports-read", + .handler = &TMH_private_get_reports, + }, + { + .url_prefix = "reports", + .method = MHD_HTTP_METHOD_POST, + .permission = "reports-write", + .handler = &TMH_private_post_reports, + }, + { + .url_prefix = "reports", + .method = MHD_HTTP_METHOD_GET, + .handler = &TMH_private_get_report, + .permission = "reports-read", + .have_id_segment = true, + }, + { + .url_prefix = "reports", + .method = MHD_HTTP_METHOD_PATCH, + .handler = &TMH_private_patch_report, + .permission = "reports-write", + .have_id_segment = true, + }, + { + .url_prefix = "reports", + .method = MHD_HTTP_METHOD_DELETE, + .handler = &TMH_private_delete_report, + .permission = "reports-write", + .have_id_segment = true, + }, + + /* Groups endpoints */ + { + .url_prefix = "groups", + .method = MHD_HTTP_METHOD_GET, + .permission = "groups-read", + .handler = &TMH_private_get_groups, + }, + { + .url_prefix = "groups", + .method = MHD_HTTP_METHOD_POST, + .permission = "groups-write", + .handler = &TMH_private_post_groups, + }, + { + .url_prefix = "groups", + .method = MHD_HTTP_METHOD_PATCH, + .handler = &TMH_private_patch_group, + .permission = "groups-write", + .have_id_segment = true, + }, + { + .url_prefix = "groups", + .method = MHD_HTTP_METHOD_DELETE, + .handler = &TMH_private_delete_group, + .permission = "groups-write", + .have_id_segment = true, + }, + { .url_prefix = "*", .method = MHD_HTTP_METHOD_OPTIONS, diff --git a/src/backend/taler-merchant-httpd_private-delete-group-ID.c b/src/backend/taler-merchant-httpd_private-delete-group-ID.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-delete-group-ID.c + * @brief implementation of DELETE /private/groups/$GROUP_ID + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-delete-group-ID.h" +#include <taler/taler_json_lib.h> + + +MHD_RESULT +TMH_private_delete_group (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + const char *group_id_str = hc->infix; + unsigned long long group_id; + enum GNUNET_DB_QueryStatus qs; + char dummy; + + (void) rh; + if (1 != sscanf (group_id_str, + "%llu%c", + &group_id, + &dummy)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "group_id"); + } + qs = TMH_db->delete_product_group (TMH_db->cls, + hc->instance->settings.id, + group_id); + + if (qs < 0) + { + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "delete_product_group"); + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_GENERIC_PRODUCT_GROUP_UNKNOWN, + group_id_str); + } + return TALER_MHD_reply_static (connection, + MHD_HTTP_NO_CONTENT, + NULL, + NULL, + 0); +} diff --git a/src/backend/taler-merchant-httpd_private-delete-group-ID.h b/src/backend/taler-merchant-httpd_private-delete-group-ID.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-delete-group-ID.h + * @brief HTTP serving layer for deleting product groups + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_GROUP_ID_H +#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_GROUP_ID_H + +#include "taler-merchant-httpd.h" + +/** + * Handle DELETE /private/groups/$GROUP_ID 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_group (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif diff --git a/src/backend/taler-merchant-httpd_private-delete-report-ID.c b/src/backend/taler-merchant-httpd_private-delete-report-ID.c @@ -0,0 +1,76 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-delete-report-ID.c + * @brief implementation of DELETE /private/reports/$REPORT_ID + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-delete-report-ID.h" +#include <taler/taler_json_lib.h> + + +MHD_RESULT +TMH_private_delete_report (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + const char *report_id_str = hc->infix; + unsigned long long report_id; + enum GNUNET_DB_QueryStatus qs; + char dummy; + + (void) rh; + + if (1 != + sscanf (report_id_str, + "%llu%c", + &report_id, + &dummy)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "report_id"); + } + + qs = TMH_db->delete_report (TMH_db->cls, + hc->instance->settings.id, + (uint64_t) report_id); + if (qs < 0) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "delete_report"); + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_GENERIC_REPORT_UNKNOWN, + report_id_str); + } + return TALER_MHD_reply_static (connection, + MHD_HTTP_NO_CONTENT, + NULL, + NULL, + 0); +} diff --git a/src/backend/taler-merchant-httpd_private-delete-report-ID.h b/src/backend/taler-merchant-httpd_private-delete-report-ID.h @@ -0,0 +1,40 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-delete-report-ID.h + * @brief HTTP serving layer for deleting reports + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_REPORT_ID_H +#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_REPORT_ID_H +#include "taler-merchant-httpd.h" + +/** + * Handle DELETE /private/reports/$REPORT_ID 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_report (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif diff --git a/src/backend/taler-merchant-httpd_private-delete-report.c b/src/backend/taler-merchant-httpd_private-delete-report.c @@ -1,76 +0,0 @@ -/* - This file is part of TALER - (C) 2025 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 Affero General Public License for more - details. - - You should have received a copy of the GNU Affero General Public License - along with TALER; see the file COPYING. If not, see - <http://www.gnu.org/licenses/> -*/ -/** - * @file merchant/backend/taler-merchant-httpd_private-delete-report.c - * @brief implementation of DELETE /private/reports/$REPORT_ID - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler-merchant-httpd_private-delete-report.h" -#include <taler/taler_json_lib.h> - - -MHD_RESULT -TMH_private_delete_report (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc) -{ - const char *report_id_str = hc->infix; - unsigned long long report_id; - enum GNUNET_DB_QueryStatus qs; - char dummy; - - (void) rh; - - if (1 != - sscanf (report_id_str, - "%llu%c", - &report_id, - &dummy)) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "report_id"); - } - - qs = TMH_db->delete_report (TMH_db->cls, - hc->instance->settings.id, - (uint64_t) report_id); - if (qs < 0) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - "delete_report"); - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_MERCHANT_GENERIC_REPORT_UNKNOWN, - report_id_str); - } - return TALER_MHD_reply_static (connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0); -} diff --git a/src/backend/taler-merchant-httpd_private-delete-report.h b/src/backend/taler-merchant-httpd_private-delete-report.h @@ -1,40 +0,0 @@ -/* - This file is part of TALER - (C) 2025 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 Affero General Public License for more - details. - - You should have received a copy of the GNU Affero General Public License - along with TALER; see the file COPYING. If not, see - <http://www.gnu.org/licenses/> -*/ -/** - * @file merchant/backend/taler-merchant-httpd_private-delete-report.h - * @brief HTTP serving layer for deleting reports - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_REPORT_H -#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_REPORT_H -#include "taler-merchant-httpd.h" - -/** - * Handle DELETE /private/reports/$REPORT_ID 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_report (const struct TMH_RequestHandler *rh, - struct MHD_Connection *connection, - struct TMH_HandlerContext *hc); - -#endif diff --git a/src/backend/taler-merchant-httpd_private-get-groups.c b/src/backend/taler-merchant-httpd_private-get-groups.c @@ -0,0 +1,122 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-get-groups.c + * @brief implementation of GET /private/groups + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-get-groups.h" +#include <taler/taler_json_lib.h> + +/** + * Sensible bound on the number of results to return + */ +#define MAX_DELTA 1024 + + +/** + * Callback for listing product groups. + * + * @param cls closure with a `json_t *` + * @param product_group_id unique identifier of the group + * @param group_name name of the group + * @param group_description human-readable description + */ +static void +add_group (void *cls, + uint64_t product_group_id, + const char *group_name, + const char *group_description) +{ + json_t *groups = cls; + json_t *entry; + + entry = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_uint64 ("group_serial", + product_group_id), + GNUNET_JSON_pack_string ("group_name", + group_name), + GNUNET_JSON_pack_string ("description", + group_description)); + GNUNET_assert (NULL != entry); + GNUNET_assert (0 == + json_array_append_new (groups, + entry)); +} + + +MHD_RESULT +TMH_private_get_groups (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + int64_t limit = -20; + uint64_t offset; + json_t *groups; + + (void) rh; + TALER_MHD_parse_request_snumber (connection, + "limit", + &limit); + if ( (-MAX_DELTA > limit) || + (limit > MAX_DELTA) ) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "limit"); + } + if (limit > 0) + offset = 0; + else + offset = INT64_MAX; + TALER_MHD_parse_request_number (connection, + "offset", + &offset); + + groups = json_array (); + GNUNET_assert (NULL != groups); + + { + enum GNUNET_DB_QueryStatus qs; + + qs = TMH_db->select_product_groups (TMH_db->cls, + hc->instance->settings.id, + limit, + offset, + &add_group, + groups); + if (qs < 0) + { + GNUNET_break (0); + json_decref (groups); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "select_product_groups"); + } + } + + return TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_array_steal ("groups", + groups)); +} diff --git a/src/backend/taler-merchant-httpd_private-get-groups.h b/src/backend/taler-merchant-httpd_private-get-groups.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-get-groups.h + * @brief HTTP serving layer for listing product groups + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_GROUPS_H +#define TALER_MERCHANT_HTTPD_PRIVATE_GET_GROUPS_H + +#include "taler-merchant-httpd.h" + +/** + * Handle GET /private/groups 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_groups (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif diff --git a/src/backend/taler-merchant-httpd_private-patch-group-ID.c b/src/backend/taler-merchant-httpd_private-patch-group-ID.c @@ -0,0 +1,110 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-patch-group-ID.c + * @brief implementation of PATCH /private/groups/$GROUP_ID + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-patch-group-ID.h" +#include <taler/taler_json_lib.h> + + +MHD_RESULT +TMH_private_patch_group (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + const char *group_id_str = hc->infix; + unsigned long long group_id; + const char *group_name; + const char *description; + enum GNUNET_DB_QueryStatus qs; + bool conflict; + char dummy; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("group_name", + &group_name), + GNUNET_JSON_spec_string ("description", + &description), + GNUNET_JSON_spec_end () + }; + + (void) rh; + if (1 != sscanf (group_id_str, + "%llu%c", + &group_id, + &dummy)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "group_id"); + } + + { + 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; + } + } + + qs = TMH_db->update_product_group (TMH_db->cls, + hc->instance->settings.id, + (uint64_t) group_id, + group_name, + description, + &conflict); + + if (qs < 0) + { + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "update_product_group"); + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_GENERIC_PRODUCT_GROUP_UNKNOWN, + group_id_str); + } + if (conflict) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_PRODUCT_GROUP_CONFLICTING_NAME, + group_name); + } + return TALER_MHD_reply_static (connection, + MHD_HTTP_NO_CONTENT, + NULL, + NULL, + 0); +} diff --git a/src/backend/taler-merchant-httpd_private-patch-group-ID.h b/src/backend/taler-merchant-httpd_private-patch-group-ID.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-patch-group-ID.h + * @brief HTTP serving layer for updating product groups + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_GROUP_ID_H +#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_GROUP_ID_H + +#include "taler-merchant-httpd.h" + +/** + * Handle PATCH /private/groups/$GROUP_ID 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_group (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif diff --git a/src/backend/taler-merchant-httpd_private-post-groups.c b/src/backend/taler-merchant-httpd_private-post-groups.c @@ -0,0 +1,88 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-post-groups.c + * @brief implementation of POST /private/groups + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-post-groups.h" +#include <taler/taler_json_lib.h> + + +MHD_RESULT +TMH_private_post_groups (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + const char *group_name; + const char *description; + enum GNUNET_DB_QueryStatus qs; + uint64_t group_id; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("group_name", + &group_name), + GNUNET_JSON_spec_string ("description", + &description), + GNUNET_JSON_spec_end () + }; + + (void) rh; + { + 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; + } + } + + qs = TMH_db->insert_product_group (TMH_db->cls, + hc->instance->settings.id, + group_name, + description, + &group_id); + if (qs < 0) + { + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "insert_product_group"); + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + /* Zero will be returned on conflict */ + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_PRODUCT_GROUP_CONFLICTING_NAME, + group_name); + } + + return TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_uint64 ("group_serial_id", + group_id)); +} diff --git a/src/backend/taler-merchant-httpd_private-post-groups.h b/src/backend/taler-merchant-httpd_private-post-groups.h @@ -0,0 +1,41 @@ +/* + This file is part of TALER + (C) 2025 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 Affero General Public License for more + details. + + You should have received a copy of the GNU Affero General Public License + along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant/backend/taler-merchant-httpd_private-post-groups.h + * @brief HTTP serving layer for creating product groups + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_GROUPS_H +#define TALER_MERCHANT_HTTPD_PRIVATE_POST_GROUPS_H + +#include "taler-merchant-httpd.h" + +/** + * Handle POST /private/groups 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_post_groups (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif diff --git a/src/backenddb/pg_insert_product_group.c b/src/backenddb/pg_insert_product_group.c @@ -57,6 +57,7 @@ TMH_PG_insert_product_group ( " SELECT merchant_serial, $2, $3" " FROM merchant_instances" " WHERE merchant_id=$1" + " ON CONFLICT DO NOTHING" " RETURNING product_group_serial"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h @@ -5244,7 +5244,8 @@ struct TALER_MERCHANTDB_Plugin * @param name set to name of the group * @param description set to description of the group * @param[out] product_group_id serial number of the new group - * @return database result code + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + * on conflict (@a name already in use at @a instance_id). */ enum GNUNET_DB_QueryStatus (*insert_product_group)(