taler-merchant-httpd_patch-private-templates-TEMPLATE_ID.c (6646B)
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_json ("template_contract", 58 &tp.template_contract), 59 GNUNET_JSON_spec_mark_optional ( 60 GNUNET_JSON_spec_json ("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 80 if (! TALER_MERCHANT_template_contract_valid (tp.template_contract)) 81 { 82 GNUNET_break_op (0); 83 GNUNET_JSON_parse_free (spec); 84 return TALER_MHD_reply_with_error (connection, 85 MHD_HTTP_BAD_REQUEST, 86 TALER_EC_GENERIC_PARAMETER_MALFORMED, 87 "template_contract"); 88 } 89 if (NULL != tp.editable_defaults) 90 { 91 const char *key; 92 json_t *val; 93 94 json_object_foreach (tp.editable_defaults, key, val) 95 { 96 if (NULL != 97 json_object_get (tp.template_contract, 98 key)) 99 { 100 char *msg; 101 enum MHD_Result ret; 102 103 GNUNET_break_op (0); 104 GNUNET_asprintf (&msg, 105 "editable_defaults::%s conflicts with template_contract", 106 key); 107 GNUNET_JSON_parse_free (spec); 108 ret = TALER_MHD_reply_with_error ( 109 connection, 110 MHD_HTTP_BAD_REQUEST, 111 TALER_EC_GENERIC_PARAMETER_MALFORMED, 112 msg); 113 GNUNET_free (msg); 114 return ret; 115 } 116 } 117 } 118 119 if (NULL != tp.otp_id) 120 { 121 uint64_t otp_serial; 122 123 /* Note: without this pre-check, an unknown @e otp_id would 124 simply resolve to NULL in the UPDATE and thus *silently* 125 remove the OTP device binding of the template. */ 126 qs = TALER_MERCHANTDB_get_otp_device_serial (TMH_db, 127 mi->settings.id, 128 tp.otp_id, 129 &otp_serial); 130 switch (qs) 131 { 132 case GNUNET_DB_STATUS_HARD_ERROR: 133 case GNUNET_DB_STATUS_SOFT_ERROR: 134 GNUNET_break (0); 135 GNUNET_JSON_parse_free (spec); 136 return TALER_MHD_reply_with_error (connection, 137 MHD_HTTP_INTERNAL_SERVER_ERROR, 138 TALER_EC_GENERIC_DB_FETCH_FAILED, 139 "get_otp_device_serial"); 140 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 141 GNUNET_JSON_parse_free (spec); 142 return TALER_MHD_reply_with_error (connection, 143 MHD_HTTP_NOT_FOUND, 144 TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN, 145 tp.otp_id); 146 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 147 break; 148 } 149 } 150 151 qs = TALER_MERCHANTDB_update_template (TMH_db, 152 mi->settings.id, 153 template_id, 154 &tp); 155 { 156 enum MHD_Result ret = MHD_NO; 157 158 switch (qs) 159 { 160 case GNUNET_DB_STATUS_HARD_ERROR: 161 GNUNET_break (0); 162 ret = TALER_MHD_reply_with_error ( 163 connection, 164 MHD_HTTP_INTERNAL_SERVER_ERROR, 165 TALER_EC_GENERIC_DB_STORE_FAILED, 166 NULL); 167 break; 168 case GNUNET_DB_STATUS_SOFT_ERROR: 169 GNUNET_break (0); 170 ret = TALER_MHD_reply_with_error ( 171 connection, 172 MHD_HTTP_INTERNAL_SERVER_ERROR, 173 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 174 "unexpected serialization problem"); 175 break; 176 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 177 ret = TALER_MHD_reply_with_error ( 178 connection, 179 MHD_HTTP_NOT_FOUND, 180 TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN, 181 template_id); 182 break; 183 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 184 ret = TALER_MHD_reply_static (connection, 185 MHD_HTTP_NO_CONTENT, 186 NULL, 187 NULL, 188 0); 189 break; 190 } 191 GNUNET_JSON_parse_free (spec); 192 return ret; 193 } 194 } 195 196 197 /* end of taler-merchant-httpd_patch-private-templates-TEMPLATE_ID.c */