taler-merchant-httpd_private-patch-units-ID.c (8272B)
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 taler-merchant-httpd_private-patch-units-ID.c 18 * @brief implement PATCH /private/units/$UNIT 19 * @author Bohdan Potuzhnyi 20 */ 21 #include "platform.h" 22 #include "taler-merchant-httpd_private-patch-units-ID.h" 23 #include "taler-merchant-httpd_helper.h" 24 #include <taler/taler_json_lib.h> 25 26 #define TMH_MAX_UNIT_PRECISION_LEVEL 6 27 28 29 MHD_RESULT 30 TMH_private_patch_units_ID (const struct TMH_RequestHandler *rh, 31 struct MHD_Connection *connection, 32 struct TMH_HandlerContext *hc) 33 { 34 struct TMH_MerchantInstance *mi = hc->instance; 35 const char *unit_id = hc->infix; 36 struct TALER_MERCHANTDB_UnitDetails nud = { 0 }; 37 bool unit_allow_fraction_missing = true; 38 bool unit_precision_missing = true; 39 bool unit_active_missing = true; 40 struct GNUNET_JSON_Specification spec[] = { 41 GNUNET_JSON_spec_mark_optional ( 42 GNUNET_JSON_spec_string ("unit_name_long", 43 (const char **) &nud.unit_name_long), 44 NULL), 45 GNUNET_JSON_spec_mark_optional ( 46 GNUNET_JSON_spec_json ("unit_name_long_i18n", 47 &nud.unit_name_long_i18n), 48 NULL), 49 GNUNET_JSON_spec_mark_optional ( 50 GNUNET_JSON_spec_string ("unit_name_short", 51 (const char **) &nud.unit_name_short), 52 NULL), 53 GNUNET_JSON_spec_mark_optional ( 54 GNUNET_JSON_spec_json ("unit_name_short_i18n", 55 &nud.unit_name_short_i18n), 56 NULL), 57 GNUNET_JSON_spec_mark_optional ( 58 GNUNET_JSON_spec_bool ("unit_allow_fraction", 59 &nud.unit_allow_fraction), 60 &unit_allow_fraction_missing), 61 GNUNET_JSON_spec_mark_optional ( 62 GNUNET_JSON_spec_uint32 ("unit_precision_level", 63 &nud.unit_precision_level), 64 &unit_precision_missing), 65 GNUNET_JSON_spec_mark_optional ( 66 GNUNET_JSON_spec_bool ("unit_active", 67 &nud.unit_active), 68 &unit_active_missing), 69 GNUNET_JSON_spec_end () 70 }; 71 enum GNUNET_GenericReturnValue res; 72 const bool *unit_allow_fraction_ptr = NULL; 73 const uint32_t *unit_precision_ptr = NULL; 74 const bool *unit_active_ptr = NULL; 75 enum GNUNET_DB_QueryStatus qs; 76 bool no_instance = false; 77 bool no_unit = false; 78 bool builtin_conflict = false; 79 MHD_RESULT ret = MHD_YES; 80 81 (void) rh; 82 GNUNET_assert (NULL != mi); 83 GNUNET_assert (NULL != unit_id); 84 85 res = TALER_MHD_parse_json_data (connection, 86 hc->request_body, 87 spec); 88 if (GNUNET_OK != res) 89 return (GNUNET_NO == res) ? MHD_YES : MHD_NO; 90 91 if (NULL == nud.unit_name_long && 92 NULL == nud.unit_name_long_i18n && 93 NULL == nud.unit_name_short && 94 NULL == nud.unit_name_short_i18n && 95 unit_allow_fraction_missing && 96 unit_precision_missing && 97 unit_active_missing) 98 { 99 ret = TALER_MHD_reply_static (connection, 100 MHD_HTTP_NO_CONTENT, 101 NULL, 102 NULL, 103 0); 104 goto cleanup; 105 } 106 107 if (! unit_precision_missing) 108 { 109 if (nud.unit_precision_level > TMH_MAX_UNIT_PRECISION_LEVEL) 110 { 111 GNUNET_break_op (0); 112 ret = TALER_MHD_reply_with_error (connection, 113 MHD_HTTP_BAD_REQUEST, 114 TALER_EC_GENERIC_PARAMETER_MALFORMED, 115 "unit_precision_level"); 116 goto cleanup; 117 } 118 unit_precision_ptr = &nud.unit_precision_level; 119 } 120 121 if (! unit_allow_fraction_missing) 122 { 123 unit_allow_fraction_ptr = &nud.unit_allow_fraction; 124 if (! nud.unit_allow_fraction) 125 { 126 nud.unit_precision_level = 0; 127 unit_precision_missing = false; 128 unit_precision_ptr = &nud.unit_precision_level; 129 } 130 } 131 132 if (! unit_active_missing) 133 unit_active_ptr = &nud.unit_active; 134 135 if (NULL != nud.unit_name_long_i18n) 136 { 137 if (! TALER_JSON_check_i18n (nud.unit_name_long_i18n)) 138 { 139 GNUNET_break_op (0); 140 ret = TALER_MHD_reply_with_error (connection, 141 MHD_HTTP_BAD_REQUEST, 142 TALER_EC_GENERIC_PARAMETER_MALFORMED, 143 "unit_name_long_i18n"); 144 goto cleanup; 145 } 146 } 147 148 if (NULL != nud.unit_name_short_i18n) 149 { 150 if (! TALER_JSON_check_i18n (nud.unit_name_short_i18n)) 151 { 152 GNUNET_break_op (0); 153 ret = TALER_MHD_reply_with_error (connection, 154 MHD_HTTP_BAD_REQUEST, 155 TALER_EC_GENERIC_PARAMETER_MALFORMED, 156 "unit_name_short_i18n"); 157 goto cleanup; 158 } 159 } 160 161 qs = TMH_db->update_unit (TMH_db->cls, 162 mi->settings.id, 163 unit_id, 164 nud.unit_name_long, 165 nud.unit_name_long_i18n, 166 nud.unit_name_short, 167 nud.unit_name_short_i18n, 168 unit_allow_fraction_ptr, 169 unit_precision_ptr, 170 unit_active_ptr, 171 &no_instance, 172 &no_unit, 173 &builtin_conflict); 174 switch (qs) 175 { 176 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 177 break; 178 case GNUNET_DB_STATUS_SOFT_ERROR: 179 GNUNET_break (0); 180 ret = TALER_MHD_reply_with_error (connection, 181 MHD_HTTP_INTERNAL_SERVER_ERROR, 182 TALER_EC_GENERIC_DB_SOFT_FAILURE, 183 "update_unit"); 184 goto cleanup; 185 case GNUNET_DB_STATUS_HARD_ERROR: 186 default: 187 GNUNET_break (0); 188 ret = TALER_MHD_reply_with_error (connection, 189 MHD_HTTP_INTERNAL_SERVER_ERROR, 190 TALER_EC_GENERIC_DB_STORE_FAILED, 191 "update_unit"); 192 goto cleanup; 193 } 194 195 if (no_instance) 196 { 197 ret = TALER_MHD_reply_with_error (connection, 198 MHD_HTTP_NOT_FOUND, 199 TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN, 200 mi->settings.id); 201 goto cleanup; 202 } 203 if (no_unit) 204 { 205 ret = TALER_MHD_reply_with_error (connection, 206 MHD_HTTP_NOT_FOUND, 207 TALER_EC_MERCHANT_GENERIC_UNIT_UNKNOWN, 208 unit_id); 209 goto cleanup; 210 } 211 if (builtin_conflict) 212 { 213 ret = TALER_MHD_reply_with_error (connection, 214 MHD_HTTP_CONFLICT, 215 TALER_EC_MERCHANT_GENERIC_UNIT_BUILTIN, 216 unit_id); 217 goto cleanup; 218 } 219 220 ret = TALER_MHD_reply_static (connection, 221 MHD_HTTP_NO_CONTENT, 222 NULL, 223 NULL, 224 0); 225 226 cleanup: 227 if (NULL != nud.unit_name_long_i18n) 228 { 229 json_decref (nud.unit_name_long_i18n); 230 nud.unit_name_long_i18n = NULL; 231 } 232 if (NULL != nud.unit_name_short_i18n) 233 { 234 json_decref (nud.unit_name_short_i18n); 235 nud.unit_name_short_i18n = NULL; 236 } 237 GNUNET_JSON_parse_free (spec); 238 return ret; 239 } 240 241 242 /* end of taler-merchant-httpd_private-patch-units-ID.c */