bank_api_admin_add_incoming.c (7359B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2015--2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU 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 15 <http://www.gnu.org/licenses/> 16 */ 17 /** 18 * @file bank-lib/bank_api_admin_add_incoming.c 19 * @brief Implementation of the /admin/add-incoming requests of the bank's HTTP API 20 * @author Christian Grothoff 21 */ 22 #include "taler/platform.h" 23 #include "bank_api_common.h" 24 #include <microhttpd.h> /* just for HTTP status codes */ 25 #include "taler/taler_signatures.h" 26 #include "taler/taler_curl_lib.h" 27 28 29 /** 30 * @brief An /admin/add-incoming Handle 31 */ 32 struct TALER_BANK_AdminAddIncomingHandle 33 { 34 35 /** 36 * The url for this request. 37 */ 38 char *request_url; 39 40 /** 41 * POST context. 42 */ 43 struct TALER_CURL_PostContext post_ctx; 44 45 /** 46 * Handle for the request. 47 */ 48 struct GNUNET_CURL_Job *job; 49 50 /** 51 * Function to call with the result. 52 */ 53 TALER_BANK_AdminAddIncomingCallback cb; 54 55 /** 56 * Closure for @a cb. 57 */ 58 void *cb_cls; 59 60 }; 61 62 63 /** 64 * Function called when we're done processing the 65 * HTTP /admin/add-incoming request. 66 * 67 * @param cls the `struct TALER_BANK_AdminAddIncomingHandle` 68 * @param response_code HTTP response code, 0 on error 69 * @param response parsed JSON result, NULL on error 70 */ 71 static void 72 handle_admin_add_incoming_finished (void *cls, 73 long response_code, 74 const void *response) 75 { 76 struct TALER_BANK_AdminAddIncomingHandle *aai = cls; 77 const json_t *j = response; 78 struct TALER_BANK_AdminAddIncomingResponse ir = { 79 .http_status = response_code, 80 .response = response 81 }; 82 83 aai->job = NULL; 84 switch (response_code) 85 { 86 case 0: 87 ir.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 88 break; 89 case MHD_HTTP_OK: 90 { 91 struct GNUNET_JSON_Specification spec[] = { 92 GNUNET_JSON_spec_uint64 ("row_id", 93 &ir.details.ok.serial_id), 94 GNUNET_JSON_spec_timestamp ("timestamp", 95 &ir.details.ok.timestamp), 96 GNUNET_JSON_spec_end () 97 }; 98 99 if (GNUNET_OK != 100 GNUNET_JSON_parse (j, 101 spec, 102 NULL, NULL)) 103 { 104 GNUNET_break_op (0); 105 ir.http_status = 0; 106 ir.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 107 break; 108 } 109 } 110 break; 111 case MHD_HTTP_BAD_REQUEST: 112 /* This should never happen, either us or the bank is buggy 113 (or API version conflict); just pass JSON reply to the application */ 114 GNUNET_break_op (0); 115 ir.ec = TALER_JSON_get_error_code (j); 116 break; 117 case MHD_HTTP_FORBIDDEN: 118 /* Access denied */ 119 ir.ec = TALER_JSON_get_error_code (j); 120 break; 121 case MHD_HTTP_UNAUTHORIZED: 122 /* Nothing really to verify, bank says the password is invalid; we should 123 pass the JSON reply to the application */ 124 ir.ec = TALER_JSON_get_error_code (j); 125 break; 126 case MHD_HTTP_NOT_FOUND: 127 /* Nothing really to verify, maybe account really does not exist. 128 We should pass the JSON reply to the application */ 129 ir.ec = TALER_JSON_get_error_code (j); 130 break; 131 case MHD_HTTP_CONFLICT: 132 /* Nothing to verify, we used the same wire subject 133 twice? */ 134 ir.ec = TALER_JSON_get_error_code (j); 135 break; 136 case MHD_HTTP_INTERNAL_SERVER_ERROR: 137 /* Server had an internal issue; we should retry, but this API 138 leaves this to the application */ 139 ir.ec = TALER_JSON_get_error_code (j); 140 break; 141 default: 142 /* unexpected response code */ 143 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 144 "Unexpected response code %u\n", 145 (unsigned int) response_code); 146 GNUNET_break (0); 147 ir.ec = TALER_JSON_get_error_code (j); 148 break; 149 } 150 aai->cb (aai->cb_cls, 151 &ir); 152 TALER_BANK_admin_add_incoming_cancel (aai); 153 } 154 155 156 struct TALER_BANK_AdminAddIncomingHandle * 157 TALER_BANK_admin_add_incoming ( 158 struct GNUNET_CURL_Context *ctx, 159 const struct TALER_BANK_AuthenticationData *auth, 160 const struct TALER_ReservePublicKeyP *reserve_pub, 161 const struct TALER_Amount *amount, 162 const struct TALER_FullPayto debit_account, 163 TALER_BANK_AdminAddIncomingCallback res_cb, 164 void *res_cb_cls) 165 { 166 struct TALER_BANK_AdminAddIncomingHandle *aai; 167 json_t *admin_obj; 168 CURL *eh; 169 170 if (NULL == debit_account.full_payto) 171 { 172 GNUNET_break (0); 173 return NULL; 174 } 175 if (NULL == reserve_pub) 176 { 177 GNUNET_break (0); 178 return NULL; 179 } 180 if (NULL == amount) 181 { 182 GNUNET_break (0); 183 return NULL; 184 } 185 admin_obj = GNUNET_JSON_PACK ( 186 GNUNET_JSON_pack_data_auto ("reserve_pub", 187 reserve_pub), 188 TALER_JSON_pack_amount ("amount", 189 amount), 190 TALER_JSON_pack_full_payto ("debit_account", 191 debit_account)); 192 if (NULL == admin_obj) 193 { 194 GNUNET_break (0); 195 return NULL; 196 } 197 aai = GNUNET_new (struct TALER_BANK_AdminAddIncomingHandle); 198 aai->cb = res_cb; 199 aai->cb_cls = res_cb_cls; 200 aai->request_url = TALER_url_join (auth->wire_gateway_url, 201 "admin/add-incoming", 202 NULL); 203 if (NULL == aai->request_url) 204 { 205 GNUNET_free (aai); 206 json_decref (admin_obj); 207 return NULL; 208 } 209 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 210 "Requesting administrative transaction at `%s' for reserve %s\n", 211 aai->request_url, 212 TALER_B2S (reserve_pub)); 213 aai->post_ctx.headers 214 = curl_slist_append ( 215 aai->post_ctx.headers, 216 "Content-Type: application/json"); 217 218 eh = curl_easy_init (); 219 if ( (NULL == eh) || 220 (GNUNET_OK != 221 TALER_BANK_setup_auth_ (eh, 222 auth)) || 223 (CURLE_OK != 224 curl_easy_setopt (eh, 225 CURLOPT_URL, 226 aai->request_url)) || 227 (GNUNET_OK != 228 TALER_curl_easy_post (&aai->post_ctx, 229 eh, 230 admin_obj)) ) 231 { 232 GNUNET_break (0); 233 TALER_BANK_admin_add_incoming_cancel (aai); 234 if (NULL != eh) 235 curl_easy_cleanup (eh); 236 json_decref (admin_obj); 237 return NULL; 238 } 239 json_decref (admin_obj); 240 241 aai->job = GNUNET_CURL_job_add2 (ctx, 242 eh, 243 aai->post_ctx.headers, 244 &handle_admin_add_incoming_finished, 245 aai); 246 return aai; 247 } 248 249 250 void 251 TALER_BANK_admin_add_incoming_cancel ( 252 struct TALER_BANK_AdminAddIncomingHandle *aai) 253 { 254 if (NULL != aai->job) 255 { 256 GNUNET_CURL_job_cancel (aai->job); 257 aai->job = NULL; 258 } 259 TALER_curl_easy_post_finished (&aai->post_ctx); 260 GNUNET_free (aai->request_url); 261 GNUNET_free (aai); 262 } 263 264 265 /* end of bank_api_admin_add_incoming.c */