testing_api_cmd_bank_admin_add_kycauth.c (10629B)
1 /* 2 This file is part of TALER 3 Copyright (C) 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_bank_admin_add_kycauth.c 21 * @brief implementation of a bank /admin/add-kycauth command 22 * @author Christian Grothoff 23 * @author Marcello Stanisci 24 */ 25 #include "taler/platform.h" 26 #include "taler/backoff.h" 27 #include "taler/taler_json_lib.h" 28 #include <gnunet/gnunet_curl_lib.h> 29 #include "taler/taler_bank_service.h" 30 #include "taler/taler_signatures.h" 31 #include "taler/taler_testing_lib.h" 32 33 34 /** 35 * State for a KYCAUTH wire transfer CMD. 36 */ 37 struct AdminAddKycauthState 38 { 39 40 /** 41 * Label of any command that can trait-offer an account priv. 42 */ 43 const char *account_ref; 44 45 /** 46 * Wire transfer amount. 47 */ 48 struct TALER_Amount amount; 49 50 /** 51 * Base URL of the credited account. 52 */ 53 const char *exchange_credit_url; 54 55 /** 56 * Money sender payto URL. 57 */ 58 struct TALER_FullPayto payto_debit_account; 59 60 /** 61 * Username to use for authentication. 62 */ 63 struct TALER_BANK_AuthenticationData auth; 64 65 /** 66 * Set (by the interpreter) to the account's private key 67 * we used to make a wire transfer subject line with. 68 */ 69 union TALER_AccountPrivateKeyP account_priv; 70 71 /** 72 * Account public key matching @e account_priv. 73 */ 74 union TALER_AccountPublicKeyP account_pub; 75 76 /** 77 * Handle to the pending request at the bank. 78 */ 79 struct TALER_BANK_AdminAddKycauthHandle *aih; 80 81 /** 82 * Interpreter state. 83 */ 84 struct TALER_TESTING_Interpreter *is; 85 86 /** 87 * Set to the wire transfer's unique ID. 88 */ 89 uint64_t serial_id; 90 91 /** 92 * Timestamp of the transaction (as returned from the bank). 93 */ 94 struct GNUNET_TIME_Timestamp timestamp; 95 96 /** 97 * Expected HTTP status code. 98 */ 99 unsigned int expected_http_status; 100 101 /** 102 * Do we have @e account_priv? 103 */ 104 bool have_priv; 105 }; 106 107 108 /** 109 * This callback will process the bank response to the wire 110 * transfer. It just checks whether the HTTP response code is 111 * acceptable. 112 * 113 * @param cls closure with the interpreter state 114 * @param air response details 115 */ 116 static void 117 confirmation_cb (void *cls, 118 const struct TALER_BANK_AdminAddKycauthResponse *air) 119 { 120 struct AdminAddKycauthState *fts = cls; 121 struct TALER_TESTING_Interpreter *is = fts->is; 122 123 fts->aih = NULL; 124 if (air->http_status != fts->expected_http_status) 125 { 126 TALER_TESTING_unexpected_status (is, 127 air->http_status, 128 fts->expected_http_status); 129 return; 130 } 131 switch (air->http_status) 132 { 133 case MHD_HTTP_OK: 134 fts->serial_id 135 = air->details.ok.serial_id; 136 fts->timestamp 137 = air->details.ok.timestamp; 138 TALER_TESTING_interpreter_next (is); 139 return; 140 case MHD_HTTP_UNAUTHORIZED: 141 switch (fts->auth.method) 142 { 143 case TALER_BANK_AUTH_NONE: 144 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 145 "Authentication required, but none configure.\n"); 146 break; 147 case TALER_BANK_AUTH_BASIC: 148 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 149 "Basic authentication (%s) failed.\n", 150 fts->auth.details.basic.username); 151 break; 152 case TALER_BANK_AUTH_BEARER: 153 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 154 "Bearer authentication (%s) failed.\n", 155 fts->auth.details.bearer.token); 156 break; 157 } 158 break; 159 case MHD_HTTP_CONFLICT: 160 TALER_TESTING_interpreter_next (is); 161 return; 162 default: 163 GNUNET_break (0); 164 break; 165 } 166 GNUNET_break (0); 167 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 168 "Bank returned HTTP status %u/%d\n", 169 air->http_status, 170 (int) air->ec); 171 TALER_TESTING_interpreter_fail (is); 172 } 173 174 175 /** 176 * Run the KYC AUTH transfer CMD. 177 * 178 * @param cls closure. 179 * @param cmd CMD being run. 180 * @param is interpreter state. 181 */ 182 static void 183 admin_add_kycauth_run (void *cls, 184 const struct TALER_TESTING_Command *cmd, 185 struct TALER_TESTING_Interpreter *is) 186 { 187 struct AdminAddKycauthState *fts = cls; 188 189 (void) cmd; 190 fts->is = is; 191 /* Use account public key as subject */ 192 if (NULL != fts->account_ref) 193 { 194 const struct TALER_TESTING_Command *ref; 195 const union TALER_AccountPrivateKeyP *account_priv; 196 197 ref = TALER_TESTING_interpreter_lookup_command ( 198 is, 199 fts->account_ref); 200 if (NULL == ref) 201 { 202 GNUNET_break (0); 203 TALER_TESTING_interpreter_fail (is); 204 return; 205 } 206 if (GNUNET_OK != 207 TALER_TESTING_get_trait_account_priv (ref, 208 &account_priv)) 209 { 210 const union TALER_AccountPublicKeyP *account_pub; 211 212 if (GNUNET_OK != 213 TALER_TESTING_get_trait_account_pub (ref, 214 &account_pub)) 215 { 216 GNUNET_break (0); 217 TALER_TESTING_interpreter_fail (is); 218 return; 219 } 220 fts->account_pub = *account_pub; 221 } 222 else 223 { 224 fts->account_priv = *account_priv; 225 fts->have_priv = true; 226 GNUNET_CRYPTO_eddsa_key_get_public ( 227 &fts->account_priv.merchant_priv.eddsa_priv, 228 &fts->account_pub.merchant_pub.eddsa_pub); 229 } 230 } 231 else 232 { 233 /* No referenced account, no instance to take priv 234 * from, no explicit subject given: create new key! */ 235 GNUNET_CRYPTO_eddsa_key_create ( 236 &fts->account_priv.merchant_priv.eddsa_priv); 237 fts->have_priv = true; 238 GNUNET_CRYPTO_eddsa_key_get_public ( 239 &fts->account_priv.merchant_priv.eddsa_priv, 240 &fts->account_pub.merchant_pub.eddsa_pub); 241 } 242 fts->aih 243 = TALER_BANK_admin_add_kycauth ( 244 TALER_TESTING_interpreter_get_context (is), 245 &fts->auth, 246 &fts->account_pub, 247 &fts->amount, 248 fts->payto_debit_account, 249 &confirmation_cb, 250 fts); 251 if (NULL == fts->aih) 252 { 253 GNUNET_break (0); 254 TALER_TESTING_interpreter_fail (is); 255 return; 256 } 257 } 258 259 260 /** 261 * Free the state of a "/admin/add-kycauth" CMD, and possibly 262 * cancel a pending operation thereof. 263 * 264 * @param cls closure 265 * @param cmd current CMD being cleaned up. 266 */ 267 static void 268 admin_add_kycauth_cleanup (void *cls, 269 const struct TALER_TESTING_Command *cmd) 270 { 271 struct AdminAddKycauthState *fts = cls; 272 273 if (NULL != fts->aih) 274 { 275 TALER_TESTING_command_incomplete (fts->is, 276 cmd->label); 277 TALER_BANK_admin_add_kycauth_cancel (fts->aih); 278 fts->aih = NULL; 279 } 280 GNUNET_free (fts); 281 } 282 283 284 /** 285 * Offer internal data from a "/admin/add-kycauth" CMD to other 286 * commands. 287 * 288 * @param cls closure. 289 * @param[out] ret result 290 * @param trait name of the trait. 291 * @param index index number of the object to offer. 292 * @return #GNUNET_OK on success. 293 */ 294 static enum GNUNET_GenericReturnValue 295 admin_add_kycauth_traits (void *cls, 296 const void **ret, 297 const char *trait, 298 unsigned int index) 299 { 300 struct AdminAddKycauthState *fts = cls; 301 static struct TALER_FullPayto void_uri = { 302 .full_payto = (char *) "payto://void/the-exchange?receiver=name=exchange" 303 }; 304 struct TALER_TESTING_Trait traits[] = { 305 /* must be first! */ 306 TALER_TESTING_make_trait_account_priv (&fts->account_priv), 307 TALER_TESTING_make_trait_bank_row (&fts->serial_id), 308 TALER_TESTING_make_trait_debit_payto_uri (&fts->payto_debit_account), 309 TALER_TESTING_make_trait_full_payto_uri (&fts->payto_debit_account), 310 /* Used as a marker, content does not matter */ 311 TALER_TESTING_make_trait_credit_payto_uri (&void_uri), 312 TALER_TESTING_make_trait_exchange_bank_account_url ( 313 fts->exchange_credit_url), 314 TALER_TESTING_make_trait_amount (&fts->amount), 315 TALER_TESTING_make_trait_timestamp (0, 316 &fts->timestamp), 317 TALER_TESTING_make_trait_account_pub (&fts->account_pub), 318 TALER_TESTING_trait_end () 319 }; 320 321 if (MHD_HTTP_OK != 322 fts->expected_http_status) 323 return GNUNET_NO; /* requests that failed generate no history */ 324 325 return TALER_TESTING_get_trait (traits + (fts->have_priv ? 0 : 1), 326 ret, 327 trait, 328 index); 329 } 330 331 332 /** 333 * Create internal state for "/admin/add-kycauth" CMD. 334 * 335 * @param amount the amount to transfer. 336 * @param payto_debit_account which account sends money 337 * @param auth authentication data 338 * @param account_ref reference to command with account 339 * private key to use; NULL to create a fresh key pair 340 * @return the internal state 341 */ 342 static struct AdminAddKycauthState * 343 make_fts (const char *amount, 344 const struct TALER_BANK_AuthenticationData *auth, 345 const struct TALER_FullPayto payto_debit_account, 346 const char *account_ref) 347 { 348 struct AdminAddKycauthState *fts; 349 350 fts = GNUNET_new (struct AdminAddKycauthState); 351 fts->exchange_credit_url = auth->wire_gateway_url; 352 fts->payto_debit_account = payto_debit_account; 353 fts->account_ref = account_ref; 354 fts->auth = *auth; 355 fts->expected_http_status = MHD_HTTP_OK; 356 if (GNUNET_OK != 357 TALER_string_to_amount (amount, 358 &fts->amount)) 359 { 360 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 361 "Failed to parse amount `%s'\n", 362 amount); 363 GNUNET_assert (0); 364 } 365 return fts; 366 } 367 368 369 struct TALER_TESTING_Command 370 TALER_TESTING_cmd_admin_add_kycauth ( 371 const char *label, 372 const char *amount, 373 const struct TALER_BANK_AuthenticationData *auth, 374 const struct TALER_FullPayto payto_debit_account, 375 const char *account_ref) 376 { 377 struct TALER_TESTING_Command cmd = { 378 .cls = make_fts (amount, 379 auth, 380 payto_debit_account, 381 account_ref), 382 .label = label, 383 .run = &admin_add_kycauth_run, 384 .cleanup = &admin_add_kycauth_cleanup, 385 .traits = &admin_add_kycauth_traits 386 }; 387 388 return cmd; 389 } 390 391 392 /* end of testing_api_cmd_bank_admin_add_kycauth.c */