merchant_api_patch-private-orders-ORDER_ID-forget.c (8129B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2020-2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Lesser General Public License as 7 published by the Free Software Foundation; either version 2.1, 8 or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General 16 Public License along with TALER; see the file COPYING.LGPL. 17 If not, see <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file merchant_api_patch-private-orders-ORDER_ID-forget-new.c 21 * @brief Implementation of the PATCH /private/orders/$ORDER_ID/forget request 22 * @author Jonathan Buchanan 23 */ 24 #include "taler/platform.h" 25 #include <curl/curl.h> 26 #include <jansson.h> 27 #include <microhttpd.h> /* just for HTTP status codes */ 28 #include <gnunet/gnunet_util_lib.h> 29 #include <gnunet/gnunet_curl_lib.h> 30 #include <taler/taler-merchant/patch-private-orders-ORDER_ID-forget.h> 31 #include "merchant_api_curl_defaults.h" 32 #include "merchant_api_common.h" 33 #include <taler/taler_json_lib.h> 34 #include <taler/taler_curl_lib.h> 35 36 37 /** 38 * Handle for a PATCH /private/orders/$ORDER_ID/forget operation. 39 */ 40 struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle 41 { 42 /** 43 * Base URL of the merchant backend. 44 */ 45 char *base_url; 46 47 /** 48 * The full URL for this request. 49 */ 50 char *url; 51 52 /** 53 * Handle for the request. 54 */ 55 struct GNUNET_CURL_Job *job; 56 57 /** 58 * Function to call with the result. 59 */ 60 TALER_MERCHANT_PatchPrivateOrdersForgetCallback cb; 61 62 /** 63 * Closure for @a cb. 64 */ 65 TALER_MERCHANT_PATCH_PRIVATE_ORDERS_FORGET_RESULT_CLOSURE *cb_cls; 66 67 /** 68 * Reference to the execution context. 69 */ 70 struct GNUNET_CURL_Context *ctx; 71 72 /** 73 * Minor context that holds body and headers. 74 */ 75 struct TALER_CURL_PostContext post_ctx; 76 77 /** 78 * Order identifier. 79 */ 80 char *order_id; 81 82 /** 83 * Array of JSON pointer paths to redact. 84 */ 85 char **fields; 86 87 /** 88 * Number of entries in @e fields. 89 */ 90 unsigned int fields_length; 91 }; 92 93 94 /** 95 * Function called when we're done processing the 96 * HTTP PATCH /private/orders/$ORDER_ID/forget request. 97 * 98 * @param cls the `struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle` 99 * @param response_code HTTP response code, 0 on error 100 * @param response response body, NULL if not in JSON 101 */ 102 static void 103 handle_patch_orders_forget_finished (void *cls, 104 long response_code, 105 const void *response) 106 { 107 struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *ofh = cls; 108 const json_t *json = response; 109 struct TALER_MERCHANT_PatchPrivateOrdersForgetResponse por = { 110 .hr.http_status = (unsigned int) response_code, 111 .hr.reply = json 112 }; 113 114 ofh->job = NULL; 115 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 116 "PATCH /private/orders/$ORDER_ID/forget completed with response code %u\n", 117 (unsigned int) response_code); 118 switch (response_code) 119 { 120 case 0: 121 por.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 122 break; 123 case MHD_HTTP_OK: 124 /* fields were NOW forgotten */ 125 break; 126 case MHD_HTTP_NO_CONTENT: 127 /* fields were already forgotten before */ 128 break; 129 case MHD_HTTP_BAD_REQUEST: 130 por.hr.ec = TALER_JSON_get_error_code (json); 131 por.hr.hint = TALER_JSON_get_error_hint (json); 132 break; 133 case MHD_HTTP_UNAUTHORIZED: 134 por.hr.ec = TALER_JSON_get_error_code (json); 135 por.hr.hint = TALER_JSON_get_error_hint (json); 136 break; 137 case MHD_HTTP_NOT_FOUND: 138 por.hr.ec = TALER_JSON_get_error_code (json); 139 por.hr.hint = TALER_JSON_get_error_hint (json); 140 break; 141 case MHD_HTTP_CONFLICT: 142 por.hr.ec = TALER_JSON_get_error_code (json); 143 por.hr.hint = TALER_JSON_get_error_hint (json); 144 break; 145 case MHD_HTTP_INTERNAL_SERVER_ERROR: 146 por.hr.ec = TALER_JSON_get_error_code (json); 147 por.hr.hint = TALER_JSON_get_error_hint (json); 148 break; 149 default: 150 TALER_MERCHANT_parse_error_details_ (json, 151 response_code, 152 &por.hr); 153 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 154 "Unexpected response code %u/%d\n", 155 (unsigned int) response_code, 156 (int) por.hr.ec); 157 GNUNET_break_op (0); 158 break; 159 } 160 ofh->cb (ofh->cb_cls, 161 &por); 162 TALER_MERCHANT_patch_private_orders_forget_cancel (ofh); 163 } 164 165 166 struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle * 167 TALER_MERCHANT_patch_private_orders_forget_create ( 168 struct GNUNET_CURL_Context *ctx, 169 const char *url, 170 const char *order_id, 171 unsigned int fields_length, 172 const char *fields[static fields_length]) 173 { 174 struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *ofh; 175 176 ofh = GNUNET_new (struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle); 177 ofh->ctx = ctx; 178 ofh->base_url = GNUNET_strdup (url); 179 ofh->order_id = GNUNET_strdup (order_id); 180 ofh->fields_length = fields_length; 181 ofh->fields = GNUNET_new_array (fields_length, 182 char *); 183 for (unsigned int i = 0; i < fields_length; i++) 184 ofh->fields[i] = GNUNET_strdup (fields[i]); 185 return ofh; 186 } 187 188 189 enum TALER_ErrorCode 190 TALER_MERCHANT_patch_private_orders_forget_start ( 191 struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *ofh, 192 TALER_MERCHANT_PatchPrivateOrdersForgetCallback cb, 193 TALER_MERCHANT_PATCH_PRIVATE_ORDERS_FORGET_RESULT_CLOSURE *cb_cls) 194 { 195 json_t *req_fields; 196 json_t *req_obj; 197 CURL *eh; 198 199 ofh->cb = cb; 200 ofh->cb_cls = cb_cls; 201 { 202 char *path; 203 204 GNUNET_asprintf (&path, 205 "private/orders/%s/forget", 206 ofh->order_id); 207 ofh->url = TALER_url_join (ofh->base_url, 208 path, 209 NULL); 210 GNUNET_free (path); 211 } 212 if (NULL == ofh->url) 213 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 214 req_fields = json_array (); 215 if (NULL == req_fields) 216 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 217 for (unsigned int i = 0; i < ofh->fields_length; i++) 218 { 219 if (0 != 220 json_array_append_new (req_fields, 221 json_string (ofh->fields[i]))) 222 { 223 json_decref (req_fields); 224 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 225 } 226 } 227 req_obj = GNUNET_JSON_PACK ( 228 GNUNET_JSON_pack_array_steal ("fields", 229 req_fields)); 230 eh = TALER_MERCHANT_curl_easy_get_ (ofh->url); 231 if ( (NULL == eh) || 232 (GNUNET_OK != 233 TALER_curl_easy_post (&ofh->post_ctx, 234 eh, 235 req_obj)) ) 236 { 237 GNUNET_break (0); 238 json_decref (req_obj); 239 if (NULL != eh) 240 curl_easy_cleanup (eh); 241 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 242 } 243 json_decref (req_obj); 244 GNUNET_assert (CURLE_OK == 245 curl_easy_setopt (eh, 246 CURLOPT_CUSTOMREQUEST, 247 MHD_HTTP_METHOD_PATCH)); 248 ofh->job = GNUNET_CURL_job_add2 (ofh->ctx, 249 eh, 250 ofh->post_ctx.headers, 251 &handle_patch_orders_forget_finished, 252 ofh); 253 if (NULL == ofh->job) 254 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 255 return TALER_EC_NONE; 256 } 257 258 259 void 260 TALER_MERCHANT_patch_private_orders_forget_cancel ( 261 struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *ofh) 262 { 263 if (NULL != ofh->job) 264 { 265 GNUNET_CURL_job_cancel (ofh->job); 266 ofh->job = NULL; 267 } 268 TALER_curl_easy_post_finished (&ofh->post_ctx); 269 for (unsigned int i = 0; i < ofh->fields_length; i++) 270 GNUNET_free (ofh->fields[i]); 271 GNUNET_free (ofh->fields); 272 GNUNET_free (ofh->order_id); 273 GNUNET_free (ofh->url); 274 GNUNET_free (ofh->base_url); 275 GNUNET_free (ofh); 276 } 277 278 279 /* end of merchant_api_patch-private-orders-ORDER_ID-forget-new.c */