Line data Source code
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 61 : handle_admin_add_incoming_finished (void *cls,
73 : long response_code,
74 : const void *response)
75 : {
76 61 : struct TALER_BANK_AdminAddIncomingHandle *aai = cls;
77 61 : const json_t *j = response;
78 61 : struct TALER_BANK_AdminAddIncomingResponse ir = {
79 : .http_status = response_code,
80 : .response = response
81 : };
82 :
83 61 : aai->job = NULL;
84 61 : switch (response_code)
85 : {
86 0 : case 0:
87 0 : ir.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
88 0 : break;
89 59 : case MHD_HTTP_OK:
90 : {
91 : struct GNUNET_JSON_Specification spec[] = {
92 59 : GNUNET_JSON_spec_uint64 ("row_id",
93 : &ir.details.ok.serial_id),
94 59 : GNUNET_JSON_spec_timestamp ("timestamp",
95 : &ir.details.ok.timestamp),
96 59 : GNUNET_JSON_spec_end ()
97 : };
98 :
99 59 : if (GNUNET_OK !=
100 59 : GNUNET_JSON_parse (j,
101 : spec,
102 : NULL, NULL))
103 : {
104 0 : GNUNET_break_op (0);
105 0 : ir.http_status = 0;
106 0 : ir.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
107 0 : break;
108 : }
109 : }
110 59 : break;
111 0 : 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 0 : GNUNET_break_op (0);
115 0 : ir.ec = TALER_JSON_get_error_code (j);
116 0 : break;
117 0 : case MHD_HTTP_FORBIDDEN:
118 : /* Access denied */
119 0 : ir.ec = TALER_JSON_get_error_code (j);
120 0 : break;
121 0 : 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 0 : ir.ec = TALER_JSON_get_error_code (j);
125 0 : break;
126 0 : 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 0 : ir.ec = TALER_JSON_get_error_code (j);
130 0 : break;
131 2 : case MHD_HTTP_CONFLICT:
132 : /* Nothing to verify, we used the same wire subject
133 : twice? */
134 2 : ir.ec = TALER_JSON_get_error_code (j);
135 2 : break;
136 0 : 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 0 : ir.ec = TALER_JSON_get_error_code (j);
140 0 : break;
141 0 : default:
142 : /* unexpected response code */
143 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
144 : "Unexpected response code %u\n",
145 : (unsigned int) response_code);
146 0 : GNUNET_break (0);
147 0 : ir.ec = TALER_JSON_get_error_code (j);
148 0 : break;
149 : }
150 61 : aai->cb (aai->cb_cls,
151 : &ir);
152 61 : TALER_BANK_admin_add_incoming_cancel (aai);
153 61 : }
154 :
155 :
156 : struct TALER_BANK_AdminAddIncomingHandle *
157 61 : 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 61 : if (NULL == debit_account.full_payto)
171 : {
172 0 : GNUNET_break (0);
173 0 : return NULL;
174 : }
175 61 : if (NULL == reserve_pub)
176 : {
177 0 : GNUNET_break (0);
178 0 : return NULL;
179 : }
180 61 : if (NULL == amount)
181 : {
182 0 : GNUNET_break (0);
183 0 : return NULL;
184 : }
185 61 : 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 61 : if (NULL == admin_obj)
193 : {
194 0 : GNUNET_break (0);
195 0 : return NULL;
196 : }
197 61 : aai = GNUNET_new (struct TALER_BANK_AdminAddIncomingHandle);
198 61 : aai->cb = res_cb;
199 61 : aai->cb_cls = res_cb_cls;
200 61 : aai->request_url = TALER_url_join (auth->wire_gateway_url,
201 : "admin/add-incoming",
202 : NULL);
203 61 : if (NULL == aai->request_url)
204 : {
205 0 : GNUNET_free (aai);
206 0 : json_decref (admin_obj);
207 0 : return NULL;
208 : }
209 61 : 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 61 : = curl_slist_append (
215 : aai->post_ctx.headers,
216 : "Content-Type: application/json");
217 :
218 61 : eh = curl_easy_init ();
219 122 : if ( (NULL == eh) ||
220 : (GNUNET_OK !=
221 61 : TALER_BANK_setup_auth_ (eh,
222 61 : auth)) ||
223 : (CURLE_OK !=
224 61 : curl_easy_setopt (eh,
225 : CURLOPT_URL,
226 61 : aai->request_url)) ||
227 : (GNUNET_OK !=
228 61 : TALER_curl_easy_post (&aai->post_ctx,
229 : eh,
230 : admin_obj)) )
231 : {
232 0 : GNUNET_break (0);
233 0 : TALER_BANK_admin_add_incoming_cancel (aai);
234 0 : if (NULL != eh)
235 0 : curl_easy_cleanup (eh);
236 0 : json_decref (admin_obj);
237 0 : return NULL;
238 : }
239 61 : json_decref (admin_obj);
240 :
241 122 : aai->job = GNUNET_CURL_job_add2 (ctx,
242 : eh,
243 61 : aai->post_ctx.headers,
244 : &handle_admin_add_incoming_finished,
245 : aai);
246 61 : return aai;
247 : }
248 :
249 :
250 : void
251 61 : TALER_BANK_admin_add_incoming_cancel (
252 : struct TALER_BANK_AdminAddIncomingHandle *aai)
253 : {
254 61 : if (NULL != aai->job)
255 : {
256 0 : GNUNET_CURL_job_cancel (aai->job);
257 0 : aai->job = NULL;
258 : }
259 61 : TALER_curl_easy_post_finished (&aai->post_ctx);
260 61 : GNUNET_free (aai->request_url);
261 61 : GNUNET_free (aai);
262 61 : }
263 :
264 :
265 : /* end of bank_api_admin_add_incoming.c */
|