Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as
7 : published by the Free Software Foundation; either version 3, or
8 : (at your 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
13 : GNU 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/test_exchange_api_age_restriction.c
21 : * @brief testcase to test exchange's age-restrictrition related HTTP API interfaces
22 : * @author Özgür Kesim
23 : */
24 : #include "taler/taler_util.h"
25 : #include "taler/taler_json_lib.h"
26 : #include <gnunet/gnunet_util_lib.h>
27 : #include <gnunet/gnunet_testing_lib.h>
28 : #include <microhttpd.h>
29 : #include "taler/taler_bank_service.h"
30 : #include "taler/taler_testing_lib.h"
31 : #include "taler/taler_extensions.h"
32 :
33 : /**
34 : * Configuration file we use. One (big) configuration is used
35 : * for the various components for this test.
36 : */
37 : static char *config_file;
38 :
39 : /**
40 : * Our credentials.
41 : */
42 : static struct TALER_TESTING_Credentials cred;
43 :
44 : /**
45 : * Some tests behave differently when using CS as we cannot
46 : * reuse the coin private key for different denominations
47 : * due to the derivation of it with the /csr values. Hence
48 : * some tests behave differently in CS mode, hence this
49 : * flag.
50 : */
51 : static bool uses_cs;
52 :
53 : /**
54 : * Execute the taler-exchange-wirewatch command with
55 : * our configuration file.
56 : *
57 : * @param label label to use for the command.
58 : */
59 : #define CMD_EXEC_WIREWATCH(label) \
60 : TALER_TESTING_cmd_exec_wirewatch2 (label, config_file, \
61 : "exchange-account-2")
62 :
63 : /**
64 : * Execute the taler-exchange-aggregator, closer and transfer commands with
65 : * our configuration file.
66 : *
67 : * @param label label to use for the command.
68 : */
69 : #define CMD_EXEC_AGGREGATOR(label) \
70 : TALER_TESTING_cmd_sleep ("sleep-before-aggregator", 2), \
71 : TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \
72 : TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file)
73 :
74 :
75 : /**
76 : * Run wire transfer of funds from some user's account to the
77 : * exchange.
78 : *
79 : * @param label label to use for the command.
80 : * @param amount amount to transfer, i.e. "EUR:1"
81 : */
82 : #define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
83 : TALER_TESTING_cmd_admin_add_incoming (label, amount, \
84 : &cred.ba, \
85 : cred.user42_payto)
86 :
87 : /**
88 : * Main function that will tell the interpreter what commands to
89 : * run.
90 : *
91 : * @param cls closure
92 : * @param is interpreter we use to run commands
93 : */
94 : static void
95 2 : run (void *cls,
96 : struct TALER_TESTING_Interpreter *is)
97 : {
98 : /**
99 : * Test withdrawal with age restriction. Success is expected (because the
100 : * amount is below the kyc threshold ), so it MUST be
101 : * called _after_ TALER_TESTING_cmd_exec_offline_sign_extensions is called,
102 : * i. e. age restriction is activated in the exchange!
103 : *
104 : * FIXME: create a test that tries to withdraw coins with age restriction but
105 : * (expectedly) fails because the exchange doesn't support age restriction
106 : * yet.
107 : */
108 : struct TALER_TESTING_Command withdraw_age[] = {
109 : /**
110 : * Move money to the exchange's bank account.
111 : */
112 2 : CMD_TRANSFER_TO_EXCHANGE (
113 : "create-reserve-age",
114 : "EUR:6.01"),
115 2 : TALER_TESTING_cmd_check_bank_admin_transfer (
116 : "check-create-reserve-age",
117 : "EUR:6.01",
118 : cred.user42_payto,
119 : cred.exchange_payto,
120 : "create-reserve-age"),
121 : /**
122 : * Make a reserve exist, according to the previous
123 : * transfer.
124 : */
125 2 : CMD_EXEC_WIREWATCH ("wirewatch-age"),
126 : /**
127 : * Withdraw EUR:5.
128 : */
129 2 : TALER_TESTING_cmd_withdraw_amount (
130 : "withdraw-coin-age-1",
131 : "create-reserve-age",
132 : "EUR:5",
133 : 13,
134 : MHD_HTTP_OK),
135 : /**
136 : * Idempotent withdrawal.
137 : */
138 2 : TALER_TESTING_cmd_withdraw_amount_reuse_all_secrets (
139 : "withdraw-coin-age-idem-1",
140 : "create-reserve-age",
141 : "EUR:5",
142 : 13,
143 : "withdraw-coin-age-1",
144 : MHD_HTTP_OK),
145 :
146 2 : TALER_TESTING_cmd_end ()
147 : };
148 :
149 : struct TALER_TESTING_Command spend_age[] = {
150 : /**
151 : * Spend the coin.
152 : */
153 2 : TALER_TESTING_cmd_set_var (
154 : "account-priv",
155 : TALER_TESTING_cmd_deposit (
156 : "deposit-simple-age-fail-kyc",
157 : "withdraw-coin-age-1",
158 : 0,
159 : cred.user42_payto,
160 : "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
161 2 : GNUNET_TIME_UNIT_ZERO,
162 : "EUR:4.99",
163 : MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS)),
164 2 : TALER_TESTING_cmd_admin_add_kycauth (
165 : "kyc-auth-transfer",
166 : "EUR:0.01",
167 : &cred.ba,
168 : cred.user42_payto,
169 : "deposit-simple-age-fail-kyc"),
170 2 : TALER_TESTING_cmd_admin_add_kycauth (
171 : "kyc-auth-transfer",
172 : "EUR:0.01",
173 : &cred.ba,
174 : cred.user43_payto,
175 : "deposit-simple-age-fail-kyc"),
176 2 : CMD_EXEC_WIREWATCH (
177 : "import-kyc-account-withdraw"),
178 2 : TALER_TESTING_cmd_deposit (
179 : "deposit-simple-age",
180 : "withdraw-coin-age-1",
181 : 0,
182 : cred.user42_payto,
183 : "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}",
184 2 : GNUNET_TIME_UNIT_ZERO,
185 : "EUR:4.99",
186 : MHD_HTTP_OK),
187 2 : TALER_TESTING_cmd_deposit_replay (
188 : "deposit-simple-replay-age",
189 : "deposit-simple-age",
190 : MHD_HTTP_OK),
191 2 : TALER_TESTING_cmd_end ()
192 : };
193 :
194 : struct TALER_TESTING_Command refresh_age[] = {
195 : /* Fill reserve with EUR:5, 1ct is for fees. */
196 2 : CMD_TRANSFER_TO_EXCHANGE (
197 : "refresh-create-reserve-age-1",
198 : "EUR:6.01"),
199 2 : TALER_TESTING_cmd_check_bank_admin_transfer (
200 : "ck-refresh-create-reserve-age-1",
201 : "EUR:6.01",
202 : cred.user42_payto,
203 : cred.exchange_payto,
204 : "refresh-create-reserve-age-1"),
205 : /**
206 : * Make previous command effective.
207 : */
208 2 : CMD_EXEC_WIREWATCH ("wirewatch-age-2"),
209 : /**
210 : * Withdraw EUR:5 with age restriction for age 13.
211 : */
212 2 : TALER_TESTING_cmd_withdraw_amount (
213 : "refresh-withdraw-coin-age-1",
214 : "refresh-create-reserve-age-1",
215 : "EUR:5",
216 : 13,
217 : MHD_HTTP_OK),
218 : /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin
219 : * (in full) (merchant would receive EUR:0.99 due to 1 ct
220 : * deposit fee)
221 : */
222 2 : TALER_TESTING_cmd_deposit (
223 : "refresh-deposit-partial-age",
224 : "refresh-withdraw-coin-age-1",
225 : 0,
226 : cred.user42_payto,
227 : "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:3\"}]}",
228 2 : GNUNET_TIME_UNIT_ZERO,
229 : "EUR:1",
230 : MHD_HTTP_OK),
231 : /**
232 : * Melt the rest of the coin's value
233 : * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
234 2 : TALER_TESTING_cmd_melt_double (
235 : "refresh-melt-age-1",
236 : "refresh-withdraw-coin-age-1",
237 : MHD_HTTP_OK,
238 : NULL),
239 : /**
240 : * Complete (successful) melt operation, and
241 : * withdraw the coins
242 : */
243 2 : TALER_TESTING_cmd_melt_reveal (
244 : "refresh-reveal-age-1",
245 : "refresh-melt-age-1",
246 : MHD_HTTP_OK),
247 : /**
248 : * Do it again to check idempotency
249 : */
250 2 : TALER_TESTING_cmd_melt_reveal (
251 : "refresh-reveal-age-1-idempotency",
252 : "refresh-melt-age-1",
253 : MHD_HTTP_OK),
254 : /**
255 : * Try to spend a refreshed EUR:1 coin
256 : */
257 2 : TALER_TESTING_cmd_deposit (
258 : "refresh-deposit-refreshed-age-1a",
259 : "refresh-reveal-age-1-idempotency",
260 : 0,
261 : cred.user42_payto,
262 : "{\"items\":[{\"name\":\"ice cream\",\"value\":4}]}",
263 2 : GNUNET_TIME_UNIT_ZERO,
264 : "EUR:1",
265 : MHD_HTTP_OK),
266 : /**
267 : * Try to spend a refreshed EUR:0.1 coin
268 : */
269 2 : TALER_TESTING_cmd_deposit (
270 : "refresh-deposit-refreshed-age-1b",
271 : "refresh-reveal-age-1",
272 : 3,
273 : cred.user43_payto,
274 : "{\"items\":[{\"name\":\"ice cream\",\"value\":5}]}",
275 2 : GNUNET_TIME_UNIT_ZERO,
276 : "EUR:0.1",
277 : MHD_HTTP_OK),
278 : /* Test running a failing melt operation (same operation
279 : * again must fail) */
280 2 : TALER_TESTING_cmd_melt (
281 : "refresh-melt-failing-age",
282 : "refresh-withdraw-coin-age-1",
283 : MHD_HTTP_CONFLICT,
284 : NULL),
285 : /* Test running a failing melt operation (on a coin that
286 : was itself revealed and subsequently deposited) */
287 2 : TALER_TESTING_cmd_melt (
288 : "refresh-melt-failing-age-2",
289 : "refresh-reveal-age-1",
290 : MHD_HTTP_CONFLICT,
291 : NULL),
292 2 : TALER_TESTING_cmd_end ()
293 : };
294 :
295 : /**
296 : * Test with age-withdraw, after kyc process has set a birthdate
297 : */
298 : struct TALER_TESTING_Command age_withdraw[] = {
299 2 : CMD_TRANSFER_TO_EXCHANGE (
300 : "create-reserve-kyc-1",
301 : "EUR:30.02"),
302 2 : TALER_TESTING_cmd_check_bank_admin_transfer (
303 : "check-create-reserve-kyc-1",
304 : "EUR:30.02",
305 : cred.user42_payto,
306 : cred.exchange_payto,
307 : "create-reserve-kyc-1"),
308 2 : CMD_EXEC_WIREWATCH ("wirewatch-age-withdraw-1"),
309 2 : TALER_TESTING_cmd_withdraw_amount (
310 : "withdraw-coin-1-lacking-kyc",
311 : "create-reserve-kyc-1",
312 : "EUR:10",
313 : 0, /* age restriction off */
314 : MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS),
315 2 : TALER_TESTING_cmd_admin_add_kycauth (
316 : "setup-account-key",
317 : "EUR:0.01",
318 : &cred.ba,
319 : cred.user42_payto,
320 : NULL /* create new key */),
321 2 : CMD_EXEC_WIREWATCH (
322 : "import-kyc-account"),
323 2 : TALER_TESTING_cmd_check_kyc_get (
324 : "check-kyc-withdraw",
325 : "withdraw-coin-1-lacking-kyc",
326 : "setup-account-key",
327 : TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER,
328 : MHD_HTTP_ACCEPTED),
329 2 : TALER_TESTING_cmd_get_kyc_info (
330 : "get-kyc-info",
331 : "check-kyc-withdraw",
332 : MHD_HTTP_OK),
333 2 : TALER_TESTING_cmd_post_kyc_start (
334 : "start-kyc-process",
335 : "get-kyc-info",
336 : 0,
337 : MHD_HTTP_OK),
338 2 : TALER_TESTING_cmd_proof_kyc_oauth2 (
339 : "proof-withdraw-kyc",
340 : "withdraw-coin-1-lacking-kyc",
341 : "test-oauth2",
342 : "pass",
343 : MHD_HTTP_SEE_OTHER),
344 2 : TALER_TESTING_cmd_withdraw_amount (
345 : "withdraw-coin-1-with-kyc",
346 : "create-reserve-kyc-1",
347 : "EUR:10",
348 : 0, /* age restriction off */
349 : MHD_HTTP_CONFLICT),
350 2 : TALER_TESTING_cmd_withdraw_with_age_proof (
351 : "age-withdraw-coin-1-too-low",
352 : "create-reserve-kyc-1",
353 : 18, /* Too high */
354 : MHD_HTTP_CONFLICT,
355 : "EUR:10",
356 : NULL),
357 2 : TALER_TESTING_cmd_withdraw_with_age_proof (
358 : "age-withdraw-coins-1",
359 : "create-reserve-kyc-1",
360 : 8,
361 : MHD_HTTP_CREATED,
362 : "EUR:10",
363 : "EUR:10",
364 : "EUR:5",
365 : NULL),
366 2 : TALER_TESTING_cmd_withdraw_reveal_age_proof (
367 : "age-withdraw-coins-reveal-1",
368 : "age-withdraw-coins-1",
369 : MHD_HTTP_OK),
370 2 : TALER_TESTING_cmd_end (),
371 : };
372 :
373 : {
374 : struct TALER_TESTING_Command commands[] = {
375 2 : TALER_TESTING_cmd_run_fakebank (
376 : "run-fakebank",
377 2 : cred.cfg,
378 : "exchange-account-2"),
379 2 : TALER_TESTING_cmd_system_start (
380 : "start-taler",
381 : config_file,
382 : "-e",
383 : NULL),
384 2 : TALER_TESTING_cmd_get_exchange (
385 : "get-exchange",
386 2 : cred.cfg,
387 : NULL,
388 : true,
389 : true),
390 2 : TALER_TESTING_cmd_oauth_with_birthdate (
391 : "oauth-service-with-birthdate",
392 : "2015-00-00", /* enough for a while */
393 : 6666),
394 2 : TALER_TESTING_cmd_batch ("withdraw-age",
395 : withdraw_age),
396 2 : TALER_TESTING_cmd_batch ("spend-age",
397 : spend_age),
398 2 : TALER_TESTING_cmd_batch ("refresh-age",
399 : refresh_age),
400 2 : TALER_TESTING_cmd_batch ("age-withdraw",
401 : age_withdraw),
402 : /* End the suite. */
403 2 : TALER_TESTING_cmd_end ()
404 : };
405 :
406 : (void) cls;
407 2 : TALER_TESTING_run (is,
408 : commands);
409 : }
410 2 : }
411 :
412 :
413 : int
414 2 : main (int argc,
415 : char *const *argv)
416 : {
417 : (void) argc;
418 : {
419 : char *cipher;
420 :
421 2 : cipher = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]);
422 2 : GNUNET_assert (NULL != cipher);
423 2 : uses_cs = (0 == strcmp (cipher,
424 2 : "cs"));
425 2 : GNUNET_asprintf (
426 : &config_file,
427 : "test_exchange_api_age_restriction-%s.conf",
428 : cipher);
429 2 : GNUNET_free (cipher);
430 : }
431 2 : return TALER_TESTING_main (
432 : argv,
433 : "INFO",
434 : config_file,
435 : "exchange-account-2",
436 : TALER_TESTING_BS_FAKEBANK,
437 : &cred,
438 : &run,
439 : NULL);
440 : }
441 :
442 :
443 : /* end of test_exchange_api_age_restriction.c */
|