Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2015--2020 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.c
19 : * @brief Implementation of the /admin/ requests of the bank's HTTP API
20 : * @author Christian Grothoff
21 : */
22 : #include "platform.h"
23 : #include "bank_api_common.h"
24 : #include <microhttpd.h> /* just for HTTP status codes */
25 : #include "taler_signatures.h"
26 : #include "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 7 : handle_admin_add_incoming_finished (void *cls,
73 : long response_code,
74 : const void *response)
75 : {
76 7 : struct TALER_BANK_AdminAddIncomingHandle *aai = cls;
77 7 : uint64_t row_id = UINT64_MAX;
78 : struct GNUNET_TIME_Timestamp timestamp;
79 : enum TALER_ErrorCode ec;
80 7 : const json_t *j = response;
81 :
82 7 : aai->job = NULL;
83 7 : timestamp = GNUNET_TIME_UNIT_FOREVER_TS;
84 7 : switch (response_code)
85 : {
86 0 : case 0:
87 0 : ec = TALER_EC_GENERIC_INVALID_RESPONSE;
88 0 : break;
89 6 : case MHD_HTTP_OK:
90 : {
91 : struct GNUNET_JSON_Specification spec[] = {
92 6 : GNUNET_JSON_spec_uint64 ("row_id",
93 : &row_id),
94 6 : GNUNET_JSON_spec_timestamp ("timestamp",
95 : ×tamp),
96 6 : GNUNET_JSON_spec_end ()
97 : };
98 :
99 6 : if (GNUNET_OK !=
100 6 : GNUNET_JSON_parse (j,
101 : spec,
102 : NULL, NULL))
103 : {
104 0 : GNUNET_break_op (0);
105 0 : response_code = 0;
106 0 : ec = TALER_EC_GENERIC_INVALID_RESPONSE;
107 0 : break;
108 : }
109 6 : ec = TALER_EC_NONE;
110 : }
111 6 : break;
112 0 : case MHD_HTTP_BAD_REQUEST:
113 : /* This should never happen, either us or the bank is buggy
114 : (or API version conflict); just pass JSON reply to the application */
115 0 : GNUNET_break_op (0);
116 0 : ec = TALER_JSON_get_error_code (j);
117 0 : break;
118 0 : case MHD_HTTP_FORBIDDEN:
119 : /* Access denied */
120 0 : ec = TALER_JSON_get_error_code (j);
121 0 : break;
122 0 : case MHD_HTTP_UNAUTHORIZED:
123 : /* Nothing really to verify, bank says the password is invalid; we should
124 : pass the JSON reply to the application */
125 0 : ec = TALER_JSON_get_error_code (j);
126 0 : break;
127 0 : case MHD_HTTP_NOT_FOUND:
128 : /* Nothing really to verify, maybe account really does not exist.
129 : We should pass the JSON reply to the application */
130 0 : ec = TALER_JSON_get_error_code (j);
131 0 : break;
132 1 : case MHD_HTTP_CONFLICT:
133 : /* Nothing to verify, we used the same wire subject
134 : twice? */
135 1 : ec = TALER_JSON_get_error_code (j);
136 1 : break;
137 0 : case MHD_HTTP_INTERNAL_SERVER_ERROR:
138 : /* Server had an internal issue; we should retry, but this API
139 : leaves this to the application */
140 0 : ec = TALER_JSON_get_error_code (j);
141 0 : break;
142 0 : default:
143 : /* unexpected response code */
144 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
145 : "Unexpected response code %u\n",
146 : (unsigned int) response_code);
147 0 : GNUNET_break (0);
148 0 : ec = TALER_JSON_get_error_code (j);
149 0 : break;
150 : }
151 7 : aai->cb (aai->cb_cls,
152 : response_code,
153 : ec,
154 : row_id,
155 : timestamp,
156 : j);
157 7 : TALER_BANK_admin_add_incoming_cancel (aai);
158 7 : }
159 :
160 :
161 : struct TALER_BANK_AdminAddIncomingHandle *
162 7 : TALER_BANK_admin_add_incoming (
163 : struct GNUNET_CURL_Context *ctx,
164 : const struct TALER_BANK_AuthenticationData *auth,
165 : const struct TALER_ReservePublicKeyP *reserve_pub,
166 : const struct TALER_Amount *amount,
167 : const char *debit_account,
168 : TALER_BANK_AdminAddIncomingCallback res_cb,
169 : void *res_cb_cls)
170 : {
171 : struct TALER_BANK_AdminAddIncomingHandle *aai;
172 : json_t *admin_obj;
173 : CURL *eh;
174 :
175 7 : if (NULL == debit_account)
176 : {
177 0 : GNUNET_break (0);
178 0 : return NULL;
179 : }
180 7 : if (NULL == reserve_pub)
181 : {
182 0 : GNUNET_break (0);
183 0 : return NULL;
184 : }
185 7 : if (NULL == amount)
186 : {
187 0 : GNUNET_break (0);
188 0 : return NULL;
189 : }
190 7 : admin_obj = GNUNET_JSON_PACK (
191 : GNUNET_JSON_pack_data_auto ("reserve_pub",
192 : reserve_pub),
193 : TALER_JSON_pack_amount ("amount",
194 : amount),
195 : GNUNET_JSON_pack_string ("debit_account",
196 : debit_account));
197 7 : if (NULL == admin_obj)
198 : {
199 0 : GNUNET_break (0);
200 0 : return NULL;
201 : }
202 7 : aai = GNUNET_new (struct TALER_BANK_AdminAddIncomingHandle);
203 7 : aai->cb = res_cb;
204 7 : aai->cb_cls = res_cb_cls;
205 7 : aai->request_url = TALER_url_join (auth->wire_gateway_url,
206 : "admin/add-incoming",
207 : NULL);
208 7 : if (NULL == aai->request_url)
209 : {
210 0 : GNUNET_free (aai);
211 0 : json_decref (admin_obj);
212 0 : return NULL;
213 : }
214 7 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
215 : "Requesting administrative transaction at `%s' for reserve %s\n",
216 : aai->request_url,
217 : TALER_B2S (reserve_pub));
218 : aai->post_ctx.headers
219 7 : = curl_slist_append (
220 : aai->post_ctx.headers,
221 : "Content-Type: application/json");
222 :
223 7 : eh = curl_easy_init ();
224 14 : if ( (NULL == eh) ||
225 : (GNUNET_OK !=
226 7 : TALER_BANK_setup_auth_ (eh,
227 7 : auth)) ||
228 : (CURLE_OK !=
229 7 : curl_easy_setopt (eh,
230 : CURLOPT_URL,
231 7 : aai->request_url)) ||
232 : (GNUNET_OK !=
233 7 : TALER_curl_easy_post (&aai->post_ctx,
234 : eh,
235 : admin_obj)) )
236 : {
237 0 : GNUNET_break (0);
238 0 : TALER_BANK_admin_add_incoming_cancel (aai);
239 0 : if (NULL != eh)
240 0 : curl_easy_cleanup (eh);
241 0 : json_decref (admin_obj);
242 0 : return NULL;
243 : }
244 7 : json_decref (admin_obj);
245 :
246 14 : aai->job = GNUNET_CURL_job_add2 (ctx,
247 : eh,
248 7 : aai->post_ctx.headers,
249 : &handle_admin_add_incoming_finished,
250 : aai);
251 7 : return aai;
252 : }
253 :
254 :
255 : void
256 7 : TALER_BANK_admin_add_incoming_cancel (
257 : struct TALER_BANK_AdminAddIncomingHandle *aai)
258 : {
259 7 : if (NULL != aai->job)
260 : {
261 0 : GNUNET_CURL_job_cancel (aai->job);
262 0 : aai->job = NULL;
263 : }
264 7 : TALER_curl_easy_post_finished (&aai->post_ctx);
265 7 : GNUNET_free (aai->request_url);
266 7 : GNUNET_free (aai);
267 7 : }
268 :
269 :
270 : /* end of bank_api_admin.c */
|