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_kyc_proof.c (8424B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2021-2026 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 /**
     21  * @file testing/testing_api_cmd_kyc_proof.c
     22  * @brief Implement the testing CMDs for the /kyc-proof/ operation.
     23  * @author Christian Grothoff
     24  */
     25 #include "taler/taler_json_lib.h"
     26 #include <gnunet/gnunet_curl_lib.h>
     27 
     28 /**
     29  * State for a "track transaction" CMD.
     30  */
     31 struct KycProofGetState;
     32 
     33 #define TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE \
     34         struct KycProofGetState
     35 #include "taler/exchange/get-kyc-proof-PROVIDER_NAME.h"
     36 #include "taler/taler_testing_lib.h"
     37 
     38 /**
     39  * State for a "track transaction" CMD.
     40  */
     41 struct KycProofGetState
     42 {
     43 
     44   /**
     45    * Command to get the OAuth2 state from: a KYC start command
     46    * offering the KYC URL, or any command offering a payment target,
     47    * whose bare hash is then used as the state.
     48    */
     49   const char *state_reference;
     50 
     51   /**
     52    * Code to pass.
     53    */
     54   const char *code;
     55 
     56   /**
     57    * Logic section name to pass to `/kyc-proof/` handler.
     58    */
     59   const char *logic;
     60 
     61   /**
     62    * Expected HTTP response code.
     63    */
     64   unsigned int expected_response_code;
     65 
     66   /**
     67    * Set to the KYC REDIRECT *if* the exchange replied with
     68    * success (#MHD_HTTP_OK).
     69    */
     70   char *redirect_url;
     71 
     72   /**
     73    * Additional URL arguments (e.g. "&code=..."), kept alive
     74    * for the lifetime of the request.
     75    */
     76   char *uargs;
     77 
     78   /**
     79    * Handle to the "track transaction" pending operation.
     80    */
     81   struct TALER_EXCHANGE_GetKycProofHandle *kph;
     82 
     83   /**
     84    * Interpreter state.
     85    */
     86   struct TALER_TESTING_Interpreter *is;
     87 };
     88 
     89 
     90 /**
     91  * Handle response to the command.
     92  *
     93  * @param kcg our state
     94  * @param kpr KYC proof response details
     95  */
     96 static void
     97 proof_kyc_cb (
     98   struct KycProofGetState *kcg,
     99   const struct TALER_EXCHANGE_GetKycProofResponse *kpr)
    100 {
    101   struct TALER_TESTING_Interpreter *is = kcg->is;
    102 
    103   kcg->kph = NULL;
    104   if (kcg->expected_response_code != kpr->hr.http_status)
    105   {
    106     TALER_TESTING_unexpected_status (is,
    107                                      kpr->hr.http_status,
    108                                      kcg->expected_response_code);
    109     return;
    110   }
    111   switch (kpr->hr.http_status)
    112   {
    113   case MHD_HTTP_SEE_OTHER:
    114     kcg->redirect_url = GNUNET_strdup (kpr->details.see_other.redirect_url);
    115     break;
    116   case MHD_HTTP_FORBIDDEN:
    117     break;
    118   case MHD_HTTP_BAD_GATEWAY:
    119     break;
    120   default:
    121     GNUNET_break (0);
    122     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    123                 "Unexpected response code %u to /kyc-proof\n",
    124                 kpr->hr.http_status);
    125     break;
    126   }
    127   TALER_TESTING_interpreter_next (kcg->is);
    128 }
    129 
    130 
    131 /**
    132  * Extract the OAuth2 state from the authorization URL
    133  * the exchange returned to start a KYC process.
    134  *
    135  * @param kyc_url authorization URL to parse
    136  * @return the state, NULL if @a kyc_url has none
    137  */
    138 static char *
    139 get_state (const char *kyc_url)
    140 {
    141   const char *q;
    142 
    143   q = strchr (kyc_url,
    144               '?');
    145   while (NULL != q)
    146   {
    147     q++;
    148     if (0 == strncmp (q,
    149                       "state=",
    150                       strlen ("state=")))
    151     {
    152       q += strlen ("state=");
    153       return GNUNET_strndup (q,
    154                              strcspn (q,
    155                                       "&#"));
    156     }
    157     q = strchr (q,
    158                 '&');
    159   }
    160   return NULL;
    161 }
    162 
    163 
    164 /**
    165  * Run the command.
    166  *
    167  * @param cls closure.
    168  * @param cmd the command to execute.
    169  * @param is the interpreter state.
    170  */
    171 static void
    172 proof_kyc_run (void *cls,
    173                const struct TALER_TESTING_Command *cmd,
    174                struct TALER_TESTING_Interpreter *is)
    175 {
    176   struct KycProofGetState *kps = cls;
    177   const struct TALER_TESTING_Command *res_cmd;
    178   const char *kyc_url;
    179   char *state;
    180   const char *exchange_url;
    181 
    182   (void) cmd;
    183   kps->is = is;
    184   exchange_url = TALER_TESTING_get_exchange_url (is);
    185   if (NULL == exchange_url)
    186   {
    187     GNUNET_break (0);
    188     return;
    189   }
    190   res_cmd = TALER_TESTING_interpreter_lookup_command (
    191     kps->is,
    192     kps->state_reference);
    193   if (NULL == res_cmd)
    194   {
    195     GNUNET_break (0);
    196     TALER_TESTING_interpreter_fail (kps->is);
    197     return;
    198   }
    199   if (GNUNET_OK ==
    200       TALER_TESTING_get_trait_kyc_url (res_cmd,
    201                                        &kyc_url))
    202   {
    203     /* Use the state the exchange issued, as the provider would. */
    204     state = get_state (kyc_url);
    205     if (NULL == state)
    206     {
    207       GNUNET_break (0);
    208       TALER_TESTING_interpreter_fail (kps->is);
    209       return;
    210     }
    211   }
    212   else
    213   {
    214     const struct TALER_NormalizedPaytoHashP *h_payto;
    215 
    216     /* Only know the account, like anyone who did not see the
    217        authorization request. */
    218     if (GNUNET_OK !=
    219         TALER_TESTING_get_trait_h_normalized_payto (res_cmd,
    220                                                     &h_payto))
    221     {
    222       GNUNET_break (0);
    223       TALER_TESTING_interpreter_fail (kps->is);
    224       return;
    225     }
    226     state = GNUNET_STRINGS_data_to_string_alloc (h_payto,
    227                                                  sizeof (*h_payto));
    228   }
    229   if (NULL != kps->code)
    230     GNUNET_asprintf (&kps->uargs,
    231                      "&code=%s",
    232                      kps->code);
    233   kps->kph = TALER_EXCHANGE_get_kyc_proof_create (
    234     TALER_TESTING_interpreter_get_context (is),
    235     exchange_url,
    236     state,
    237     kps->logic);
    238   GNUNET_free (state);
    239   GNUNET_assert (NULL != kps->kph);
    240   if (NULL != kps->uargs)
    241     TALER_EXCHANGE_get_kyc_proof_set_options (
    242       kps->kph,
    243       TALER_EXCHANGE_get_kyc_proof_option_args (kps->uargs));
    244   {
    245     enum TALER_ErrorCode ec;
    246 
    247     ec = TALER_EXCHANGE_get_kyc_proof_start (kps->kph,
    248                                              &proof_kyc_cb,
    249                                              kps);
    250     if (TALER_EC_NONE != ec)
    251     {
    252       GNUNET_break (0);
    253       kps->kph = NULL;
    254       TALER_TESTING_interpreter_fail (kps->is);
    255       return;
    256     }
    257   }
    258 }
    259 
    260 
    261 /**
    262  * Cleanup the state from a "kyc proof" CMD, and possibly
    263  * cancel a operation thereof.
    264  *
    265  * @param cls closure.
    266  * @param cmd the command which is being cleaned up.
    267  */
    268 static void
    269 proof_kyc_cleanup (void *cls,
    270                    const struct TALER_TESTING_Command *cmd)
    271 {
    272   struct KycProofGetState *kps = cls;
    273 
    274   if (NULL != kps->kph)
    275   {
    276     TALER_TESTING_command_incomplete (kps->is,
    277                                       cmd->label);
    278     TALER_EXCHANGE_get_kyc_proof_cancel (kps->kph);
    279     kps->kph = NULL;
    280   }
    281   GNUNET_free (kps->redirect_url);
    282   GNUNET_free (kps->uargs);
    283   GNUNET_free (kps);
    284 }
    285 
    286 
    287 /**
    288  * Offer internal data from a "proof KYC" CMD.
    289  *
    290  * @param cls closure.
    291  * @param[out] ret result (could be anything).
    292  * @param trait name of the trait.
    293  * @param index index number of the object to offer.
    294  * @return #GNUNET_OK on success.
    295  */
    296 static enum GNUNET_GenericReturnValue
    297 proof_kyc_traits (void *cls,
    298                   const void **ret,
    299                   const char *trait,
    300                   unsigned int index)
    301 {
    302   struct KycProofGetState *kps = cls;
    303   struct TALER_TESTING_Trait traits[] = {
    304     TALER_TESTING_make_trait_web_url (kps->redirect_url),
    305     TALER_TESTING_trait_end ()
    306   };
    307 
    308   return TALER_TESTING_get_trait (traits,
    309                                   ret,
    310                                   trait,
    311                                   index);
    312 }
    313 
    314 
    315 struct TALER_TESTING_Command
    316 TALER_TESTING_cmd_proof_kyc_oauth2 (
    317   const char *label,
    318   const char *state_reference,
    319   const char *logic_section,
    320   const char *code,
    321   unsigned int expected_response_code)
    322 {
    323   struct KycProofGetState *kps;
    324 
    325   kps = GNUNET_new (struct KycProofGetState);
    326   kps->code = code;
    327   kps->logic = logic_section;
    328   kps->state_reference = state_reference;
    329   kps->expected_response_code = expected_response_code;
    330   {
    331     struct TALER_TESTING_Command cmd = {
    332       .cls = kps,
    333       .label = label,
    334       .run = &proof_kyc_run,
    335       .cleanup = &proof_kyc_cleanup,
    336       .traits = &proof_kyc_traits
    337     };
    338 
    339     return cmd;
    340   }
    341 }
    342 
    343 
    344 /* end of testing_api_cmd_kyc_proof.c */