taler-merchant-httpd_patch-private-units-UNIT.c (8455B)
1 /* 2 This file is part of TALER 3 (C) 2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file src/backend/taler-merchant-httpd_patch-private-units-UNIT.c 18 * @brief implement PATCH /private/units/$UNIT 19 * @author Bohdan Potuzhnyi 20 */ 21 #include "platform.h" 22 #include "taler-merchant-httpd_patch-private-units-UNIT.h" 23 #include "taler-merchant-httpd_helper.h" 24 #include <taler/taler_json_lib.h> 25 #include "merchant-database/update_unit.h" 26 27 #define TMH_MAX_UNIT_PRECISION_LEVEL 6 28 29 30 enum MHD_Result 31 TMH_private_patch_units_ID (const struct TMH_RequestHandler *rh, 32 struct MHD_Connection *connection, 33 struct TMH_HandlerContext *hc) 34 { 35 struct TMH_MerchantInstance *mi = hc->instance; 36 const char *unit_id = hc->infix; 37 struct TALER_MERCHANTDB_UnitDetails nud = { 0 }; 38 bool unit_allow_fraction_missing = true; 39 bool unit_precision_missing = true; 40 bool unit_active_missing = true; 41 struct GNUNET_JSON_Specification spec[] = { 42 GNUNET_JSON_spec_mark_optional ( 43 GNUNET_JSON_spec_string ("unit_name_long", 44 (const char **) &nud.unit_name_long), 45 NULL), 46 GNUNET_JSON_spec_mark_optional ( 47 GNUNET_JSON_spec_json ("unit_name_long_i18n", 48 &nud.unit_name_long_i18n), 49 NULL), 50 GNUNET_JSON_spec_mark_optional ( 51 GNUNET_JSON_spec_string ("unit_name_short", 52 (const char **) &nud.unit_name_short), 53 NULL), 54 GNUNET_JSON_spec_mark_optional ( 55 GNUNET_JSON_spec_json ("unit_name_short_i18n", 56 &nud.unit_name_short_i18n), 57 NULL), 58 GNUNET_JSON_spec_mark_optional ( 59 GNUNET_JSON_spec_bool ("unit_allow_fraction", 60 &nud.unit_allow_fraction), 61 &unit_allow_fraction_missing), 62 GNUNET_JSON_spec_mark_optional ( 63 GNUNET_JSON_spec_uint32 ("unit_precision_level", 64 &nud.unit_precision_level), 65 &unit_precision_missing), 66 GNUNET_JSON_spec_mark_optional ( 67 GNUNET_JSON_spec_bool ("unit_active", 68 &nud.unit_active), 69 &unit_active_missing), 70 GNUNET_JSON_spec_end () 71 }; 72 enum GNUNET_GenericReturnValue res; 73 const bool *unit_allow_fraction_ptr = NULL; 74 const uint32_t *unit_precision_ptr = NULL; 75 const bool *unit_active_ptr = NULL; 76 enum GNUNET_DB_QueryStatus qs; 77 bool no_instance = false; 78 bool no_unit = false; 79 bool builtin_conflict = false; 80 enum MHD_Result ret = MHD_YES; 81 82 (void) rh; 83 GNUNET_assert (NULL != mi); 84 GNUNET_assert (NULL != unit_id); 85 86 res = TALER_MHD_parse_json_data (connection, 87 hc->request_body, 88 spec); 89 if (GNUNET_OK != res) 90 return (GNUNET_NO == res) ? MHD_YES : MHD_NO; 91 92 if (NULL == nud.unit_name_long && 93 NULL == nud.unit_name_long_i18n && 94 NULL == nud.unit_name_short && 95 NULL == nud.unit_name_short_i18n && 96 unit_allow_fraction_missing && 97 unit_precision_missing && 98 unit_active_missing) 99 { 100 ret = TALER_MHD_reply_static (connection, 101 MHD_HTTP_NO_CONTENT, 102 NULL, 103 NULL, 104 0); 105 goto cleanup; 106 } 107 108 if (! unit_precision_missing) 109 { 110 if (nud.unit_precision_level > TMH_MAX_UNIT_PRECISION_LEVEL) 111 { 112 GNUNET_break_op (0); 113 ret = TALER_MHD_reply_with_error (connection, 114 MHD_HTTP_BAD_REQUEST, 115 TALER_EC_GENERIC_PARAMETER_MALFORMED, 116 "unit_precision_level"); 117 goto cleanup; 118 } 119 unit_precision_ptr = &nud.unit_precision_level; 120 } 121 122 if (! unit_allow_fraction_missing) 123 { 124 unit_allow_fraction_ptr = &nud.unit_allow_fraction; 125 if (! nud.unit_allow_fraction) 126 { 127 nud.unit_precision_level = 0; 128 unit_precision_missing = false; 129 unit_precision_ptr = &nud.unit_precision_level; 130 } 131 } 132 133 if (! unit_active_missing) 134 unit_active_ptr = &nud.unit_active; 135 136 if (NULL != nud.unit_name_long_i18n) 137 { 138 if (! TALER_JSON_check_i18n (nud.unit_name_long_i18n)) 139 { 140 GNUNET_break_op (0); 141 ret = TALER_MHD_reply_with_error (connection, 142 MHD_HTTP_BAD_REQUEST, 143 TALER_EC_GENERIC_PARAMETER_MALFORMED, 144 "unit_name_long_i18n"); 145 goto cleanup; 146 } 147 } 148 149 if (NULL != nud.unit_name_short_i18n) 150 { 151 if (! TALER_JSON_check_i18n (nud.unit_name_short_i18n)) 152 { 153 GNUNET_break_op (0); 154 ret = TALER_MHD_reply_with_error (connection, 155 MHD_HTTP_BAD_REQUEST, 156 TALER_EC_GENERIC_PARAMETER_MALFORMED, 157 "unit_name_short_i18n"); 158 goto cleanup; 159 } 160 } 161 162 qs = TALER_MERCHANTDB_update_unit (TMH_db, 163 mi->settings.id, 164 unit_id, 165 nud.unit_name_long, 166 nud.unit_name_long_i18n, 167 nud.unit_name_short, 168 nud.unit_name_short_i18n, 169 unit_allow_fraction_ptr, 170 unit_precision_ptr, 171 unit_active_ptr, 172 &no_instance, 173 &no_unit, 174 &builtin_conflict); 175 switch (qs) 176 { 177 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 178 break; 179 case GNUNET_DB_STATUS_SOFT_ERROR: 180 GNUNET_break (0); 181 ret = TALER_MHD_reply_with_error (connection, 182 MHD_HTTP_INTERNAL_SERVER_ERROR, 183 TALER_EC_GENERIC_DB_SOFT_FAILURE, 184 "update_unit"); 185 goto cleanup; 186 case GNUNET_DB_STATUS_HARD_ERROR: 187 default: 188 GNUNET_break (0); 189 ret = TALER_MHD_reply_with_error (connection, 190 MHD_HTTP_INTERNAL_SERVER_ERROR, 191 TALER_EC_GENERIC_DB_STORE_FAILED, 192 "update_unit"); 193 goto cleanup; 194 } 195 196 if (no_instance) 197 { 198 ret = TALER_MHD_reply_with_error (connection, 199 MHD_HTTP_NOT_FOUND, 200 TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN, 201 mi->settings.id); 202 goto cleanup; 203 } 204 if (no_unit) 205 { 206 ret = TALER_MHD_reply_with_error (connection, 207 MHD_HTTP_NOT_FOUND, 208 TALER_EC_MERCHANT_GENERIC_UNIT_UNKNOWN, 209 unit_id); 210 goto cleanup; 211 } 212 if (builtin_conflict) 213 { 214 ret = TALER_MHD_reply_with_error (connection, 215 MHD_HTTP_CONFLICT, 216 TALER_EC_MERCHANT_GENERIC_UNIT_BUILTIN, 217 unit_id); 218 goto cleanup; 219 } 220 221 ret = TALER_MHD_reply_static (connection, 222 MHD_HTTP_NO_CONTENT, 223 NULL, 224 NULL, 225 0); 226 227 cleanup: 228 if (NULL != nud.unit_name_long_i18n) 229 { 230 json_decref (nud.unit_name_long_i18n); 231 nud.unit_name_long_i18n = NULL; 232 } 233 if (NULL != nud.unit_name_short_i18n) 234 { 235 json_decref (nud.unit_name_short_i18n); 236 nud.unit_name_short_i18n = NULL; 237 } 238 GNUNET_JSON_parse_free (spec); 239 return ret; 240 } 241 242 243 /* end of taler-merchant-httpd_patch-private-units-UNIT.c */