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