diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd_post-using-templates.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_post-using-templates.c | 322 |
1 files changed, 194 insertions, 128 deletions
diff --git a/src/backend/taler-merchant-httpd_post-using-templates.c b/src/backend/taler-merchant-httpd_post-using-templates.c index 9252afc8..cdaf917e 100644 --- a/src/backend/taler-merchant-httpd_post-using-templates.c +++ b/src/backend/taler-merchant-httpd_post-using-templates.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2022 Taler Systems SA + (C) 2022-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 @@ -21,6 +21,7 @@ * @file taler-merchant-httpd_post-using-templates.c * @brief implementing POST /using-templates request handling * @author Priscilla HUANG + * @author Christian Grothoff */ #include "platform.h" #include "taler-merchant-httpd_post-using-templates.h" @@ -29,13 +30,49 @@ #include <taler/taler_json_lib.h> +/** + * Our context. + */ +struct UseContext +{ + /** + * Internal handler context we are passing into the + * POST /private/orders handler. + */ + struct TMH_HandlerContext ihc; + + /** + * Our template details from the DB. + */ + struct TALER_MERCHANTDB_TemplateDetails etp; + +}; + + +/** + * Clean up a `struct UseContext *` + * + * @param cls a `struct UseContext *` + */ +static void +cleanup_use_context (void *cls) +{ + struct UseContext *uc = cls; + + TALER_MERCHANTDB_template_details_free (&uc->etp); + if (NULL != uc->ihc.cc) + uc->ihc.cc (uc->ihc.ctx); + json_decref (uc->ihc.request_body); + GNUNET_free (uc); +} + + MHD_RESULT TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { struct TMH_MerchantInstance *mi = hc->instance; - MHD_RESULT mret; const char *template_id = hc->infix; const char *summary = NULL; const char *fulfillment_url = NULL; @@ -44,20 +81,26 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh, bool no_amount; json_t *fake_body; bool no_summary; - struct TALER_MERCHANTDB_TemplateDetails etp; - struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("summary", &summary), NULL), GNUNET_JSON_spec_mark_optional ( - TALER_JSON_spec_amount ("amount", - TMH_currency, - &amount), + TALER_JSON_spec_amount_any ("amount", + &amount), &no_amount), GNUNET_JSON_spec_end () }; + struct UseContext *uc = hc->ctx; + + if (NULL == uc) + { + uc = GNUNET_new (struct UseContext); + hc->ctx = uc; + hc->cc = &cleanup_use_context; + uc->ihc.instance = hc->instance; + } { enum GNUNET_GenericReturnValue res; @@ -80,156 +123,179 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh, qs = TMH_db->lookup_template (TMH_db->cls, mi->settings.id, template_id, - &etp); + &uc->etp); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: /* Clean up and fail hard */ GNUNET_break (0); GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - NULL); + 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: /* this should be impossible (single select) */ GNUNET_break (0); GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - NULL); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + NULL); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: /* template not found! */ GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN, - template_id); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN, + template_id); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: /* all good */ break; } /* End of the switch */ } - const char *tsummary; - uint32_t min_age; - struct GNUNET_TIME_Relative pay_duration; - struct TALER_Amount tamount; - bool no_tamount; + { + /* template */ + const char *tsummary = NULL; + const char *tcurrency = NULL; + uint32_t min_age; + struct GNUNET_TIME_Relative pay_duration; + struct TALER_Amount tamount; + bool no_tamount; + struct GNUNET_JSON_Specification tspec[] = { + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("summary", + &tsummary), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("currency", + &tcurrency), + NULL), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_amount_any ("amount", + &tamount), + &no_tamount), + GNUNET_JSON_spec_uint32 ("minimum_age", + &min_age), + GNUNET_JSON_spec_relative_time ("pay_duration", + &pay_duration), + GNUNET_JSON_spec_end () + }; - struct GNUNET_JSON_Specification tspec[] = { - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("summary", - &tsummary), - NULL), - GNUNET_JSON_spec_mark_optional ( - TALER_JSON_spec_amount ("amount", - TMH_currency, - &tamount), - &no_tamount), - GNUNET_JSON_spec_uint32 ("minimum_age", - &min_age), - GNUNET_JSON_spec_relative_time ("pay_duration", - &pay_duration), - GNUNET_JSON_spec_end () - }; + { + enum GNUNET_GenericReturnValue res; + const char *err_name; + unsigned int err_line; - { - enum GNUNET_GenericReturnValue res; - const char *err_name; - unsigned int err_line; + res = GNUNET_JSON_parse (uc->etp.template_contract, + tspec, + &err_name, + &err_line); + if (GNUNET_OK != res) + { + GNUNET_break (0); + json_dumpf (uc->etp.template_contract, + stderr, + JSON_INDENT (2)); + GNUNET_JSON_parse_free (spec); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + err_name); + } + } - res = GNUNET_JSON_parse (etp.template_contract, - tspec, - &err_name, - &err_line); - if (GNUNET_OK != res) + if ( (! no_amount) && + (! no_tamount) ) { - GNUNET_break (0); - json_dumpf (etp.template_contract, - stderr, - JSON_INDENT (2)); GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - err_name); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT, + NULL); } - } - // if amount given in template AND request - if ((! no_amount) && (! no_tamount)) - { - GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT, - NULL); - } - - // if there is no amount in template and request - if (no_amount && no_tamount) - { - GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_AMOUNT, - NULL); - } + if ( (! no_amount) && + (NULL != tcurrency) && + (0 != strcmp (tcurrency, + amount.currency)) ) + { + GNUNET_JSON_parse_free (spec); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH, + tcurrency); + } - if ( (NULL!=summary) && (NULL != tsummary)) - { + if (no_amount && no_tamount) + { + GNUNET_JSON_parse_free (spec); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_AMOUNT, + NULL); + } - GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_POST_USING_TEMPLATES_SUMMARY_CONFLICT_TEMPLATES_CONTRACT_SUBJECT, - NULL); - } + if ( (NULL != summary) && + (NULL != tsummary) ) + { + GNUNET_JSON_parse_free (spec); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_POST_USING_TEMPLATES_SUMMARY_CONFLICT_TEMPLATES_CONTRACT_SUBJECT, + NULL); + } - // if there is no summary in template and request - if ( (NULL == summary) && (NULL == tsummary) ) - { - GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY, - NULL); + if ( (NULL == summary) && + (NULL == tsummary) ) + { + GNUNET_JSON_parse_free (spec); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY, + NULL); + } + no_summary = (NULL == summary); + fake_body = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("otp_id", + uc->etp.otp_id)), + GNUNET_JSON_pack_object_steal ( + "order", + GNUNET_JSON_PACK ( + TALER_JSON_pack_amount ("amount", + no_amount ? + &tamount : + &amount), + GNUNET_JSON_pack_string ("summary", + no_summary ? + tsummary : + summary), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ( + "fulfillment_url", + fulfillment_url)), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ( + "fulfillment_message", + fulfillment_message)) + )) + ); } - no_summary = (NULL == summary); - fake_body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_object_steal ("order", - GNUNET_JSON_PACK ( - TALER_JSON_pack_amount ("amount", - no_amount ? - &tamount : - &amount), - GNUNET_JSON_pack_string ("summary", - no_summary ? - tsummary : - summary), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ( - "fulfillment_url", - fulfillment_url)), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ( - "fulfillment_message", - fulfillment_message)) - )) - ); - TALER_MERCHANTDB_template_details_free (&etp); - { - struct TMH_HandlerContext fake_hc = { - .request_body = fake_body, - .instance = hc->instance - }; - mret = TMH_private_post_orders (NULL, /* not even used */ - connection, - &fake_hc); - } - json_decref (fake_body); - return mret; + uc->ihc.request_body = fake_body; + return TMH_private_post_orders ( + NULL, /* not even used */ + connection, + &uc->ihc); } |