exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_bank_admin_add_kycauth.c (10574B)


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