Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023, 2024, 2026 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it
6 : under the terms of the GNU General Public License as published by
7 : the Free Software Foundation; either version 3, or (at your
8 : option) any later version.
9 :
10 : TALER is distributed in the hope that it will be useful, but
11 : WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public
16 : License along with TALER; see the file COPYING. If not, see
17 : <http://www.gnu.org/licenses/>
18 : */
19 : /**
20 : * @file testing/testing_api_cmd_check_aml_decisions.c
21 : * @brief command for testing GET /aml/$OFFICER_PUB/decisions
22 : * @author Christian Grothoff
23 : */
24 : #include "taler/platform.h"
25 : #include "taler/taler_json_lib.h"
26 : #include <gnunet/gnunet_curl_lib.h>
27 :
28 : /**
29 : * State for a "check_aml_decisions" CMD.
30 : */
31 : struct AmlCheckState;
32 :
33 : #define TALER_EXCHANGE_GET_AML_DECISIONS_RESULT_CLOSURE \
34 : struct AmlCheckState
35 : #include "taler/taler-exchange/get-aml-OFFICER_PUB-decisions.h"
36 : #include "taler/taler_testing_lib.h"
37 : #include "taler/taler_signatures.h"
38 : #include "taler/backoff.h"
39 :
40 :
41 : /**
42 : * State for a "check_aml_decisions" CMD.
43 : */
44 : struct AmlCheckState
45 : {
46 :
47 : /**
48 : * Handle while operation is running.
49 : */
50 : struct TALER_EXCHANGE_GetAmlDecisionsHandle *dh;
51 :
52 : /**
53 : * Our interpreter.
54 : */
55 : struct TALER_TESTING_Interpreter *is;
56 :
57 : /**
58 : * Reference to command to previous set officer.
59 : */
60 : const char *ref_officer;
61 :
62 : /**
63 : * Reference to a command with a trait of a payto-URI for an account we want
64 : * to get the status on; NULL to match all accounts. If it has also a
65 : * justification trait, we check that this is the current justification for
66 : * the latest AML decision.
67 : */
68 : const char *ref_operation;
69 :
70 : /**
71 : * Expected HTTP status.
72 : */
73 : unsigned int expected_http_status;
74 :
75 : };
76 :
77 :
78 : /**
79 : * Callback to analyze the /aml/$OFFICER_PUB/$decision/$H_PAYTO response, just used to check
80 : * if the response code is acceptable.
81 : *
82 : * @param ds our state
83 : * @param adr response details
84 : */
85 : static void
86 4 : check_aml_decisions_cb (
87 : TALER_EXCHANGE_GET_AML_DECISIONS_RESULT_CLOSURE *ds,
88 : const struct TALER_EXCHANGE_GetAmlDecisionsResponse *adr)
89 : {
90 4 : ds->dh = NULL;
91 4 : if (ds->expected_http_status != adr->hr.http_status)
92 : {
93 0 : TALER_TESTING_unexpected_status (ds->is,
94 : adr->hr.http_status,
95 : ds->expected_http_status);
96 0 : return;
97 : }
98 4 : if (MHD_HTTP_OK == adr->hr.http_status)
99 : {
100 : const struct TALER_TESTING_Command *ref;
101 : const char *justification;
102 2 : const struct TALER_EXCHANGE_GetAmlDecisionsDecision *oldest = NULL;
103 :
104 2 : if (NULL != ds->ref_operation)
105 : {
106 1 : ref = TALER_TESTING_interpreter_lookup_command (
107 : ds->is,
108 : ds->ref_operation);
109 1 : if (NULL == ref)
110 : {
111 0 : GNUNET_break (0);
112 0 : TALER_TESTING_interpreter_fail (ds->is);
113 0 : return;
114 : }
115 1 : if (GNUNET_OK ==
116 1 : TALER_TESTING_get_trait_aml_justification (
117 : ref,
118 : &justification))
119 : {
120 2 : for (unsigned int i = 0; i<adr->details.ok.records_length; i++)
121 : {
122 1 : const struct TALER_EXCHANGE_GetAmlDecisionsDecision *aml_history
123 1 : = &adr->details.ok.records[i];
124 :
125 1 : if ( (NULL == oldest) ||
126 0 : (GNUNET_TIME_timestamp_cmp (oldest->decision_time,
127 : >,
128 : aml_history->decision_time)) )
129 1 : oldest = aml_history;
130 : }
131 1 : if (NULL == oldest)
132 : {
133 0 : GNUNET_break (0);
134 0 : TALER_TESTING_interpreter_fail (ds->is);
135 0 : return;
136 : }
137 1 : if (0 != strcmp (oldest->justification,
138 : justification) )
139 : {
140 0 : GNUNET_break (0);
141 0 : TALER_TESTING_interpreter_fail (ds->is);
142 0 : return;
143 : }
144 : }
145 : }
146 : }
147 4 : TALER_TESTING_interpreter_next (ds->is);
148 : }
149 :
150 :
151 : /**
152 : * Run the command.
153 : *
154 : * @param cls closure.
155 : * @param cmd the command to execute.
156 : * @param is the interpreter state.
157 : */
158 : static void
159 4 : check_aml_decisions_run (
160 : void *cls,
161 : const struct TALER_TESTING_Command *cmd,
162 : struct TALER_TESTING_Interpreter *is)
163 : {
164 4 : struct AmlCheckState *ds = cls;
165 4 : const struct TALER_NormalizedPaytoHashP *h_payto = NULL;
166 : const struct TALER_AmlOfficerPrivateKeyP *officer_priv;
167 : const struct TALER_TESTING_Command *ref;
168 : const char *exchange_url;
169 :
170 : (void) cmd;
171 4 : ds->is = is;
172 : {
173 : const struct TALER_TESTING_Command *exchange_cmd;
174 :
175 : exchange_cmd
176 4 : = TALER_TESTING_interpreter_get_command (
177 : is,
178 : "exchange");
179 4 : if (NULL == exchange_cmd)
180 : {
181 0 : GNUNET_break (0);
182 0 : TALER_TESTING_interpreter_fail (is);
183 0 : return;
184 : }
185 4 : GNUNET_assert (
186 : GNUNET_OK ==
187 : TALER_TESTING_get_trait_exchange_url (exchange_cmd,
188 : &exchange_url));
189 : }
190 :
191 4 : if (NULL != ds->ref_operation)
192 : {
193 3 : ref = TALER_TESTING_interpreter_lookup_command (
194 : is,
195 : ds->ref_operation);
196 3 : if (NULL == ref)
197 : {
198 0 : GNUNET_break (0);
199 0 : TALER_TESTING_interpreter_fail (is);
200 0 : return;
201 : }
202 3 : GNUNET_assert (GNUNET_OK ==
203 : TALER_TESTING_get_trait_h_normalized_payto (
204 : ref,
205 : &h_payto));
206 : }
207 4 : ref = TALER_TESTING_interpreter_lookup_command (
208 : is,
209 : ds->ref_officer);
210 4 : if (NULL == ref)
211 : {
212 0 : GNUNET_break (0);
213 0 : TALER_TESTING_interpreter_fail (is);
214 0 : return;
215 : }
216 4 : GNUNET_assert (GNUNET_OK ==
217 : TALER_TESTING_get_trait_officer_priv (
218 : ref,
219 : &officer_priv));
220 4 : ds->dh = TALER_EXCHANGE_get_aml_decisions_create (
221 : TALER_TESTING_interpreter_get_context (is),
222 : exchange_url,
223 : officer_priv);
224 4 : if (NULL == ds->dh)
225 : {
226 0 : GNUNET_break (0);
227 0 : TALER_TESTING_interpreter_fail (is);
228 0 : return;
229 : }
230 4 : TALER_EXCHANGE_get_aml_decisions_set_options (
231 : ds->dh,
232 : TALER_EXCHANGE_get_aml_decisions_option_offset (UINT64_MAX),
233 : TALER_EXCHANGE_get_aml_decisions_option_limit (-1));
234 4 : if (NULL != h_payto)
235 3 : TALER_EXCHANGE_get_aml_decisions_set_options (
236 : ds->dh,
237 : TALER_EXCHANGE_get_aml_decisions_option_filter_h_payto (h_payto));
238 : {
239 : enum TALER_ErrorCode ec;
240 :
241 4 : ec = TALER_EXCHANGE_get_aml_decisions_start (ds->dh,
242 : &check_aml_decisions_cb,
243 : ds);
244 4 : if (TALER_EC_NONE != ec)
245 : {
246 0 : GNUNET_break (0);
247 0 : ds->dh = NULL;
248 0 : TALER_TESTING_interpreter_fail (is);
249 0 : return;
250 : }
251 : }
252 : }
253 :
254 :
255 : /**
256 : * Free the state of a "check_aml_decision" CMD, and possibly cancel a
257 : * pending operation thereof.
258 : *
259 : * @param cls closure, must be a `struct AmlCheckState`.
260 : * @param cmd the command which is being cleaned up.
261 : */
262 : static void
263 4 : check_aml_decisions_cleanup (
264 : void *cls,
265 : const struct TALER_TESTING_Command *cmd)
266 : {
267 4 : struct AmlCheckState *ds = cls;
268 :
269 4 : if (NULL != ds->dh)
270 : {
271 0 : TALER_TESTING_command_incomplete (ds->is,
272 : cmd->label);
273 0 : TALER_EXCHANGE_get_aml_decisions_cancel (ds->dh);
274 0 : ds->dh = NULL;
275 : }
276 4 : GNUNET_free (ds);
277 4 : }
278 :
279 :
280 : struct TALER_TESTING_Command
281 4 : TALER_TESTING_cmd_check_aml_decisions (
282 : const char *label,
283 : const char *ref_officer,
284 : const char *ref_operation,
285 : unsigned int expected_http_status)
286 : {
287 : struct AmlCheckState *ds;
288 :
289 4 : ds = GNUNET_new (struct AmlCheckState);
290 4 : ds->ref_officer = ref_officer;
291 4 : ds->ref_operation = ref_operation;
292 4 : ds->expected_http_status = expected_http_status;
293 : {
294 4 : struct TALER_TESTING_Command cmd = {
295 : .cls = ds,
296 : .label = label,
297 : .run = &check_aml_decisions_run,
298 : .cleanup = &check_aml_decisions_cleanup
299 : };
300 :
301 4 : return cmd;
302 : }
303 : }
304 :
305 :
306 : /* end of testing_api_cmd_check_aml_decisions.c */
|