test_exchange_api_age_restriction.c (12509B)
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 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 CMD_TRANSFER_TO_EXCHANGE ( 113 "create-reserve-age", 114 "EUR:6.01"), 115 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 CMD_EXEC_WIREWATCH ("wirewatch-age"), 126 /** 127 * Withdraw EUR:5. 128 */ 129 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 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 TALER_TESTING_cmd_end () 147 }; 148 149 struct TALER_TESTING_Command spend_age[] = { 150 /** 151 * Spend the coin. 152 */ 153 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 GNUNET_TIME_UNIT_ZERO, 162 "EUR:4.99", 163 MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS)), 164 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 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 CMD_EXEC_WIREWATCH ( 177 "import-kyc-account-withdraw"), 178 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 GNUNET_TIME_UNIT_ZERO, 185 "EUR:4.99", 186 MHD_HTTP_OK), 187 TALER_TESTING_cmd_deposit_replay ( 188 "deposit-simple-replay-age", 189 "deposit-simple-age", 190 MHD_HTTP_OK), 191 TALER_TESTING_cmd_end () 192 }; 193 194 struct TALER_TESTING_Command refresh_age[] = { 195 /* Fill reserve with EUR:5, 1ct is for fees. */ 196 CMD_TRANSFER_TO_EXCHANGE ( 197 "refresh-create-reserve-age-1", 198 "EUR:6.01"), 199 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 CMD_EXEC_WIREWATCH ("wirewatch-age-2"), 209 /** 210 * Withdraw EUR:5 with age restriction for age 13. 211 */ 212 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 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 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 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 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 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 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 GNUNET_TIME_UNIT_ZERO, 264 "EUR:1", 265 MHD_HTTP_OK), 266 /** 267 * Try to spend a refreshed EUR:0.1 coin 268 */ 269 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 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 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 TALER_TESTING_cmd_melt ( 288 "refresh-melt-failing-age-2", 289 "refresh-reveal-age-1", 290 MHD_HTTP_CONFLICT, 291 NULL), 292 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 CMD_TRANSFER_TO_EXCHANGE ( 300 "create-reserve-kyc-1", 301 "EUR:30.02"), 302 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 CMD_EXEC_WIREWATCH ("wirewatch-age-withdraw-1"), 309 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 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 CMD_EXEC_WIREWATCH ( 322 "import-kyc-account"), 323 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 TALER_TESTING_cmd_get_kyc_info ( 330 "get-kyc-info", 331 "check-kyc-withdraw", 332 MHD_HTTP_OK), 333 TALER_TESTING_cmd_post_kyc_start ( 334 "start-kyc-process", 335 "get-kyc-info", 336 0, 337 MHD_HTTP_OK), 338 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 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 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 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 TALER_TESTING_cmd_withdraw_reveal_age_proof ( 367 "age-withdraw-coins-reveal-1", 368 "age-withdraw-coins-1", 369 MHD_HTTP_OK), 370 TALER_TESTING_cmd_end (), 371 }; 372 373 { 374 struct TALER_TESTING_Command commands[] = { 375 TALER_TESTING_cmd_run_fakebank ( 376 "run-fakebank", 377 cred.cfg, 378 "exchange-account-2"), 379 TALER_TESTING_cmd_system_start ( 380 "start-taler", 381 config_file, 382 "-e", 383 NULL), 384 TALER_TESTING_cmd_get_exchange ( 385 "get-exchange", 386 cred.cfg, 387 NULL, 388 true, 389 true), 390 TALER_TESTING_cmd_oauth_with_birthdate ( 391 "oauth-service-with-birthdate", 392 "2015-00-00", /* enough for a while */ 393 6666), 394 TALER_TESTING_cmd_batch ("withdraw-age", 395 withdraw_age), 396 TALER_TESTING_cmd_batch ("spend-age", 397 spend_age), 398 TALER_TESTING_cmd_batch ("refresh-age", 399 refresh_age), 400 TALER_TESTING_cmd_batch ("age-withdraw", 401 age_withdraw), 402 /* End the suite. */ 403 TALER_TESTING_cmd_end () 404 }; 405 406 (void) cls; 407 TALER_TESTING_run (is, 408 commands); 409 } 410 } 411 412 413 int 414 main (int argc, 415 char *const *argv) 416 { 417 (void) argc; 418 { 419 char *cipher; 420 421 cipher = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]); 422 GNUNET_assert (NULL != cipher); 423 uses_cs = (0 == strcmp (cipher, 424 "cs")); 425 GNUNET_asprintf ( 426 &config_file, 427 "test_exchange_api_age_restriction-%s.conf", 428 cipher); 429 GNUNET_free (cipher); 430 } 431 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 */