Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023, 2024 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 "platform.h"
25 : #include "taler_json_lib.h"
26 : #include <gnunet/gnunet_curl_lib.h>
27 : #include "taler_testing_lib.h"
28 : #include "taler_signatures.h"
29 : #include "backoff.h"
30 :
31 :
32 : /**
33 : * State for a "check_aml_decisions" CMD.
34 : */
35 : struct AmlCheckState
36 : {
37 :
38 : /**
39 : * Handle while operation is running.
40 : */
41 : struct TALER_EXCHANGE_LookupAmlDecisions *dh;
42 :
43 : /**
44 : * Our interpreter.
45 : */
46 : struct TALER_TESTING_Interpreter *is;
47 :
48 : /**
49 : * Reference to command to previous set officer.
50 : */
51 : const char *ref_officer;
52 :
53 : /**
54 : * Reference to a command with a trait of a payto-URI for an account we want
55 : * to get the status on; NULL to match all accounts. If it has also a
56 : * justification trait, we check that this is the current justification for
57 : * the latest AML decision.
58 : */
59 : const char *ref_operation;
60 :
61 : /**
62 : * Expected HTTP status.
63 : */
64 : unsigned int expected_http_status;
65 :
66 : };
67 :
68 :
69 : /**
70 : * Callback to analyze the /aml/$OFFICER_PUB/$decision/$H_PAYTO response, just used to check
71 : * if the response code is acceptable.
72 : *
73 : * @param cls closure.
74 : * @param adr response details
75 : */
76 : static void
77 4 : check_aml_decisions_cb (
78 : void *cls,
79 : const struct TALER_EXCHANGE_AmlDecisionsResponse *adr)
80 : {
81 4 : struct AmlCheckState *ds = cls;
82 :
83 4 : ds->dh = NULL;
84 4 : if (ds->expected_http_status != adr->hr.http_status)
85 : {
86 0 : TALER_TESTING_unexpected_status (ds->is,
87 : adr->hr.http_status,
88 : ds->expected_http_status);
89 0 : return;
90 : }
91 4 : if (MHD_HTTP_OK == adr->hr.http_status)
92 : {
93 : const struct TALER_TESTING_Command *ref;
94 : const char *justification;
95 2 : const struct TALER_EXCHANGE_AmlDecision *oldest = NULL;
96 :
97 2 : if (NULL != ds->ref_operation)
98 : {
99 1 : ref = TALER_TESTING_interpreter_lookup_command (
100 : ds->is,
101 : ds->ref_operation);
102 1 : if (NULL == ref)
103 : {
104 0 : GNUNET_break (0);
105 0 : TALER_TESTING_interpreter_fail (ds->is);
106 0 : return;
107 : }
108 1 : if (GNUNET_OK ==
109 1 : TALER_TESTING_get_trait_aml_justification (
110 : ref,
111 : &justification))
112 : {
113 2 : for (unsigned int i = 0; i<adr->details.ok.decisions_length; i++)
114 : {
115 1 : const struct TALER_EXCHANGE_AmlDecision *aml_history
116 1 : = &adr->details.ok.decisions[i];
117 :
118 1 : if ( (NULL == oldest) ||
119 0 : (GNUNET_TIME_timestamp_cmp (oldest->decision_time,
120 : >,
121 : aml_history->decision_time)) )
122 1 : oldest = aml_history;
123 : }
124 1 : if (NULL == oldest)
125 : {
126 0 : GNUNET_break (0);
127 0 : TALER_TESTING_interpreter_fail (ds->is);
128 0 : return;
129 : }
130 1 : if (0 != strcmp (oldest->justification,
131 : justification) )
132 : {
133 0 : GNUNET_break (0);
134 0 : TALER_TESTING_interpreter_fail (ds->is);
135 0 : return;
136 : }
137 : }
138 : }
139 : }
140 4 : TALER_TESTING_interpreter_next (ds->is);
141 : }
142 :
143 :
144 : /**
145 : * Run the command.
146 : *
147 : * @param cls closure.
148 : * @param cmd the command to execute.
149 : * @param is the interpreter state.
150 : */
151 : static void
152 4 : check_aml_decisions_run (
153 : void *cls,
154 : const struct TALER_TESTING_Command *cmd,
155 : struct TALER_TESTING_Interpreter *is)
156 : {
157 4 : struct AmlCheckState *ds = cls;
158 4 : const struct TALER_NormalizedPaytoHashP *h_payto = NULL;
159 : const struct TALER_AmlOfficerPrivateKeyP *officer_priv;
160 : const struct TALER_TESTING_Command *ref;
161 : const char *exchange_url;
162 :
163 : (void) cmd;
164 4 : ds->is = is;
165 : {
166 : const struct TALER_TESTING_Command *exchange_cmd;
167 :
168 : exchange_cmd
169 4 : = TALER_TESTING_interpreter_get_command (
170 : is,
171 : "exchange");
172 4 : if (NULL == exchange_cmd)
173 : {
174 0 : GNUNET_break (0);
175 0 : TALER_TESTING_interpreter_fail (is);
176 0 : return;
177 : }
178 4 : GNUNET_assert (
179 : GNUNET_OK ==
180 : TALER_TESTING_get_trait_exchange_url (exchange_cmd,
181 : &exchange_url));
182 : }
183 :
184 4 : if (NULL != ds->ref_operation)
185 : {
186 3 : ref = TALER_TESTING_interpreter_lookup_command (
187 : is,
188 : ds->ref_operation);
189 3 : if (NULL == ref)
190 : {
191 0 : GNUNET_break (0);
192 0 : TALER_TESTING_interpreter_fail (is);
193 0 : return;
194 : }
195 3 : GNUNET_assert (GNUNET_OK ==
196 : TALER_TESTING_get_trait_h_normalized_payto (
197 : ref,
198 : &h_payto));
199 : }
200 4 : ref = TALER_TESTING_interpreter_lookup_command (
201 : is,
202 : ds->ref_officer);
203 4 : if (NULL == ref)
204 : {
205 0 : GNUNET_break (0);
206 0 : TALER_TESTING_interpreter_fail (is);
207 0 : return;
208 : }
209 4 : GNUNET_assert (GNUNET_OK ==
210 : TALER_TESTING_get_trait_officer_priv (
211 : ref,
212 : &officer_priv));
213 4 : ds->dh = TALER_EXCHANGE_lookup_aml_decisions (
214 : TALER_TESTING_interpreter_get_context (is),
215 : exchange_url,
216 : h_payto, /* NULL to return all */
217 : TALER_EXCHANGE_YNA_ALL,
218 : TALER_EXCHANGE_YNA_ALL,
219 : UINT64_MAX, /* offset */
220 : -1, /* limit */
221 : officer_priv,
222 : &check_aml_decisions_cb,
223 : ds);
224 4 : if (NULL == ds->dh)
225 : {
226 0 : GNUNET_break (0);
227 0 : TALER_TESTING_interpreter_fail (is);
228 0 : return;
229 : }
230 : }
231 :
232 :
233 : /**
234 : * Free the state of a "check_aml_decision" CMD, and possibly cancel a
235 : * pending operation thereof.
236 : *
237 : * @param cls closure, must be a `struct AmlCheckState`.
238 : * @param cmd the command which is being cleaned up.
239 : */
240 : static void
241 4 : check_aml_decisions_cleanup (
242 : void *cls,
243 : const struct TALER_TESTING_Command *cmd)
244 : {
245 4 : struct AmlCheckState *ds = cls;
246 :
247 4 : if (NULL != ds->dh)
248 : {
249 0 : TALER_TESTING_command_incomplete (ds->is,
250 : cmd->label);
251 0 : TALER_EXCHANGE_lookup_aml_decisions_cancel (ds->dh);
252 0 : ds->dh = NULL;
253 : }
254 4 : GNUNET_free (ds);
255 4 : }
256 :
257 :
258 : struct TALER_TESTING_Command
259 4 : TALER_TESTING_cmd_check_aml_decisions (
260 : const char *label,
261 : const char *ref_officer,
262 : const char *ref_operation,
263 : unsigned int expected_http_status)
264 : {
265 : struct AmlCheckState *ds;
266 :
267 4 : ds = GNUNET_new (struct AmlCheckState);
268 4 : ds->ref_officer = ref_officer;
269 4 : ds->ref_operation = ref_operation;
270 4 : ds->expected_http_status = expected_http_status;
271 : {
272 4 : struct TALER_TESTING_Command cmd = {
273 : .cls = ds,
274 : .label = label,
275 : .run = &check_aml_decisions_run,
276 : .cleanup = &check_aml_decisions_cleanup
277 : };
278 :
279 4 : return cmd;
280 : }
281 : }
282 :
283 :
284 : /* end of testing_api_cmd_check_aml_decisions.c */
|