taler-merchant-httpd_private-patch-templates-ID.c (7584B)
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 taler-merchant-httpd_private-patch-templates-ID.c 22 * @brief implementing PATCH /templates/$ID request handling 23 * @author Priscilla HUANG 24 */ 25 #include "platform.h" 26 #include "taler-merchant-httpd_private-patch-templates-ID.h" 27 #include "taler-merchant-httpd_helper.h" 28 #include <taler/taler_json_lib.h> 29 30 31 /** 32 * Determine the cause of the PATCH failure in more detail and report. 33 * 34 * @param connection connection to report on 35 * @param instance_id instance we are processing 36 * @param template_id ID of the product to patch 37 * @param tp template details we failed to set 38 */ 39 static MHD_RESULT 40 determine_cause (struct MHD_Connection *connection, 41 const char *instance_id, 42 const char *template_id, 43 const struct TALER_MERCHANTDB_TemplateDetails *tp) 44 { 45 struct TALER_MERCHANTDB_TemplateDetails tpx; 46 enum GNUNET_DB_QueryStatus qs; 47 48 qs = TMH_db->lookup_template (TMH_db->cls, 49 instance_id, 50 template_id, 51 &tpx); 52 switch (qs) 53 { 54 case GNUNET_DB_STATUS_HARD_ERROR: 55 GNUNET_break (0); 56 return TALER_MHD_reply_with_error (connection, 57 MHD_HTTP_INTERNAL_SERVER_ERROR, 58 TALER_EC_GENERIC_DB_FETCH_FAILED, 59 NULL); 60 case GNUNET_DB_STATUS_SOFT_ERROR: 61 GNUNET_break (0); 62 return TALER_MHD_reply_with_error (connection, 63 MHD_HTTP_INTERNAL_SERVER_ERROR, 64 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 65 "unexpected serialization problem"); 66 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 67 return TALER_MHD_reply_with_error (connection, 68 MHD_HTTP_NOT_FOUND, 69 TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN, 70 template_id); 71 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 72 break; /* do below */ 73 } 74 75 { 76 enum TALER_ErrorCode ec; 77 78 ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 79 TALER_MERCHANTDB_template_details_free (&tpx); 80 GNUNET_break (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE != ec); 81 return TALER_MHD_reply_with_error (connection, 82 MHD_HTTP_CONFLICT, 83 ec, 84 NULL); 85 } 86 } 87 88 89 /** 90 * PATCH configuration of an existing instance, given its configuration. 91 * 92 * @param rh context of the handler 93 * @param connection the MHD connection to handle 94 * @param[in,out] hc context with further information about the request 95 * @return MHD result code 96 */ 97 MHD_RESULT 98 TMH_private_patch_templates_ID (const struct TMH_RequestHandler *rh, 99 struct MHD_Connection *connection, 100 struct TMH_HandlerContext *hc) 101 { 102 struct TMH_MerchantInstance *mi = hc->instance; 103 const char *template_id = hc->infix; 104 struct TALER_MERCHANTDB_TemplateDetails tp = {0}; 105 enum GNUNET_DB_QueryStatus qs; 106 struct GNUNET_JSON_Specification spec[] = { 107 GNUNET_JSON_spec_string ("template_description", 108 (const char **) &tp.template_description), 109 GNUNET_JSON_spec_mark_optional ( 110 GNUNET_JSON_spec_string ("otp_id", 111 (const char **) &tp.otp_id), 112 NULL), 113 GNUNET_JSON_spec_json ("template_contract", 114 &tp.template_contract), 115 GNUNET_JSON_spec_mark_optional ( 116 GNUNET_JSON_spec_json ("editable_defaults", 117 &tp.editable_defaults), 118 NULL), 119 GNUNET_JSON_spec_end () 120 }; 121 122 GNUNET_assert (NULL != mi); 123 GNUNET_assert (NULL != template_id); 124 { 125 enum GNUNET_GenericReturnValue res; 126 127 res = TALER_MHD_parse_json_data (connection, 128 hc->request_body, 129 spec); 130 if (GNUNET_OK != res) 131 return (GNUNET_NO == res) 132 ? MHD_YES 133 : MHD_NO; 134 } 135 136 if (! TMH_template_contract_valid (tp.template_contract)) 137 { 138 GNUNET_break_op (0); 139 GNUNET_JSON_parse_free (spec); 140 return TALER_MHD_reply_with_error (connection, 141 MHD_HTTP_BAD_REQUEST, 142 TALER_EC_GENERIC_PARAMETER_MALFORMED, 143 "template_contract"); 144 } 145 if (NULL != tp.editable_defaults) 146 { 147 const char *key; 148 json_t *val; 149 150 json_object_foreach (tp.editable_defaults, key, val) 151 { 152 if (NULL != 153 json_object_get (tp.template_contract, 154 key)) 155 { 156 char *msg; 157 MHD_RESULT ret; 158 159 GNUNET_break_op (0); 160 GNUNET_asprintf (&msg, 161 "editable_defaults::%s conflicts with template_contract", 162 key); 163 GNUNET_JSON_parse_free (spec); 164 ret = TALER_MHD_reply_with_error (connection, 165 MHD_HTTP_BAD_REQUEST, 166 TALER_EC_GENERIC_PARAMETER_MALFORMED, 167 msg); 168 GNUNET_free (msg); 169 return ret; 170 } 171 } 172 } 173 174 qs = TMH_db->update_template (TMH_db->cls, 175 mi->settings.id, 176 template_id, 177 &tp); 178 { 179 MHD_RESULT ret = MHD_NO; 180 181 switch (qs) 182 { 183 case GNUNET_DB_STATUS_HARD_ERROR: 184 GNUNET_break (0); 185 ret = TALER_MHD_reply_with_error (connection, 186 MHD_HTTP_INTERNAL_SERVER_ERROR, 187 TALER_EC_GENERIC_DB_STORE_FAILED, 188 NULL); 189 break; 190 case GNUNET_DB_STATUS_SOFT_ERROR: 191 GNUNET_break (0); 192 ret = TALER_MHD_reply_with_error (connection, 193 MHD_HTTP_INTERNAL_SERVER_ERROR, 194 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, 195 "unexpected serialization problem"); 196 break; 197 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 198 ret = determine_cause (connection, 199 mi->settings.id, 200 template_id, 201 &tp); 202 break; 203 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 204 ret = TALER_MHD_reply_static (connection, 205 MHD_HTTP_NO_CONTENT, 206 NULL, 207 NULL, 208 0); 209 break; 210 } 211 GNUNET_JSON_parse_free (spec); 212 return ret; 213 } 214 } 215 216 217 /* end of taler-merchant-httpd_private-patch-templates-ID.c */