exchange

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

fakebank_tbi_post_withdrawal_operation.c (9822B)


      1 /*
      2   This file is part of TALER
      3   (C) 2016-2024 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU General Public License
      7   as published by the Free Software Foundation; either version 3,
      8   or (at your option) any later version.
      9 
     10   TALER is distributed in the hope that it will be useful,
     11   but 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,
     17   see <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file bank-lib/fakebank_tbi_post_withdrawal_operation.c
     21  * @brief library that fakes being a Taler bank for testcases
     22  * @author Christian Grothoff <christian@grothoff.org>
     23  */
     24 #include "taler/platform.h"
     25 #include <pthread.h>
     26 #include "taler/taler_fakebank_lib.h"
     27 #include "taler/taler_bank_service.h"
     28 #include "taler/taler_mhd_lib.h"
     29 #include <gnunet/gnunet_mhd_compat.h>
     30 #include <gnunet/gnunet_mhd_lib.h>
     31 #include "fakebank.h"
     32 #include "fakebank_common_lookup.h"
     33 #include "fakebank_tbi_post_withdrawal_operation.h"
     34 
     35 
     36 /**
     37  * Execute POST /withdrawal-operation/ request.
     38  *
     39  * @param h our handle
     40  * @param connection the connection
     41  * @param wopid the withdrawal operation identifier
     42  * @param reserve_pub public key of the reserve
     43  * @param exchange_payto_uri payto://-URI of the exchange
     44  * @param amount chosen by the client, or NULL to use the
     45  *        pre-determined amount
     46  * @return MHD result code
     47  */
     48 static MHD_RESULT
     49 do_post_withdrawal (
     50   struct TALER_FAKEBANK_Handle *h,
     51   struct MHD_Connection *connection,
     52   const char *wopid,
     53   const struct TALER_ReservePublicKeyP *reserve_pub,
     54   const struct TALER_FullPayto exchange_payto_uri,
     55   const struct TALER_Amount *amount)
     56 {
     57   struct WithdrawalOperation *wo;
     58   char *credit_name;
     59   struct Account *credit_account;
     60   const char *status_string;
     61 
     62   GNUNET_assert (0 ==
     63                  pthread_mutex_lock (&h->big_lock));
     64   wo = TALER_FAKEBANK_lookup_withdrawal_operation_ (h,
     65                                                     wopid);
     66   if (NULL == wo)
     67   {
     68     GNUNET_assert (0 ==
     69                    pthread_mutex_unlock (&h->big_lock));
     70     return TALER_MHD_reply_with_error (connection,
     71                                        MHD_HTTP_NOT_FOUND,
     72                                        TALER_EC_BANK_TRANSACTION_NOT_FOUND,
     73                                        wopid);
     74   }
     75   if (wo->aborted)
     76   {
     77     GNUNET_assert (0 ==
     78                    pthread_mutex_unlock (&h->big_lock));
     79     return TALER_MHD_reply_with_error (connection,
     80                                        MHD_HTTP_CONFLICT,
     81                                        TALER_EC_BANK_UPDATE_ABORT_CONFLICT,
     82                                        wopid);
     83   }
     84   if ( (wo->selection_done) &&
     85        (0 != GNUNET_memcmp (&wo->reserve_pub,
     86                             reserve_pub)) )
     87   {
     88     GNUNET_assert (0 ==
     89                    pthread_mutex_unlock (&h->big_lock));
     90     return TALER_MHD_reply_with_error (connection,
     91                                        MHD_HTTP_CONFLICT,
     92                                        TALER_EC_BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT,
     93                                        "reserve public key changed");
     94   }
     95   {
     96     /* check if reserve_pub is already in use */
     97     const struct GNUNET_PeerIdentity *pid;
     98 
     99     pid = (const struct GNUNET_PeerIdentity *) &wo->reserve_pub;
    100     if (GNUNET_CONTAINER_multipeermap_contains (h->rpubs,
    101                                                 pid))
    102     {
    103       GNUNET_assert (0 ==
    104                      pthread_mutex_unlock (&h->big_lock));
    105       return TALER_MHD_reply_with_error (connection,
    106                                          MHD_HTTP_CONFLICT,
    107                                          TALER_EC_BANK_DUPLICATE_RESERVE_PUB_SUBJECT,
    108                                          NULL);
    109     }
    110   }
    111   credit_name = TALER_xtalerbank_account_from_payto (exchange_payto_uri);
    112   if (NULL == credit_name)
    113   {
    114     GNUNET_break_op (0);
    115     GNUNET_assert (0 ==
    116                    pthread_mutex_unlock (&h->big_lock));
    117     return TALER_MHD_reply_with_error (connection,
    118                                        MHD_HTTP_BAD_REQUEST,
    119                                        TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
    120                                        NULL);
    121   }
    122   credit_account = TALER_FAKEBANK_lookup_account_ (h,
    123                                                    credit_name,
    124                                                    NULL);
    125   if (NULL == credit_account)
    126   {
    127     MHD_RESULT res;
    128 
    129     GNUNET_break_op (0);
    130     GNUNET_assert (0 ==
    131                    pthread_mutex_unlock (&h->big_lock));
    132     res = TALER_MHD_reply_with_error (connection,
    133                                       MHD_HTTP_NOT_FOUND,
    134                                       TALER_EC_BANK_UNKNOWN_ACCOUNT,
    135                                       credit_name);
    136     GNUNET_free (credit_name);
    137     return res;
    138   }
    139   GNUNET_free (credit_name);
    140   if ( (NULL != wo->exchange_account) &&
    141        (credit_account != wo->exchange_account) )
    142   {
    143     GNUNET_assert (0 ==
    144                    pthread_mutex_unlock (&h->big_lock));
    145     return TALER_MHD_reply_with_error (connection,
    146                                        MHD_HTTP_CONFLICT,
    147                                        TALER_EC_BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT,
    148                                        "exchange account changed");
    149   }
    150   if ( (NULL != wo->amount) && (NULL != amount) && (0 != TALER_amount_cmp (wo->
    151                                                                            amount,
    152                                                                            amount)) )
    153   {
    154     GNUNET_assert (0 ==
    155                    pthread_mutex_unlock (&h->big_lock));
    156     return TALER_MHD_reply_with_error (connection,
    157                                        MHD_HTTP_CONFLICT,
    158                                        TALER_EC_BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT,
    159                                        "amount changed");
    160   }
    161   if (NULL == wo->amount)
    162   {
    163     if (NULL == amount)
    164     {
    165       GNUNET_assert (0 ==
    166                      pthread_mutex_unlock (&h->big_lock));
    167       return TALER_MHD_reply_with_error (connection,
    168                                          MHD_HTTP_BAD_REQUEST,
    169                                          TALER_EC_BANK_POST_WITHDRAWAL_OPERATION_REQUIRED,
    170                                          "amount missing");
    171     }
    172     else
    173     {
    174       wo->amount = GNUNET_new (struct TALER_Amount);
    175       *wo->amount = *amount;
    176     }
    177   }
    178   GNUNET_assert (NULL != wo->amount);
    179   wo->exchange_account = credit_account;
    180   wo->reserve_pub = *reserve_pub;
    181   wo->selection_done = true;
    182   GNUNET_assert (0 ==
    183                  pthread_mutex_unlock (&h->big_lock));
    184   if (wo->aborted)
    185     status_string = "aborted";
    186   else if (wo->confirmation_done)
    187     status_string = "confirmed";
    188   else
    189     status_string = "selected";
    190   return TALER_MHD_REPLY_JSON_PACK (
    191     connection,
    192     MHD_HTTP_OK,
    193     // FIXME: Deprecated field, should be deleted in the future.
    194     GNUNET_JSON_pack_bool ("transfer_done",
    195                            wo->confirmation_done),
    196     GNUNET_JSON_pack_string ("status",
    197                              status_string));
    198 }
    199 
    200 
    201 MHD_RESULT
    202 TALER_FAKEBANK_tbi_post_withdrawal (
    203   struct TALER_FAKEBANK_Handle *h,
    204   struct MHD_Connection *connection,
    205   const char *wopid,
    206   const void *upload_data,
    207   size_t *upload_data_size,
    208   void **con_cls)
    209 {
    210   struct ConnectionContext *cc = *con_cls;
    211   enum GNUNET_MHD_PostResult pr;
    212   json_t *json;
    213   MHD_RESULT res;
    214 
    215   if (NULL == cc)
    216   {
    217     cc = GNUNET_new (struct ConnectionContext);
    218     cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup;
    219     *con_cls = cc;
    220   }
    221   pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX,
    222                                connection,
    223                                &cc->ctx,
    224                                upload_data,
    225                                upload_data_size,
    226                                &json);
    227   switch (pr)
    228   {
    229   case GNUNET_MHD_PR_OUT_OF_MEMORY:
    230     GNUNET_break (0);
    231     return MHD_NO;
    232   case GNUNET_MHD_PR_CONTINUE:
    233     return MHD_YES;
    234   case GNUNET_MHD_PR_REQUEST_TOO_LARGE:
    235     GNUNET_break (0);
    236     return MHD_NO;
    237   case GNUNET_MHD_PR_JSON_INVALID:
    238     GNUNET_break (0);
    239     return MHD_NO;
    240   case GNUNET_MHD_PR_SUCCESS:
    241     break;
    242   }
    243 
    244   {
    245     struct TALER_ReservePublicKeyP reserve_pub;
    246     struct TALER_FullPayto exchange_payto_url;
    247     enum GNUNET_GenericReturnValue ret;
    248     struct TALER_Amount amount;
    249     bool amount_missing;
    250     struct TALER_Amount *amount_ptr;
    251     struct GNUNET_JSON_Specification spec[] = {
    252       GNUNET_JSON_spec_fixed_auto ("reserve_pub",
    253                                    &reserve_pub),
    254       TALER_JSON_spec_full_payto_uri ("selected_exchange",
    255                                       &exchange_payto_url),
    256       GNUNET_JSON_spec_mark_optional (
    257         TALER_JSON_spec_amount ("amount",
    258                                 h->currency,
    259                                 &amount),
    260         &amount_missing),
    261       GNUNET_JSON_spec_end ()
    262     };
    263 
    264     if (GNUNET_OK !=
    265         (ret = TALER_MHD_parse_json_data (connection,
    266                                           json,
    267                                           spec)))
    268     {
    269       GNUNET_break_op (0);
    270       json_decref (json);
    271       return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
    272     }
    273 
    274     amount_ptr = amount_missing ? NULL : &amount;
    275 
    276     res = do_post_withdrawal (h,
    277                               connection,
    278                               wopid,
    279                               &reserve_pub,
    280                               exchange_payto_url,
    281                               amount_ptr);
    282   }
    283   json_decref (json);
    284   return res;
    285 }