taler-merchant-httpd_patch-private-templates-TEMPLATE_ID.c (6673B)
1 /* 2 This file is part of TALER 3 (C) 2022, 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Affero General Public License as 7 published by the Free Software Foundation; either version 3, 8 or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, 17 see <http://www.gnu.org/licenses/> 18 */ 19 20 /** 21 * @file src/backend/taler-merchant-httpd_patch-private-templates-TEMPLATE_ID.c 22 * @brief implementing PATCH /templates/$ID request handling 23 * @author Priscilla HUANG 24 */ 25 #include "platform.h" 26 #include "taler-merchant-httpd_patch-private-templates-TEMPLATE_ID.h" 27 #include "taler-merchant-httpd_helper.h" 28 #include <taler/taler_json_lib.h> 29 #include "merchant-database/get_otp_device_serial.h" 30 #include "merchant-database/update_template.h" 31 32 33 /** 34 * PATCH configuration of an existing instance, given its configuration. 35 * 36 * @param rh context of the handler 37 * @param connection the MHD connection to handle 38 * @param[in,out] hc context with further information about the request 39 * @return MHD result code 40 */ 41 enum MHD_Result 42 TMH_private_patch_templates_ID (const struct TMH_RequestHandler *rh, 43 struct MHD_Connection *connection, 44 struct TMH_HandlerContext *hc) 45 { 46 struct TMH_MerchantInstance *mi = hc->instance; 47 const char *template_id = hc->infix; 48 struct TALER_MERCHANTDB_TemplateDetails tp = {0}; 49 enum GNUNET_DB_QueryStatus qs; 50 struct GNUNET_JSON_Specification spec[] = { 51 GNUNET_JSON_spec_string ("template_description", 52 (const char **) &tp.template_description), 53 GNUNET_JSON_spec_mark_optional ( 54 TALER_JSON_spec_slug ("otp_id", 55 (const char **) &tp.otp_id), 56 NULL), 57 GNUNET_JSON_spec_object_copy ("template_contract", 58 &tp.template_contract), 59 GNUNET_JSON_spec_mark_optional ( 60 GNUNET_JSON_spec_object_copy ("editable_defaults", 61 &tp.editable_defaults), 62 NULL), 63 GNUNET_JSON_spec_end () 64 }; 65 66 GNUNET_assert (NULL != mi); 67 GNUNET_assert (NULL != template_id); 68 { 69 enum GNUNET_GenericReturnValue res; 70 71 res = TALER_MHD_parse_json_data (connection, 72 hc->request_body, 73 spec); 74 if (GNUNET_OK != res) 75 return (GNUNET_NO == res) 76 ? MHD_YES 77 : MHD_NO; 78 } 79 if (! TALER_MERCHANT_template_contract_valid (tp.template_contract)) 80 { 81 GNUNET_break_op (0); 82 GNUNET_JSON_parse_free (spec); 83 return TALER_MHD_reply_with_error (connection, 84 MHD_HTTP_BAD_REQUEST, 85 TALER_EC_GENERIC_PARAMETER_MALFORMED, 86 "template_contract"); 87 } 88 if (NULL != tp.editable_defaults) 89 { 90 const char *key; 91 json_t *val; 92 93 json_object_foreach (tp.editable_defaults, key, val) 94 { 95 if (NULL != 96 json_object_get (tp.template_contract, 97 key)) 98 { 99 char *msg; 100 enum MHD_Result ret; 101 102 GNUNET_break_op (0); 103 GNUNET_asprintf (&msg, 104 "editable_defaults::%s conflicts with template_contract", 105 key); 106 GNUNET_JSON_parse_free (spec); 107 ret = TALER_MHD_reply_with_error ( 108 connection, 109 MHD_HTTP_BAD_REQUEST, 110 TALER_EC_GENERIC_PARAMETER_MALFORMED, 111 msg); 112 GNUNET_free (msg); 113 return ret; 114 } 115 } 116 } 117 118 if (NULL != tp.otp_id) 119 { 120 uint64_t otp_serial; 121 122 /* Note: without this pre-check, an unknown @e otp_id would 123 simply resolve to NULL in the UPDATE and thus *silently* 124 remove the OTP device binding of the template. */ 125 qs = TALER_MERCHANTDB_get_otp_device_serial (TMH_db, 126 mi->settings.id, 127 tp.otp_id, 128 &otp_serial); 129 switch (qs) 130 { 131 case GNUNET_DB_STATUS_HARD_ERROR: 132 case GNUNET_DB_STATUS_SOFT_ERROR: 133 GNUNET_break (0); 134 GNUNET_JSON_parse_free (spec); 135 return TALER_MHD_reply_with_error (connection, 136 MHD_HTTP_INTERNAL_SERVER_ERROR, 137 TALER_EC_GENERIC_DB_FETCH_FAILED, 138 "get_otp_device_serial"); 139 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 140 GNUNET_JSON_parse_free (spec); 141 return TALER_MHD_reply_with_error (connection, 142 MHD_HTTP_NOT_FOUND, 143 TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN, 144 tp.otp_id); 145 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 146 break; 147 } 148 } 149 150 qs = TALER_MERCHANTDB_update_template (TMH_db, 151 mi->settings.id, 152 template_id, 153 &tp); 154 { 155 enum MHD_Result ret = MHD_NO; 156 157 switch (qs) 158 { 159 case GNUNET_DB_STATUS_HARD_ERROR: 160 GNUNET_break (0); 161 ret = TALER_MHD_reply_with_error ( 162 connection, 163 MHD_HTTP_INTERNAL_SERVER_ERROR, 164 TALER_EC_GENERIC_DB_STORE_FAILED, 165 NULL); 166 break; 167 case GNUNET_DB_STATUS_SOFT_ERROR: 168 GNUNET_break (0); 169 ret = TALER_MHD_reply_with_error ( 170 connection, 171 MHD_HTTP_INTERNAL_SERVER_ERROR, 172 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 173 "unexpected serialization problem"); 174 break; 175 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 176 ret = TALER_MHD_reply_with_error ( 177 connection, 178 MHD_HTTP_NOT_FOUND, 179 TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN, 180 template_id); 181 break; 182 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 183 ret = TALER_MHD_reply_static (connection, 184 MHD_HTTP_NO_CONTENT, 185 NULL, 186 NULL, 187 0); 188 break; 189 } 190 GNUNET_JSON_parse_free (spec); 191 return ret; 192 } 193 } 194 195 196 /* end of taler-merchant-httpd_patch-private-templates-TEMPLATE_ID.c */