taler-merchant-httpd_helper.h (14099B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2021-2023 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 Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero 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_helper.h 18 * @brief helpers for shared logic 19 * @author Florian Dold 20 * @author Benedikt Mueller 21 * @author Christian Grothoff 22 */ 23 #ifndef TALER_MERCHANT_HTTPD_HELPER_H 24 #define TALER_MERCHANT_HTTPD_HELPER_H 25 26 #define TMH_MAX_FRACTIONAL_PRECISION_LEVEL 6 27 28 29 #include "taler-merchant-httpd.h" 30 31 /** 32 * check @a accounts for well-formedness 33 * 34 * @param accounts JSON array of merchant accounts (presumably) 35 * @return true if they are all valid accounts 36 */ 37 bool 38 TMH_accounts_array_valid (const json_t *accounts); 39 40 41 /** 42 * Check if @a taxes is an array of valid Taxes in the sense of 43 * Taler's API definition. 44 * 45 * @param taxes array to check 46 * @return true if @a taxes is an array and all 47 * entries are valid Taxes. 48 */ 49 bool 50 TMH_taxes_array_valid (const json_t *taxes); 51 52 53 /** 54 * Check if @a location is a valid Location object in the sense of Taler's API 55 * definition. 56 * 57 * @param location object to check 58 * @return true if @a location is an object 59 * representing a Location. 60 */ 61 bool 62 TMH_location_object_valid (const json_t *location); 63 64 65 /** 66 * Check if @a products is an array of valid Product(s) in the sense of 67 * Taler's API definition. 68 * 69 * @param products array to check 70 * @return true if @a products is an array and all 71 * entries are valid Products. 72 */ 73 bool 74 TMH_products_array_valid (const json_t *products); 75 76 77 /** 78 * Parse decimal quantity expressed as string for request handling. 79 * 80 * @param value string to parse 81 * @param[out] integer_part result integer component 82 * @param[out] fractional_part result fractional component (0..MERCHANT_UNIT_FRAC_BASE-1) 83 * @return #GNUNET_OK on success, #GNUNET_SYSERR on validation failure 84 */ 85 enum GNUNET_GenericReturnValue 86 TMH_parse_fractional_string (const char *value, 87 int64_t *integer_part, 88 uint32_t *fractional_part); 89 90 /** 91 * Kind of fixed-decimal value the helpers operate on. 92 * Primarily distinguishes how special sentinel values (such as "-1" 93 * meaning infinity for stock) must be encoded. 94 */ 95 enum TMH_ValueKind 96 { 97 TMH_VK_QUANTITY, /* -1 is illegal */ 98 TMH_VK_STOCK /* -1 means "infinity" */ 99 }; 100 101 /** 102 * Extract a fixed-decimal number that may be supplied either 103 * - as pure integer (e.g. "total_stock"), or 104 * - as decimal text (e.g. "unit_total_stock"). 105 * 106 * Rules: 107 * - If both forms are missing -> error. 108 * - If both are present -> they must match and the decimal must have no fraction. 109 * - For kind == TMH_VK_STOCK the integer value -1 represents infinity. 110 * 111 * @param kind See #TMH_ValueKind 112 * @param allow_fractional False: any fractional part is rejected 113 * @param int_missing True if client omitted the integer field 114 * @param int_raw Raw integer (undefined if @a int_missing is true) 115 * @param str_missing True if client omitted the string field 116 * @param str_raw Raw UTF-8 string (undefined if @a str_missing is true) 117 * @param[out] int_out Canonicalised integer part 118 * @param[out] frac_out Canonicalised fractional part 119 * @param[out] error_param Set to offending field name on failure 120 * @param int_field Integer field name (for error reporting) 121 * @param str_field String field name (for error reporting) 122 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise 123 */ 124 enum GNUNET_GenericReturnValue 125 TMH_process_quantity_inputs (enum TMH_ValueKind kind, 126 bool allow_fractional, 127 bool int_missing, 128 int64_t int_raw, 129 bool str_missing, 130 const char *str_raw, 131 uint64_t *int_out, 132 uint32_t *frac_out, 133 const char **error_param); 134 135 /** 136 * Lookup the defaults for @a unit within @a mi and fall back to sane 137 * values (disallow fractional quantities, zero precision) if no data 138 * is available. 139 * 140 * @param mi merchant instance whose defaults should be consulted (must not be NULL) 141 * @param unit textual unit name (must not be NULL or empty) 142 * @param allow_fractional updated with whether fractional quantities are allowed (must not be NULL) 143 * @param precision_level updated with the supported precision (must not be NULL) 144 */ 145 void 146 TMH_quantity_defaults_from_unit (const struct TMH_MerchantInstance *mi, 147 const char *unit, 148 bool *allow_fractional, 149 uint32_t *precision_level); 150 151 /** 152 * Query the database for precision defaults tied to @a unit within 153 * @a mi. Returns #GNUNET_OK even if no unit information exists, in 154 * which case the out-parameters remain at their implicit defaults. 155 * 156 * @param mi merchant instance whose unit table is inspected (must not be NULL) 157 * @param unit textual unit name (must not be NULL or empty) 158 * @param allow_fractional updated with whether fractional quantities are allowed (must not be NULL) 159 * @param precision_level updated with the supported precision (must not be NULL) 160 * @return #GNUNET_OK on success, #GNUNET_SYSERR on database failure 161 */ 162 enum GNUNET_GenericReturnValue 163 TMH_unit_defaults_for_instance (const struct TMH_MerchantInstance *mi, 164 const char *unit, 165 bool *allow_fractional, 166 uint32_t *precision_level); 167 168 /** 169 * Format a fixed-decimal pair into canonical string representation. 170 * Recognises INT64_MAX / INT32_MAX as the "-1" sentinel used for 171 * infinite stock if @a kind equals #TMH_VK_STOCK. 172 * 173 * @param kind specifies whether sentinel values are permitted 174 * @param integer integer portion 175 * @param fractional fractional portion (0..MERCHANT_UNIT_FRAC_BASE-1 or sentinel) 176 * @param buffer output buffer 177 * @param buffer_length length of @a buffer 178 */ 179 void 180 TMH_format_fractional_string (enum TMH_ValueKind kind, 181 uint64_t integer, 182 uint32_t fractional, 183 size_t buffer_length, 184 char buffer[static buffer_length]); 185 186 /** 187 * Check if @a image_data_url is a valid image 188 * data URL. Does not validate the actual payload, 189 * only the syntax and that it properly claims to 190 * be an image. 191 * 192 * @param image_data_url string to check 193 * @return true if @a image_data_url is a data 194 * URL with an "image/" mime-type 195 */ 196 bool 197 TMH_image_data_url_valid (const char *image_data_url); 198 199 200 /** 201 * Check if @a template_contract is a valid template_contract object in the sense of Taler's API 202 * definition. 203 * 204 * @param template_contract object to check 205 * @return true if @a template_location is an object 206 * representing a template_location. 207 */ 208 bool 209 TMH_template_contract_valid (const json_t *template_contract); 210 211 212 /** 213 * Setup new wire method for the given @ payto_uri. 214 * 215 * @param payto_uri already validated payto URI 216 * @param credit_facade_url where to download credit information for this account (can be NULL) 217 * @param credit_facade_credentials credentials for the @a credit_facade_url 218 * @return new wire method object, never fails 219 */ 220 struct TMH_WireMethod * 221 TMH_setup_wire_account ( 222 struct TALER_FullPayto payto_uri, 223 const char *credit_facade_url, 224 const json_t *credit_facade_credentials); 225 226 227 /** 228 * Test if JSON spec @a account for a wire method is equal to the given @a wm. 229 * 230 * @param account JSON spec for a merchant account 231 * @param wm known wire method 232 * @return #GNUNET_YES if both specifications are equal 233 * #GNUNET_NO if the specifications are for 234 * the same account but differ in the credit facade 235 * #GNUNET_SYSERR if the specs are for different accounts 236 * or if @a account is malformed 237 */ 238 enum GNUNET_GenericReturnValue 239 TMH_cmp_wire_account ( 240 const json_t *account, 241 const struct TMH_WireMethod *wm); 242 243 244 /** 245 * Check that the provided authentication configuration 246 * is valid. 247 * 248 * @param connection connection to use for returning errors 249 * @param jauth JSON with authentication data 250 * @param[out] auth_token set to the authentication token 251 * @return #GNUNET_OK on success, 252 * #GNUNET_NO if an error was returned on @a connection 253 * #GNUNET_SYSERR if we failed to return an error on @a connection 254 */ 255 enum GNUNET_GenericReturnValue 256 TMH_check_auth_config (struct MHD_Connection *connection, 257 const json_t *jauth, 258 const char **auth_token); 259 260 261 /** 262 * Generate binary UUID from client-provided UUID-string. 263 * 264 * @param uuids string intpu 265 * @param[out] uuid set to binary UUID 266 */ 267 void 268 TMH_uuid_from_string (const char *uuids, 269 struct GNUNET_Uuid *uuid); 270 271 272 /** 273 * Initializes a buffer with 274 * the ``http[s]://$HOST/[$PATH/][instances/$INSTANCE/]`` 275 * string using $HOST and $PATH from @a connection. 276 * 277 * @param[in] connection connection to base the construction on 278 * @param instance instance to set, NULL for none 279 * @param[out] buf buffer to initialize 280 * @return #GNUNET_OK on success 281 */ 282 enum GNUNET_GenericReturnValue 283 TMH_base_url_by_connection (struct MHD_Connection *connection, 284 const char *instance, 285 struct GNUNET_Buffer *buf); 286 287 288 /** 289 * Initializes a buffer with 290 * the ``taler[+http]://$METHOD/$HOST/[instances/$INSTANCE/]`` 291 * string using $HOST from @a connection. 292 * 293 * @param[in] connection connection to base the construction on 294 * @param method taler-URI method to inject 295 * @param instance instance to set, NULL for none 296 * @param[out] buf buffer to initialize 297 * @return #GNUNET_OK on success 298 */ 299 enum GNUNET_GenericReturnValue 300 TMH_taler_uri_by_connection (struct MHD_Connection *connection, 301 const char *method, 302 const char *instance, 303 struct GNUNET_Buffer *buf); 304 305 306 /** 307 * Create a taler://pay/ URI for the given @a con and @a order_id 308 * and @a session_id and @a instance_id. 309 * 310 * @param con HTTP connection 311 * @param order_id the order id 312 * @param session_id session, may be NULL 313 * @param instance_id instance, may be "default" 314 * @param claim_token claim token for the order, may be NULL 315 * @return corresponding taler://pay/ URI, or NULL on missing "host" 316 */ 317 char * 318 TMH_make_taler_pay_uri (struct MHD_Connection *con, 319 const char *order_id, 320 const char *session_id, 321 const char *instance_id, 322 struct TALER_ClaimTokenP *claim_token); 323 324 /** 325 * Create a http(s) URL for the given @a con and @a order_id 326 * and @a instance_id to display the /orders/{order_id} page. 327 * 328 * @param con HTTP connection 329 * @param order_id the order id 330 * @param session_id session, may be NULL 331 * @param instance_id instance, may be "default" 332 * @param claim_token claim token for the order, may be NULL 333 * @param h_contract contract hash for authentication, may be NULL 334 * @return corresponding http(s):// URL, or NULL on missing "host" 335 */ 336 char * 337 TMH_make_order_status_url (struct MHD_Connection *con, 338 const char *order_id, 339 const char *session_id, 340 const char *instance_id, 341 struct TALER_ClaimTokenP *claim_token, 342 struct TALER_PrivateContractHashP *h_contract); 343 344 345 /** 346 * Put data from an exchange's HTTP response into 347 * a JSON reply 348 * 349 * @param hr a `TALER_EXCHANGE_HttpResponse` 350 */ 351 #define TMH_pack_exchange_reply(hr) \ 352 GNUNET_JSON_pack_uint64 ("exchange_code", (hr)->ec), \ 353 GNUNET_JSON_pack_uint64 ("exchange_http_status", (hr)->http_status), \ 354 GNUNET_JSON_pack_uint64 ("exchange_ec", (hr)->ec), /* LEGACY */ \ 355 GNUNET_JSON_pack_uint64 ("exchange_hc", (hr)->http_status), /* LEGACY */ \ 356 GNUNET_JSON_pack_allow_null ( \ 357 GNUNET_JSON_pack_object_incref ("exchange_reply", (json_t *) (hr)-> \ 358 reply)) 359 360 361 /** 362 * TMH_trigger_webhook is a function that need to be use when someone 363 * pay. Merchant need to have a notification. 364 * 365 * @param instance that we need to send the webhook as a notification 366 * @param event of the webhook 367 * @param args argument of the function 368 */ 369 enum GNUNET_DB_QueryStatus 370 TMH_trigger_webhook (const char *instance, 371 const char *action, 372 const json_t *args); 373 374 375 /** 376 * Return JSON array with all of the exchange accounts 377 * that support the given @a wire_method. 378 * 379 * @param master_pub master public key to match exchange by 380 * @param wire_method NULL for any 381 * @return JSON array with information about all matching accounts 382 */ 383 json_t * 384 TMH_exchange_accounts_by_method ( 385 const struct TALER_MasterPublicKeyP *master_pub, 386 const char *wire_method); 387 388 /** 389 * Check validity of login @a token for the given @a instance_id. 390 * 391 * @param token the login token given in the request 392 * @param instance_id the instance the login is to be checked against 393 * @param[out] as set to scope of the token if it is valid 394 * @return TALER_EC_NONE on success 395 */ 396 enum TALER_ErrorCode 397 TMH_check_token (const char *token, 398 const char *instance_id, 399 enum TMH_AuthScope *as); 400 401 #endif