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