diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-05-25 21:39:57 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-05-25 21:39:57 +0200 |
commit | 3da8f0416e8a3f449db34d54dd4c3f359471bb7e (patch) | |
tree | c2c3a4f06d13fdbf798ae989c5514c340a2d6b41 | |
parent | 6f5a1cd3e657e7c41fdd9431a6eca83cc500348e (diff) |
start on implementing protocol v16
27 files changed, 1640 insertions, 27 deletions
diff --git a/src/backend/taler-merchant-httpd_private-delete-categories-ID.c b/src/backend/taler-merchant-httpd_private-delete-categories-ID.c new file mode 100644 index 00000000..47aab5a0 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-delete-categories-ID.c @@ -0,0 +1,92 @@ +/* + This file is part of TALER + (C) 2024 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-categories-ID.c + * @brief implement DELETE /private/categories/$ID + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-delete-categories-ID.h" +#include <taler/taler_json_lib.h> + + +/** + * Handle a DELETE "/categories/$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_categories_ID ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + struct TMH_MerchantInstance *mi = hc->instance; + enum GNUNET_DB_QueryStatus qs; + unsigned long long cnum; + char dummy; + + (void) rh; + GNUNET_assert (NULL != mi); + GNUNET_assert (NULL != hc->infix); + if (1 != sscanf (hc->infix, + "%llu%d", + &cnum, + &dummy)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "category_id must be a number"); + } + qs = TMH_db->delete_category (TMH_db->cls, + mi->settings.id, + cnum); + 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_category"); + 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_category"); + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_GENERIC_CATEGORY_UNKNOWN, + hc->infix); + 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-categories-ID.c */ diff --git a/src/backend/taler-merchant-httpd_private-delete-categories-ID.h b/src/backend/taler-merchant-httpd_private-delete-categories-ID.h new file mode 100644 index 00000000..b17eed49 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-delete-categories-ID.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + (C) 2024 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-categories-ID.h + * @brief implement DELETE /private/categories/$ID/ + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_DELETE_CATEGORIES_ID_H +#define TALER_MERCHANT_HTTPD_PRIVATE_DELETE_CATEGORIES_ID_H + +#include "taler-merchant-httpd.h" + + +/** + * Handle a DELETE "/categories/$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_categories_ID ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +/* end of taler-merchant-httpd_private-delete-categories-ID.h */ +#endif diff --git a/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.c b/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.c index b147b84f..ff9ad2ef 100644 --- a/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.c +++ b/src/backend/taler-merchant-httpd_private-delete-otp-devices-ID.c @@ -61,7 +61,7 @@ TMH_private_delete_otp_devices_ID (const struct TMH_RequestHandler *rh, case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: return TALER_MHD_reply_with_error (connection, MHD_HTTP_NOT_FOUND, - TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN, + TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN, hc->infix); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: return TALER_MHD_reply_static (connection, diff --git a/src/backend/taler-merchant-httpd_private-get-categories-ID.c b/src/backend/taler-merchant-httpd_private-get-categories-ID.c new file mode 100644 index 00000000..bebe087f --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-get-categories-ID.c @@ -0,0 +1,111 @@ +/* + This file is part of TALER + (C) 2022-2024 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-categories-ID.c + * @brief implement GET /private/categories/$ID + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-get-categories-ID.h" +#include <taler/taler_json_lib.h> + + +/** + * Handle a GET "/private/categories/$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_get_categories_ID ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + struct TMH_MerchantInstance *mi = hc->instance; + struct TALER_MERCHANTDB_OtpDeviceDetails tp = { 0 }; + enum GNUNET_DB_QueryStatus qs; + uint64_t faketime_s + = GNUNET_TIME_timestamp_to_s (GNUNET_TIME_timestamp_get ()); + struct GNUNET_TIME_Timestamp my_time; + struct TALER_Amount price; + + TALER_MHD_parse_request_number (connection, + "faketime", + &faketime_s); + memset (&price, + 0, + sizeof (price)); + TALER_MHD_parse_request_amount (connection, + "price", + &price); + my_time = GNUNET_TIME_timestamp_from_s (faketime_s); + GNUNET_assert (NULL != mi); + qs = TMH_db->select_otp (TMH_db->cls, + mi->settings.id, + hc->infix, + &tp); + if (0 > qs) + { + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "select_otp"); + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_GENERIC_CATEGORY_UNKNOWN, + hc->infix); + } + { + MHD_RESULT ret; + char *pos_confirmation; + + pos_confirmation = (NULL == tp.otp_key) + ? NULL + : TALER_build_pos_confirmation (tp.otp_key, + tp.otp_algorithm, + &price, + my_time); + /* Note: we deliberately (by design) do not return the otp_key */ + ret = TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_string ("device_description", + tp.otp_description), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("otp_code", + pos_confirmation)), + GNUNET_JSON_pack_uint64 ("otp_timestamp", + faketime_s), + GNUNET_JSON_pack_uint64 ("otp_algorithm", + tp.otp_algorithm), + GNUNET_JSON_pack_uint64 ("otp_ctr", + tp.otp_ctr)); + GNUNET_free (pos_confirmation); + GNUNET_free (tp.otp_description); + GNUNET_free (tp.otp_key); + return ret; + } +} + + +/* end of taler-merchant-httpd_private-get-categories-ID.c */ diff --git a/src/backend/taler-merchant-httpd_private-get-categories-ID.h b/src/backend/taler-merchant-httpd_private-get-categories-ID.h new file mode 100644 index 00000000..c0226659 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-get-categories-ID.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + (C) 2024 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-categories-ID.h + * @brief implement GET /private/categories/$ID/ + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_CATEGORIES_ID_H +#define TALER_MERCHANT_HTTPD_PRIVATE_GET_CATEGORIES_ID_H + +#include "taler-merchant-httpd.h" + + +/** + * Handle a GET "/private/categories/$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_get_categories_ID ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +/* end of taler-merchant-httpd_private-get-categories-ID.h */ +#endif diff --git a/src/backend/taler-merchant-httpd_private-get-categories.c b/src/backend/taler-merchant-httpd_private-get-categories.c new file mode 100644 index 00000000..74c0d6cd --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-get-categories.c @@ -0,0 +1,80 @@ +/* + This file is part of TALER + (C) 2024 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-categories.c + * @brief implement GET /categories + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-get-categories.h" + + +/** + * Add OTP device details to our JSON array. + * + * @param cls a `json_t *` JSON array to build + * @param otp_id ID of the OTP device + * @param otp_description human-readable description for the OTP device + */ +static void +add_otp (void *cls, + const char *otp_id, + const char *otp_description) +{ + json_t *pa = cls; + + GNUNET_assert (0 == + json_array_append_new ( + pa, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("otp_device_id", + otp_id), + GNUNET_JSON_pack_string ("device_description", + otp_description)))); +} + + +MHD_RESULT +TMH_private_get_categories (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + json_t *pa; + enum GNUNET_DB_QueryStatus qs; + + pa = json_array (); + GNUNET_assert (NULL != pa); + qs = TMH_db->lookup_categories (TMH_db->cls, + hc->instance->settings.id, + &add_otp, + pa); + if (0 > qs) + { + GNUNET_break (0); + json_decref (pa); + 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 ("categories", + pa)); +} + + +/* end of taler-merchant-httpd_private-get-categories.c */ diff --git a/src/backend/taler-merchant-httpd_private-get-categories.h b/src/backend/taler-merchant-httpd_private-get-categories.h new file mode 100644 index 00000000..68eed05e --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-get-categories.h @@ -0,0 +1,42 @@ +/* + This file is part of TALER + (C) 2024 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-categories.h + * @brief implement GET /private/categories + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_CATEGORIES_H +#define TALER_MERCHANT_HTTPD_PRIVATE_GET_CATEGORIES_H + +#include "taler-merchant-httpd.h" + + +/** + * Handle a GET "/private/categories" 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_categories ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +/* end of taler-merchant-httpd_private-get-categories.h */ +#endif diff --git a/src/backend/taler-merchant-httpd_private-patch-categories-ID.c b/src/backend/taler-merchant-httpd_private-patch-categories-ID.c new file mode 100644 index 00000000..596b8b09 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-patch-categories-ID.c @@ -0,0 +1,114 @@ +/* + This file is part of TALER + (C) 2022 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-otp-devices-ID.c + * @brief implementing PATCH /otp-devices/$ID request handling + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-patch-otp-devices-ID.h" +#include "taler-merchant-httpd_helper.h" +#include <taler/taler_json_lib.h> + + +MHD_RESULT +TMH_private_patch_otp_devices_ID (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + struct TMH_MerchantInstance *mi = hc->instance; + const char *device_id = hc->infix; + struct TALER_MERCHANTDB_OtpDeviceDetails tp = {0}; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("otp_device_description", + (const char **) &tp.otp_description), + TALER_JSON_spec_otp_type ("otp_algorithm", + &tp.otp_algorithm), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_uint64 ("otp_ctr", + &tp.otp_ctr), + NULL), + GNUNET_JSON_spec_mark_optional( + + TALER_JSON_spec_otp_key ("otp_key", + (const char **) &tp.otp_key), + NULL), + GNUNET_JSON_spec_end () + }; + + GNUNET_assert (NULL != mi); + GNUNET_assert (NULL != device_id); + { + 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; + } + + qs = TMH_db->update_otp (TMH_db->cls, + mi->settings.id, + device_id, + &tp); + { + 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, + "update_pos"); + 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: + ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN, + device_id); + 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-otp-devices-ID.c */ diff --git a/src/backend/taler-merchant-httpd_private-patch-categories-ID.h b/src/backend/taler-merchant-httpd_private-patch-categories-ID.h new file mode 100644 index 00000000..c88290a8 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-patch-categories-ID.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + (C) 2024 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-categories-ID.h + * @brief implementing PATCH /private/categories/$ID request handling + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_CATEGORIES_ID_H +#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_CATEGORIES_ID_H + +#include "taler-merchant-httpd.h" + + +/** + * PATCH descriptions of an existing product category. + * + * @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_categories_ID ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif diff --git a/src/backend/taler-merchant-httpd_private-post-categories.c b/src/backend/taler-merchant-httpd_private-post-categories.c new file mode 100644 index 00000000..255fd2c4 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-post-categories.c @@ -0,0 +1,198 @@ +/* + This file is part of TALER + (C) 2024 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-categories.c + * @brief implementing POST /private/categories request handling + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-post-categories.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 categories are identical. + * + * @param t1 device to compare + * @param t2 other device to compare + * @return true if they are 'equal', false if not or of payto_uris is not an array + */ +static bool +categories_equal (const struct TALER_MERCHANTDB_OtpDeviceDetails *t1, + const struct TALER_MERCHANTDB_OtpDeviceDetails *t2) +{ + return ( (0 == strcmp (t1->otp_description, + t2->otp_description)) && + (0 == strcmp (t1->otp_key, + t2->otp_key) ) && + (t1->otp_ctr == t2->otp_ctr) && + (t1->otp_algorithm == t2->otp_algorithm) ); +} + + +MHD_RESULT +TMH_private_post_categories (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + struct TMH_MerchantInstance *mi = hc->instance; + struct TALER_MERCHANTDB_OtpDeviceDetails tp = { 0 }; + const char *device_id; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("otp_device_id", + &device_id), + GNUNET_JSON_spec_string ("otp_device_description", + (const char **) &tp.otp_description), + TALER_JSON_spec_otp_type ("otp_algorithm", + &tp.otp_algorithm), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_uint64 ("otp_ctr", + &tp.otp_ctr), + NULL), + TALER_JSON_spec_otp_key ("otp_key", + (const char **) &tp.otp_key), + 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; + } + } + + /* finally, interact with DB until no serialization error */ + for (unsigned int i = 0; i<MAX_RETRIES; i++) + { + /* Test if a OTP device of this id is known */ + struct TALER_MERCHANTDB_OtpDeviceDetails etp; + + if (GNUNET_OK != + TMH_db->start (TMH_db->cls, + "/post categories")) + { + 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->select_otp (TMH_db->cls, + mi->settings.id, + device_id, + &etp); + 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 etp == tp? */ + { + bool eq; + + eq = categories_equal (&tp, + &etp); + GNUNET_free (etp.otp_description); + GNUNET_free (etp.otp_key); + 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) + : TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_POST_CATEGORIES_CONFLICT_CATEGORY_EXISTS, + device_id); + } + } /* end switch (qs) */ + + qs = TMH_db->insert_otp (TMH_db->cls, + mi->settings.id, + device_id, + &tp); + 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-categories.c */ diff --git a/src/backend/taler-merchant-httpd_private-post-categories.h b/src/backend/taler-merchant-httpd_private-post-categories.h new file mode 100644 index 00000000..a8431059 --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-post-categories.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + (C) 2024 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-categories.h + * @brief implementing POST /categories request handling + * @author Christian Grothoff + */ +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_CATEGORIES_H +#define TALER_MERCHANT_HTTPD_PRIVATE_POST_CATEGORIES_H + +#include "taler-merchant-httpd.h" + + +/** + * Generate a product category. + * + * @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_categories ( + const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am index 89be9a4f..8d1c582c 100644 --- a/src/backenddb/Makefile.am +++ b/src/backenddb/Makefile.am @@ -22,6 +22,7 @@ sql_DATA = \ merchant-0003.sql \ merchant-0004.sql \ merchant-0005.sql \ + merchant-0006.sql \ drop.sql BUILT_SOURCES = \ @@ -62,7 +63,7 @@ libtalermerchantdb_la_LIBADD = \ libtalermerchantdb_la_LDFLAGS = \ $(POSTGRESQL_LDFLAGS) \ - -version-info 3:0:1 \ + -version-info 3:1:1 \ -no-undefined libtaler_plugin_merchantdb_postgres_la_SOURCES = \ @@ -76,6 +77,11 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \ pg_insert_transfer_details.h pg_insert_transfer_details.c \ pg_store_wire_fee_by_exchange.h pg_store_wire_fee_by_exchange.c \ pg_select_open_transfers.h pg_select_open_transfers.c \ + pg_lookup_categories.h pg_lookup_categories.c \ + pg_select_category.h pg_select_category.c \ + pg_update_category.h pg_update_category.c \ + pg_insert_category.h pg_insert_category.c \ + pg_delete_category.h pg_delete_category.c \ pg_lookup_instances.h pg_lookup_instances.c \ pg_lookup_transfers.h pg_lookup_transfers.c \ pg_update_transfer_status.h pg_update_transfer_status.c \ diff --git a/src/backenddb/merchant-0006.sql b/src/backenddb/merchant-0006.sql new file mode 100644 index 00000000..d68927c0 --- /dev/null +++ b/src/backenddb/merchant-0006.sql @@ -0,0 +1,55 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2024 Taler Systems SA +-- +-- TALER 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. +-- +-- 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/> +-- + +-- Everything in one big transaction +BEGIN; + +-- Check patch versioning is in place. +SELECT _v.register_patch('merchant-0006', NULL, NULL); + +SET search_path TO merchant; + +CREATE TABLE IF NOT EXISTS merchant_categories + (category_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY + ,merchant_serial BIGINT NOT NULL + REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE + ,category_name TEXT NOT NULL UNIQUE + ,category_name_i18n BYTEA NOT NULL + ); + +COMMENT ON COLUMN merchant_categories.category_name + IS 'name of the category'; +COMMENT ON COLUMN merchant_categories.category_name_i18n + IS 'JSON with translations of the category name'; + +CREATE TABLE merchant_product_categories + (category_serial BIGINT NOT NULL + REFERENCES merchant_categories (category_serial) ON DELETE CASCADE + ,product_serial BIGINT NOT NULL + REFERENCES merchant_inventory (product_serial) ON DELETE CASCADE); +CREATE INDEX merchant_categories_by_category + ON merchant_categories (category_serial); +CREATE INDEX merchant_categories_by_product + ON merchant_categories (product_serial); + +COMMENT ON COLUMN merchant_product_categories.category_serial + IS 'Reference to a category the product is part of'; +COMMENT ON COLUMN merchant_product_categories.product_serial + IS 'Reference to a product which is in the given category'; + + +-- Complete transaction +COMMIT; diff --git a/src/backenddb/pg_delete_category.c b/src/backenddb/pg_delete_category.c new file mode 100644 index 00000000..4a43aa37 --- /dev/null +++ b/src/backenddb/pg_delete_category.c @@ -0,0 +1,54 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_delete_category.c + * @brief Implementation of the delete_category function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_delete_category.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_delete_category (void *cls, + const char *instance_id, + uint64_t category_id) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_uint64 (&category_id), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "delete_category", + "DELETE" + " FROM merchant_categories" + " WHERE merchant_serial=" + " (SELECT merchant_serial " + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND category_serial=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "delete_category", + params); +} diff --git a/src/backenddb/pg_delete_category.h b/src/backenddb/pg_delete_category.h new file mode 100644 index 00000000..8837a6b8 --- /dev/null +++ b/src/backenddb/pg_delete_category.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_delete_category.h + * @brief implementation of the delete_category function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_DELETE_CATEGORY_H +#define PG_DELETE_CATEGORY_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + +/** + * Delete information about a product category. + * + * @param cls closure + * @param instance_id instance to delete category of + * @param category_id identifies the category to delete + * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + * if template unknown. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_delete_category (void *cls, + const char *instance_id, + uint64_t category_id); + + +#endif diff --git a/src/backenddb/pg_delete_otp.c b/src/backenddb/pg_delete_otp.c index 5f011a4b..60f20481 100644 --- a/src/backenddb/pg_delete_otp.c +++ b/src/backenddb/pg_delete_otp.c @@ -43,11 +43,11 @@ TMH_PG_delete_otp (void *cls, "delete_otp", "DELETE" " FROM merchant_otp_devices" - " WHERE merchant_otp_devices.merchant_serial=" + " WHERE merchant_serial=" " (SELECT merchant_serial " " FROM merchant_instances" " WHERE merchant_id=$1)" - " AND merchant_otp_devices.otp_id=$2"); + " AND otp_id=$2"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "delete_otp", params); diff --git a/src/backenddb/pg_insert_category.c b/src/backenddb/pg_insert_category.c new file mode 100644 index 00000000..f820b2c6 --- /dev/null +++ b/src/backenddb/pg_insert_category.c @@ -0,0 +1,65 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_insert_category.c + * @brief Implementation of the insert_category function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_insert_category.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_insert_category (void *cls, + const char *instance_id, + const char *category_name, + const json_t *category_name_i18n, + uint64_t *category_id) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (category_name), + TALER_PQ_query_param_json (category_name_i18n), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("category_serial", + category_id), + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + PREPARE (pg, + "insert_category", + "INSERT INTO merchant_categories" + "(category_name" + ",category_name_i18n" + ")" + " SELECT merchant_serial," + " $2, $3" + " FROM merchant_instances" + " WHERE merchant_id=$1" + " RETURNING category_serial"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "insert_category", + params, + rs); +} diff --git a/src/backenddb/pg_insert_category.h b/src/backenddb/pg_insert_category.h new file mode 100644 index 00000000..8f4bfc99 --- /dev/null +++ b/src/backenddb/pg_insert_category.h @@ -0,0 +1,46 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_insert_category.h + * @brief implementation of the insert_category function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_CATEGORY_H +#define PG_INSERT_CATEGORY_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + +/** + * Insert new product category. + * + * @param cls closure + * @param instance_id instance to insert OTP device for + * @param category_name name of the category + * @param category_name_i18n translations of the category name + * @param[out] category_id set to the category id on success + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_insert_category (void *cls, + const char *instance_id, + const char *category_name, + const json_t *category_name_i18n, + uint64_t *category_id); + + +#endif diff --git a/src/backenddb/pg_lookup_categories.c b/src/backenddb/pg_lookup_categories.c new file mode 100644 index 00000000..9aea5477 --- /dev/null +++ b/src/backenddb/pg_lookup_categories.c @@ -0,0 +1,148 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_lookup_categories.c + * @brief Implementation of the lookup_categories function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_lookup_categories.h" +#include "pg_helper.h" + + +/** + * Context used for TMH_PG_lookup_categories(). + */ +struct LookupCategoryContext +{ + /** + * Function to call with the results. + */ + TALER_MERCHANTDB_CategoriesCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Did database result extraction fail? + */ + bool extract_failed; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results about otp_device. + * + * @param[in,out] cls of type `struct LookupCategoryContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lookup_categories_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupCategoryContext *tlc = cls; + + for (unsigned int i = 0; i < num_results; i++) + { + uint64_t category_id; + char *category_name; + json_t *category_name_i18n; + uint64_t product_count; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("category_serial", + &category_id), + GNUNET_PQ_result_spec_string ("category_name", + &category_name), + TALER_PQ_result_spec_json ("category_name_i18n", + &category_name_i18n), + GNUNET_PQ_result_spec_uint64 ("product_count", + &product_count), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + tlc->extract_failed = true; + return; + } + tlc->cb (tlc->cb_cls, + category_id, + category_name, + category_name_i18n, + product_count); + GNUNET_PQ_cleanup_result (rs); + } +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_categories (void *cls, + const char *instance_id, + TALER_MERCHANTDB_CategoriesCallback cb, + void *cb_cls) +{ + + struct PostgresClosure *pg = cls; + struct LookupCategoryContext tlc = { + .cb = cb, + .cb_cls = cb_cls, + /* Can be overwritten by the lookup_categories_cb */ + .extract_failed = false, + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "lookup_categories", + "SELECT" + " mc.category_serial" + ",mc.category_name" + ",mc.category_name_i18n" + ",COALESCE(COUNT(mpc.product_serial),0)" + " AS product_count" + " FROM merchant_categories mc" + " JOIN merchant_product_categories mpc" + " JOIN merchant_instances mi" + " USING (merchant_serial)" + " WHERE mi.merchant_id=$1" + " GROUP BY mc.category_serial" + " ORDER BY mc.category_serial;"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_categories", + params, + &lookup_categories_cb, + &tlc); + /* If there was an error inside lookup_categories_cb, return a hard error. */ + if (tlc.extract_failed) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} diff --git a/src/backenddb/pg_lookup_categories.h b/src/backenddb/pg_lookup_categories.h new file mode 100644 index 00000000..500295c0 --- /dev/null +++ b/src/backenddb/pg_lookup_categories.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_lookup_categories.h + * @brief implementation of the lookup_categories function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_LOOKUP_CATEGORIES_H +#define PG_LOOKUP_CATEGORIES_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + +/** + * Lookup all of the product categories the given instance has configured. + * + * @param cls closure + * @param instance_id instance to lookup OTP devices for + * @param cb function to call on all categories found + * @param cb_cls closure for @a cb + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_categories (void *cls, + const char *instance_id, + TALER_MERCHANTDB_CategoriesCallback cb, + void *cb_cls); + +#endif diff --git a/src/backenddb/pg_select_category.c b/src/backenddb/pg_select_category.c new file mode 100644 index 00000000..c20d7bb7 --- /dev/null +++ b/src/backenddb/pg_select_category.c @@ -0,0 +1,37 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_select_category.c + * @brief Implementation of the select_category function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_select_category.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_select_category (void *cls, + const char *instance_id, + uint64_t category_id, + struct TALER_MERCHANTDB_CategoryDetails *cd) +{ + GNUNET_break (0); // FIXME + return GNUNET_DB_STATUS_HARD_ERROR; +} diff --git a/src/backenddb/pg_select_category.h b/src/backenddb/pg_select_category.h new file mode 100644 index 00000000..9eeb14aa --- /dev/null +++ b/src/backenddb/pg_select_category.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_select_category.h + * @brief implementation of the select_category function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_CATEGORY_H +#define PG_SELECT_CATEGORY_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Lookup details about product category. + * + * @param cls closure + * @param instance_id instance to lookup template for + * @param category_id category to update + * @param[out] cd set to the category details on success, can be NULL + * (in that case we only want to check if the category exists) + * @return database result code + */ +enum GNUNET_DB_QueryStatus +TMH_PG_select_category (void *cls, + const char *instance_id, + uint64_t category_id, + struct TALER_MERCHANTDB_CategoryDetails *cd); + +#endif diff --git a/src/backenddb/pg_update_category.c b/src/backenddb/pg_update_category.c new file mode 100644 index 00000000..3b07a266 --- /dev/null +++ b/src/backenddb/pg_update_category.c @@ -0,0 +1,59 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_update_category.c + * @brief Implementation of the update_category function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_update_category.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_update_category (void *cls, + const char *instance_id, + uint64_t category_id, + const char *category_name, + const json_t *category_name_i18n) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_uint64 (&category_id), + GNUNET_PQ_query_param_string (category_name), + TALER_PQ_query_param_json (category_name_i18n), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE (pg, + "update_category", + "UPDATE merchant_categories SET" + " category_name=$3" + ",category_name_i18n=$4" + " WHERE merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND category_serial=$2"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "update_category", + params); +} diff --git a/src/backenddb/pg_update_category.h b/src/backenddb/pg_update_category.h new file mode 100644 index 00000000..616a714a --- /dev/null +++ b/src/backenddb/pg_update_category.h @@ -0,0 +1,47 @@ +/* + This file is part of TALER + Copyright (C) 2024 Taler Systems SA + + TALER 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. + + 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 backenddb/pg_update_category.h + * @brief implementation of the update_category function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_UPDATE_CATEGORY_H +#define PG_UPDATE_CATEGORY_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Update descriptions of a product category. + * + * @param cls closure + * @param instance_id instance to update OTP device for + * @param category_id category to update + * @param category_name name of the category + * @param category_name_i18n translations of the category name + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template + * does not yet exist. + */ +enum GNUNET_DB_QueryStatus +TMH_PG_update_category (void *cls, + const char *instance_id, + uint64_t category_id, + const char *category_name, + const json_t *category_name_i18n); + +#endif diff --git a/src/backenddb/pg_update_otp.c b/src/backenddb/pg_update_otp.c index bdcb9624..218ae74e 100644 --- a/src/backenddb/pg_update_otp.c +++ b/src/backenddb/pg_update_otp.c @@ -26,17 +26,6 @@ #include "pg_helper.h" -/** - * Update details about a particular OTP device. - * - * @param cls closure - * @param instance_id instance to update OTP device for - * @param otp_id OTP device to update - * @param td update to the OTP device details on success, can be NULL - * (in that case we only want to check if the template exists) - * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template - * does not yet exist. - */ enum GNUNET_DB_QueryStatus TMH_PG_update_otp (void *cls, const char *instance_id, @@ -52,7 +41,7 @@ TMH_PG_update_otp (void *cls, GNUNET_PQ_query_param_uint32 (&pos32), GNUNET_PQ_query_param_uint64 (&td->otp_ctr), (NULL == td->otp_key) - ? GNUNET_PQ_query_param_null() + ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (td->otp_key), GNUNET_PQ_query_param_end }; @@ -74,5 +63,3 @@ TMH_PG_update_otp (void *cls, "update_otp", params); } - - diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 4a03dbfe..ede43100 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -44,6 +44,11 @@ #include "pg_lookup_instances.h" #include "pg_lookup_transfers.h" #include "pg_lookup_pending_deposits.h" +#include "pg_lookup_categories.h" +#include "pg_select_category.h" +#include "pg_update_category.h" +#include "pg_insert_category.h" +#include "pg_delete_category.h" #include "pg_update_wirewatch_progress.h" #include "pg_select_wirewatch_accounts.h" #include "pg_select_open_transfers.h" @@ -564,6 +569,16 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) = &TMH_PG_insert_pending_webhook; plugin->update_pending_webhook = &TMH_PG_update_pending_webhook; + plugin->lookup_categories + = &TMH_PG_lookup_categories; + plugin->select_category + = &TMH_PG_select_category; + plugin->update_category + = &TMH_PG_update_category; + plugin->insert_category + = &TMH_PG_insert_category; + plugin->delete_category + = &TMH_PG_delete_category; plugin->delete_exchange_accounts = &TMH_PG_delete_exchange_accounts; plugin->select_accounts_by_exchange diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index 12b13e33..d06ab76c 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -441,6 +441,75 @@ struct TALER_MERCHANTDB_OtpDeviceDetails /** + * Typically called by `lookup_categories`. + * + * @param cls closure + * @param category_id ID of the category + * @param category_name name of the category + * @param category_name_i18n translations of the @a category_name + * @param product_count number of products in the category + */ +typedef void +(*TALER_MERCHANTDB_CategoriesCallback)( + void *cls, + uint64_t category_id, + const char *category_name, + const json_t *category_name_i18n, + uint64_t product_count); + + +/** + * Details about a product category. + */ +struct TALER_MERCHANTDB_ProductSummary +{ + /** + * ID of the product. + */ + char *product_id; + + /** + * Description for the product. + */ + char *description; + + /** + * Translation of the @e description. + */ + json_t *description_i18n; + +}; + +/** + * Details about a product category. + */ +struct TALER_MERCHANTDB_CategoryDetails +{ + + /** + * Name of the category. + */ + char *category_name; + + /** + * Translations of the name of the category. + */ + json_t *category_name_i18n; + + /** + * Products in the category. + */ + struct TALER_MERCHANTDB_ProductSummary *products; + + /** + * Length of the @e products array. + */ + unsigned int num_products; + +}; + + +/** * Typically called by `lookup_webhooks`. * * @param cls a `json_t *` JSON array to build @@ -2876,6 +2945,24 @@ struct TALER_MERCHANTDB_Plugin /** + * Update details about a particular template. + * + * @param cls closure + * @param instance_id instance to update template for + * @param template_id template to update + * @param td update to the template details on success, can be NULL + * (in that case we only want to check if the template exists) + * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template + * does not yet exist. + */ + enum GNUNET_DB_QueryStatus + (*update_template)(void *cls, + const char *instance_id, + const char *template_id, + const struct TALER_MERCHANTDB_TemplateDetails *td); + + + /** * Delete information about an OTP device. * * @param cls closure @@ -2971,21 +3058,86 @@ struct TALER_MERCHANTDB_Plugin /** - * Update details about a particular template. + * Delete information about a product category. * * @param cls closure - * @param instance_id instance to update template for - * @param template_id template to update - * @param td update to the template details on success, can be NULL - * (in that case we only want to check if the template exists) + * @param instance_id instance to delete category of + * @param category_id identifies the category to delete + * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS + * if template unknown. + */ + enum GNUNET_DB_QueryStatus + (*delete_category)(void *cls, + const char *instance_id, + uint64_t category_id); + + /** + * Insert new product category. + * + * @param cls closure + * @param instance_id instance to insert OTP device for + * @param category_name name of the category + * @param category_name_i18n translations of the category name + * @param[out] category_id set to the category id on success + * @return database result code + */ + enum GNUNET_DB_QueryStatus + (*insert_category)(void *cls, + const char *instance_id, + const char *category_name, + const json_t *category_name_i18n, + uint64_t *category_id); + + + /** + * Update descriptions of a product category. + * + * @param cls closure + * @param instance_id instance to update OTP device for + * @param category_id category to update + * @param category_name name of the category + * @param category_name_i18n translations of the category name * @return database result code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the template * does not yet exist. */ enum GNUNET_DB_QueryStatus - (*update_template)(void *cls, + (*update_category)(void *cls, const char *instance_id, - const char *template_id, - const struct TALER_MERCHANTDB_TemplateDetails *td); + uint64_t category_id, + const char *category_name, + const json_t *category_name_i18n); + + /** + * Lookup all of the product categories the given instance has configured. + * + * @param cls closure + * @param instance_id instance to lookup OTP devices for + * @param cb function to call on all categories found + * @param cb_cls closure for @a cb + * @return database result code + */ + enum GNUNET_DB_QueryStatus + (*lookup_categories)(void *cls, + const char *instance_id, + TALER_MERCHANTDB_CategoriesCallback cb, + void *cb_cls); + + + /** + * Lookup details about product category. + * + * @param cls closure + * @param instance_id instance to lookup template for + * @param category_id category to update + * @param[out] cd set to the category details on success, can be NULL + * (in that case we only want to check if the category exists) + * @return database result code + */ + enum GNUNET_DB_QueryStatus + (*select_category)(void *cls, + const char *instance_id, + uint64_t category_id, + struct TALER_MERCHANTDB_CategoryDetails *cd); /** |