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 (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 */