Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023-2026 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 lib/exchange_api_post-management-aml-officers.c
19 : * @brief functions to update AML officer status via POST /management/aml-officers
20 : * @author Christian Grothoff
21 : */
22 : #include "taler/platform.h"
23 : #include "taler/taler_json_lib.h"
24 : #include <gnunet/gnunet_curl_lib.h>
25 : #include <microhttpd.h>
26 : #include "taler/taler_exchange_service.h"
27 : #include "taler/taler-exchange/post-management-aml-officers.h"
28 : #include "exchange_api_curl_defaults.h"
29 : #include "taler/taler_signatures.h"
30 : #include "taler/taler_curl_lib.h"
31 :
32 :
33 : /**
34 : * Handle for a POST /management/aml-officers request.
35 : */
36 : struct TALER_EXCHANGE_PostManagementAmlOfficersHandle
37 : {
38 :
39 : /**
40 : * The base URL for this request.
41 : */
42 : char *base_url;
43 :
44 : /**
45 : * The full URL for this request, set during _start.
46 : */
47 : char *url;
48 :
49 : /**
50 : * Minor context that holds body and headers.
51 : */
52 : struct TALER_CURL_PostContext post_ctx;
53 :
54 : /**
55 : * Handle for the request.
56 : */
57 : struct GNUNET_CURL_Job *job;
58 :
59 : /**
60 : * Function to call with the result.
61 : */
62 : TALER_EXCHANGE_PostManagementAmlOfficersCallback cb;
63 :
64 : /**
65 : * Closure for @a cb.
66 : */
67 : TALER_EXCHANGE_POST_MANAGEMENT_AML_OFFICERS_RESULT_CLOSURE *cb_cls;
68 :
69 : /**
70 : * Reference to the execution context.
71 : */
72 : struct GNUNET_CURL_Context *ctx;
73 :
74 : /**
75 : * Public key of the officer.
76 : */
77 : struct TALER_AmlOfficerPublicKeyP officer_pub;
78 :
79 : /**
80 : * Name of the officer.
81 : */
82 : char *officer_name;
83 :
84 : /**
85 : * When to affect the status change.
86 : */
87 : struct GNUNET_TIME_Timestamp change_date;
88 :
89 : /**
90 : * Is the officer active?
91 : */
92 : bool is_active;
93 :
94 : /**
95 : * Is the officer read-only?
96 : */
97 : bool read_only;
98 :
99 : /**
100 : * Master signature affirming the change.
101 : */
102 : struct TALER_MasterSignatureP master_sig;
103 :
104 : };
105 :
106 :
107 : /**
108 : * Function called when we're done processing the
109 : * HTTP POST /management/aml-officers request.
110 : *
111 : * @param cls the `struct TALER_EXCHANGE_PostManagementAmlOfficersHandle`
112 : * @param response_code HTTP response code, 0 on error
113 : * @param response response body, NULL if not in JSON
114 : */
115 : static void
116 4 : handle_post_aml_officer_finished (void *cls,
117 : long response_code,
118 : const void *response)
119 : {
120 4 : struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *pmaoh = cls;
121 4 : const json_t *json = response;
122 4 : struct TALER_EXCHANGE_PostManagementAmlOfficersResponse res = {
123 4 : .hr.http_status = (unsigned int) response_code,
124 : .hr.reply = json
125 : };
126 :
127 4 : pmaoh->job = NULL;
128 4 : switch (response_code)
129 : {
130 0 : case 0:
131 : /* no reply */
132 0 : res.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
133 0 : res.hr.hint = "server offline?";
134 0 : break;
135 4 : case MHD_HTTP_NO_CONTENT:
136 4 : break;
137 0 : case MHD_HTTP_FORBIDDEN:
138 0 : res.hr.ec = TALER_JSON_get_error_code (json);
139 0 : res.hr.hint = TALER_JSON_get_error_hint (json);
140 0 : break;
141 0 : case MHD_HTTP_NOT_FOUND:
142 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
143 : "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n",
144 : pmaoh->url);
145 0 : if (NULL != json)
146 : {
147 0 : res.hr.ec = TALER_JSON_get_error_code (json);
148 0 : res.hr.hint = TALER_JSON_get_error_hint (json);
149 : }
150 : else
151 : {
152 0 : res.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
153 0 : res.hr.hint = TALER_ErrorCode_get_hint (res.hr.ec);
154 : }
155 0 : break;
156 0 : case MHD_HTTP_CONFLICT:
157 0 : res.hr.ec = TALER_JSON_get_error_code (json);
158 0 : res.hr.hint = TALER_JSON_get_error_hint (json);
159 0 : break;
160 0 : default:
161 : /* unexpected response code */
162 0 : GNUNET_break_op (0);
163 0 : res.hr.ec = TALER_JSON_get_error_code (json);
164 0 : res.hr.hint = TALER_JSON_get_error_hint (json);
165 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
166 : "Unexpected response code %u/%d for exchange POST management AML officer\n",
167 : (unsigned int) response_code,
168 : (int) res.hr.ec);
169 0 : break;
170 : }
171 4 : if (NULL != pmaoh->cb)
172 : {
173 4 : pmaoh->cb (pmaoh->cb_cls,
174 : &res);
175 4 : pmaoh->cb = NULL;
176 : }
177 4 : TALER_EXCHANGE_post_management_aml_officers_cancel (pmaoh);
178 4 : }
179 :
180 :
181 : struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *
182 4 : TALER_EXCHANGE_post_management_aml_officers_create (
183 : struct GNUNET_CURL_Context *ctx,
184 : const char *url,
185 : const struct TALER_AmlOfficerPublicKeyP *officer_pub,
186 : const char *officer_name,
187 : struct GNUNET_TIME_Timestamp change_date,
188 : bool is_active,
189 : bool read_only,
190 : const struct TALER_MasterSignatureP *master_sig)
191 : {
192 : struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *pmaoh;
193 :
194 4 : pmaoh = GNUNET_new (struct TALER_EXCHANGE_PostManagementAmlOfficersHandle);
195 4 : pmaoh->ctx = ctx;
196 4 : pmaoh->base_url = GNUNET_strdup (url);
197 4 : pmaoh->officer_pub = *officer_pub;
198 4 : pmaoh->officer_name = GNUNET_strdup (officer_name);
199 4 : pmaoh->change_date = change_date;
200 4 : pmaoh->is_active = is_active;
201 4 : pmaoh->read_only = read_only;
202 4 : pmaoh->master_sig = *master_sig;
203 4 : return pmaoh;
204 : }
205 :
206 :
207 : enum TALER_ErrorCode
208 4 : TALER_EXCHANGE_post_management_aml_officers_start (
209 : struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *pmaoh,
210 : TALER_EXCHANGE_PostManagementAmlOfficersCallback cb,
211 : TALER_EXCHANGE_POST_MANAGEMENT_AML_OFFICERS_RESULT_CLOSURE *cb_cls)
212 : {
213 : CURL *eh;
214 : json_t *body;
215 :
216 4 : pmaoh->cb = cb;
217 4 : pmaoh->cb_cls = cb_cls;
218 4 : pmaoh->url = TALER_url_join (pmaoh->base_url,
219 : "management/aml-officers",
220 : NULL);
221 4 : if (NULL == pmaoh->url)
222 : {
223 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
224 : "Could not construct request URL.\n");
225 0 : return TALER_EC_GENERIC_CONFIGURATION_INVALID;
226 : }
227 4 : body = GNUNET_JSON_PACK (
228 : GNUNET_JSON_pack_string ("officer_name",
229 : pmaoh->officer_name),
230 : GNUNET_JSON_pack_data_auto ("officer_pub",
231 : &pmaoh->officer_pub),
232 : GNUNET_JSON_pack_data_auto ("master_sig",
233 : &pmaoh->master_sig),
234 : GNUNET_JSON_pack_bool ("is_active",
235 : pmaoh->is_active),
236 : GNUNET_JSON_pack_bool ("read_only",
237 : pmaoh->read_only),
238 : GNUNET_JSON_pack_timestamp ("change_date",
239 : pmaoh->change_date));
240 4 : eh = TALER_EXCHANGE_curl_easy_get_ (pmaoh->url);
241 8 : if ( (NULL == eh) ||
242 : (GNUNET_OK !=
243 4 : TALER_curl_easy_post (&pmaoh->post_ctx,
244 : eh,
245 : body)) )
246 : {
247 0 : GNUNET_break (0);
248 0 : if (NULL != eh)
249 0 : curl_easy_cleanup (eh);
250 0 : json_decref (body);
251 0 : GNUNET_free (pmaoh->url);
252 0 : pmaoh->url = NULL;
253 0 : return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
254 : }
255 4 : json_decref (body);
256 4 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
257 : "Requesting URL '%s'\n",
258 : pmaoh->url);
259 8 : pmaoh->job = GNUNET_CURL_job_add2 (pmaoh->ctx,
260 : eh,
261 4 : pmaoh->post_ctx.headers,
262 : &handle_post_aml_officer_finished,
263 : pmaoh);
264 4 : if (NULL == pmaoh->job)
265 : {
266 0 : TALER_curl_easy_post_finished (&pmaoh->post_ctx);
267 0 : GNUNET_free (pmaoh->url);
268 0 : pmaoh->url = NULL;
269 0 : return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
270 : }
271 4 : return TALER_EC_NONE;
272 : }
273 :
274 :
275 : void
276 4 : TALER_EXCHANGE_post_management_aml_officers_cancel (
277 : struct TALER_EXCHANGE_PostManagementAmlOfficersHandle *pmaoh)
278 : {
279 4 : if (NULL != pmaoh->job)
280 : {
281 0 : GNUNET_CURL_job_cancel (pmaoh->job);
282 0 : pmaoh->job = NULL;
283 : }
284 4 : TALER_curl_easy_post_finished (&pmaoh->post_ctx);
285 4 : GNUNET_free (pmaoh->url);
286 4 : GNUNET_free (pmaoh->officer_name);
287 4 : GNUNET_free (pmaoh->base_url);
288 4 : GNUNET_free (pmaoh);
289 4 : }
290 :
291 :
292 : /* end of exchange_api_post-management-aml-officers.c */
|