LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_bank_admin_add_kycauth.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 67 108 62.0 %
Date: 2025-06-05 21:03:14 Functions: 6 6 100.0 %

          Line data    Source code
       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 "platform.h"
      26             : #include "backoff.h"
      27             : #include "taler_json_lib.h"
      28             : #include <gnunet/gnunet_curl_lib.h>
      29             : #include "taler_bank_service.h"
      30             : #include "taler_signatures.h"
      31             : #include "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          16 : confirmation_cb (void *cls,
     118             :                  const struct TALER_BANK_AdminAddKycauthResponse *air)
     119             : {
     120          16 :   struct AdminAddKycauthState *fts = cls;
     121          16 :   struct TALER_TESTING_Interpreter *is = fts->is;
     122             : 
     123          16 :   fts->aih = NULL;
     124          16 :   if (air->http_status != fts->expected_http_status)
     125             :   {
     126           0 :     TALER_TESTING_unexpected_status (is,
     127             :                                      air->http_status,
     128             :                                      fts->expected_http_status);
     129           0 :     return;
     130             :   }
     131          16 :   switch (air->http_status)
     132             :   {
     133          16 :   case MHD_HTTP_OK:
     134             :     fts->serial_id
     135          16 :       = air->details.ok.serial_id;
     136             :     fts->timestamp
     137          16 :       = air->details.ok.timestamp;
     138          16 :     TALER_TESTING_interpreter_next (is);
     139          16 :     return;
     140           0 :   case MHD_HTTP_UNAUTHORIZED:
     141           0 :     switch (fts->auth.method)
     142             :     {
     143           0 :     case TALER_BANK_AUTH_NONE:
     144           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     145             :                   "Authentication required, but none configure.\n");
     146           0 :       break;
     147           0 :     case TALER_BANK_AUTH_BASIC:
     148           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     149             :                   "Basic authentication (%s) failed.\n",
     150             :                   fts->auth.details.basic.username);
     151           0 :       break;
     152           0 :     case TALER_BANK_AUTH_BEARER:
     153           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     154             :                   "Bearer authentication (%s) failed.\n",
     155             :                   fts->auth.details.bearer.token);
     156           0 :       break;
     157             :     }
     158           0 :     break;
     159           0 :   case MHD_HTTP_CONFLICT:
     160           0 :     TALER_TESTING_interpreter_next (is);
     161           0 :     return;
     162           0 :   default:
     163           0 :     GNUNET_break (0);
     164           0 :     break;
     165             :   }
     166           0 :   GNUNET_break (0);
     167           0 :   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     168             :               "Bank returned HTTP status %u/%d\n",
     169             :               air->http_status,
     170             :               (int) air->ec);
     171           0 :   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          16 : admin_add_kycauth_run (void *cls,
     184             :                        const struct TALER_TESTING_Command *cmd,
     185             :                        struct TALER_TESTING_Interpreter *is)
     186             : {
     187          16 :   struct AdminAddKycauthState *fts = cls;
     188             : 
     189             :   (void) cmd;
     190          16 :   fts->is = is;
     191             :   /* Use account public key as subject */
     192          16 :   if (NULL != fts->account_ref)
     193             :   {
     194             :     const struct TALER_TESTING_Command *ref;
     195             :     const union TALER_AccountPrivateKeyP *account_priv;
     196             : 
     197          10 :     ref = TALER_TESTING_interpreter_lookup_command (
     198             :       is,
     199             :       fts->account_ref);
     200          10 :     if (NULL == ref)
     201             :     {
     202           0 :       GNUNET_break (0);
     203           0 :       TALER_TESTING_interpreter_fail (is);
     204           0 :       return;
     205             :     }
     206          10 :     if (GNUNET_OK !=
     207          10 :         TALER_TESTING_get_trait_account_priv (ref,
     208             :                                               &account_priv))
     209             :     {
     210             :       const union TALER_AccountPublicKeyP *account_pub;
     211             : 
     212           0 :       if (GNUNET_OK !=
     213           0 :           TALER_TESTING_get_trait_account_pub (ref,
     214             :                                                &account_pub))
     215             :       {
     216           0 :         GNUNET_break (0);
     217           0 :         TALER_TESTING_interpreter_fail (is);
     218           0 :         return;
     219             :       }
     220           0 :       fts->account_pub = *account_pub;
     221             :     }
     222             :     else
     223             :     {
     224          10 :       fts->account_priv = *account_priv;
     225          10 :       fts->have_priv = true;
     226          10 :       GNUNET_CRYPTO_eddsa_key_get_public (
     227          10 :         &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           6 :     GNUNET_CRYPTO_eddsa_key_create (
     236             :       &fts->account_priv.merchant_priv.eddsa_priv);
     237           6 :     fts->have_priv = true;
     238           6 :     GNUNET_CRYPTO_eddsa_key_get_public (
     239           6 :       &fts->account_priv.merchant_priv.eddsa_priv,
     240             :       &fts->account_pub.merchant_pub.eddsa_pub);
     241             :   }
     242             :   fts->aih
     243          16 :     = TALER_BANK_admin_add_kycauth (
     244             :         TALER_TESTING_interpreter_get_context (is),
     245          16 :         &fts->auth,
     246          16 :         &fts->account_pub,
     247          16 :         &fts->amount,
     248             :         fts->payto_debit_account,
     249             :         &confirmation_cb,
     250             :         fts);
     251          16 :   if (NULL == fts->aih)
     252             :   {
     253           0 :     GNUNET_break (0);
     254           0 :     TALER_TESTING_interpreter_fail (is);
     255           0 :     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          16 : admin_add_kycauth_cleanup (void *cls,
     269             :                            const struct TALER_TESTING_Command *cmd)
     270             : {
     271          16 :   struct AdminAddKycauthState *fts = cls;
     272             : 
     273          16 :   if (NULL != fts->aih)
     274             :   {
     275           0 :     TALER_TESTING_command_incomplete (fts->is,
     276             :                                       cmd->label);
     277           0 :     TALER_BANK_admin_add_kycauth_cancel (fts->aih);
     278           0 :     fts->aih = NULL;
     279             :   }
     280          16 :   GNUNET_free (fts);
     281          16 : }
     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          33 : admin_add_kycauth_traits (void *cls,
     296             :                           const void **ret,
     297             :                           const char *trait,
     298             :                           unsigned int index)
     299             : {
     300          33 :   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          33 :     TALER_TESTING_make_trait_account_priv (&fts->account_priv),
     307          33 :     TALER_TESTING_make_trait_bank_row (&fts->serial_id),
     308          33 :     TALER_TESTING_make_trait_debit_payto_uri (&fts->payto_debit_account),
     309          33 :     TALER_TESTING_make_trait_full_payto_uri (&fts->payto_debit_account),
     310             :     /* Used as a marker, content does not matter */
     311          33 :     TALER_TESTING_make_trait_credit_payto_uri (&void_uri),
     312          33 :     TALER_TESTING_make_trait_exchange_bank_account_url (
     313             :       fts->exchange_credit_url),
     314          33 :     TALER_TESTING_make_trait_amount (&fts->amount),
     315          33 :     TALER_TESTING_make_trait_timestamp (0,
     316          33 :                                         &fts->timestamp),
     317          33 :     TALER_TESTING_make_trait_account_pub (&fts->account_pub),
     318          33 :     TALER_TESTING_trait_end ()
     319             :   };
     320             : 
     321          33 :   if (MHD_HTTP_OK !=
     322          33 :       fts->expected_http_status)
     323           0 :     return GNUNET_NO; /* requests that failed generate no history */
     324             : 
     325          33 :   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          16 : 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          16 :   fts = GNUNET_new (struct AdminAddKycauthState);
     351          16 :   fts->exchange_credit_url = auth->wire_gateway_url;
     352          16 :   fts->payto_debit_account = payto_debit_account;
     353          16 :   fts->account_ref = account_ref;
     354          16 :   fts->auth = *auth;
     355          16 :   fts->expected_http_status = MHD_HTTP_OK;
     356          16 :   if (GNUNET_OK !=
     357          16 :       TALER_string_to_amount (amount,
     358             :                               &fts->amount))
     359             :   {
     360           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     361             :                 "Failed to parse amount `%s'\n",
     362             :                 amount);
     363           0 :     GNUNET_assert (0);
     364             :   }
     365          16 :   return fts;
     366             : }
     367             : 
     368             : 
     369             : struct TALER_TESTING_Command
     370          16 : 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          32 :   struct TALER_TESTING_Command cmd = {
     378          16 :     .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          16 :   return cmd;
     389             : }
     390             : 
     391             : 
     392             : /* end of testing_api_cmd_bank_admin_add_kycauth.c */

Generated by: LCOV version 1.16