exchange

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

fakebank_bank_post_accounts_withdrawals.c (6361B)


      1 /*
      2   This file is part of TALER
      3   (C) 2016-2023 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_bank_post_accounts_withdrawals.c
     21  * @brief implementation of the bank API's POST /accounts/AID/withdrawals endpoint
     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_bank_post_accounts_withdrawals.h"
     33 #include "fakebank_common_lookup.h"
     34 
     35 
     36 /**
     37  * Execute POST /accounts/$account_name/withdrawals request.
     38  *
     39  * @param h our fakebank handle
     40  * @param connection the connection
     41  * @param account_name name of the account
     42  * @param amount amount to withdraw
     43  * @return MHD result code
     44  */
     45 static MHD_RESULT
     46 do_post_account_withdrawals (
     47   struct TALER_FAKEBANK_Handle *h,
     48   struct MHD_Connection *connection,
     49   const char *account_name,
     50   const struct TALER_Amount *amount)
     51 {
     52   struct Account *acc;
     53   struct WithdrawalOperation *wo;
     54 
     55   GNUNET_assert (0 ==
     56                  pthread_mutex_lock (&h->big_lock));
     57   acc = TALER_FAKEBANK_lookup_account_ (h,
     58                                         account_name,
     59                                         NULL);
     60   if (NULL == acc)
     61   {
     62     GNUNET_assert (0 ==
     63                    pthread_mutex_unlock (&h->big_lock));
     64     return TALER_MHD_reply_with_error (connection,
     65                                        MHD_HTTP_NOT_FOUND,
     66                                        TALER_EC_BANK_UNKNOWN_ACCOUNT,
     67                                        account_name);
     68   }
     69   wo = GNUNET_new (struct WithdrawalOperation);
     70   wo->debit_account = acc;
     71   if (NULL != amount)
     72   {
     73     wo->amount = GNUNET_new (struct TALER_Amount);
     74     *wo->amount = *amount;
     75   }
     76   if (NULL == h->wops)
     77   {
     78     h->wops = GNUNET_CONTAINER_multishortmap_create (32,
     79                                                      GNUNET_YES);
     80   }
     81   while (1)
     82   {
     83     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
     84                                 &wo->wopid,
     85                                 sizeof (wo->wopid));
     86     if (GNUNET_OK ==
     87         GNUNET_CONTAINER_multishortmap_put (h->wops,
     88                                             &wo->wopid,
     89                                             wo,
     90                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
     91 
     92 
     93 
     94       break;
     95   }
     96   {
     97     char *wopids;
     98     char *uri;
     99     MHD_RESULT res;
    100 
    101     wopids = GNUNET_STRINGS_data_to_string_alloc (&wo->wopid,
    102                                                   sizeof (wo->wopid));
    103     GNUNET_asprintf (&uri,
    104                      "taler+http://withdraw/%s:%u/taler-integration/%s",
    105                      h->hostname,
    106                      (unsigned int) h->port,
    107                      wopids);
    108     GNUNET_free (wopids);
    109     res = TALER_MHD_REPLY_JSON_PACK (
    110       connection,
    111       MHD_HTTP_OK,
    112       GNUNET_JSON_pack_string ("taler_withdraw_uri",
    113                                uri),
    114       GNUNET_JSON_pack_data_auto ("withdrawal_id",
    115                                   &wo->wopid));
    116     GNUNET_assert (0 ==
    117                    pthread_mutex_unlock (&h->big_lock));
    118     GNUNET_free (uri);
    119     return res;
    120   }
    121 }
    122 
    123 
    124 /**
    125  * Handle POST /accounts/$account_name/withdrawals request.
    126  *
    127  * @param h our fakebank handle
    128  * @param connection the connection
    129  * @param account_name name of the account
    130  * @param upload_data request data
    131  * @param upload_data_size size of @a upload_data in bytes
    132  * @param con_cls closure for request
    133  * @return MHD result code
    134  */
    135 MHD_RESULT
    136 TALER_FAKEBANK_bank_post_account_withdrawals_ (
    137   struct TALER_FAKEBANK_Handle *h,
    138   struct MHD_Connection *connection,
    139   const char *account_name,
    140   const void *upload_data,
    141   size_t *upload_data_size,
    142   void **con_cls)
    143 {
    144   struct ConnectionContext *cc = *con_cls;
    145   enum GNUNET_MHD_PostResult pr;
    146   json_t *json;
    147   MHD_RESULT res;
    148 
    149   if (NULL == cc)
    150   {
    151     cc = GNUNET_new (struct ConnectionContext);
    152     cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup;
    153     *con_cls = cc;
    154   }
    155   pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX,
    156                                connection,
    157                                &cc->ctx,
    158                                upload_data,
    159                                upload_data_size,
    160                                &json);
    161   switch (pr)
    162   {
    163   case GNUNET_MHD_PR_OUT_OF_MEMORY:
    164     GNUNET_break (0);
    165     return MHD_NO;
    166   case GNUNET_MHD_PR_CONTINUE:
    167     return MHD_YES;
    168   case GNUNET_MHD_PR_REQUEST_TOO_LARGE:
    169     GNUNET_break (0);
    170     return MHD_NO;
    171   case GNUNET_MHD_PR_JSON_INVALID:
    172     GNUNET_break (0);
    173     return MHD_NO;
    174   case GNUNET_MHD_PR_SUCCESS:
    175     break;
    176   }
    177 
    178   {
    179     struct TALER_Amount amount;
    180     bool amount_missing;
    181     struct TALER_Amount *amount_ptr;
    182     enum GNUNET_GenericReturnValue ret;
    183     struct GNUNET_JSON_Specification spec[] = {
    184       GNUNET_JSON_spec_mark_optional (
    185         TALER_JSON_spec_amount ("amount",
    186                                 h->currency,
    187                                 &amount),
    188         &amount_missing),
    189       GNUNET_JSON_spec_end ()
    190     };
    191 
    192     if (GNUNET_OK !=
    193         (ret = TALER_MHD_parse_json_data (connection,
    194                                           json,
    195                                           spec)))
    196     {
    197       GNUNET_break_op (0);
    198       json_decref (json);
    199       return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
    200     }
    201 
    202     amount_ptr = amount_missing ? NULL : &amount;
    203 
    204     res = do_post_account_withdrawals (h,
    205                                        connection,
    206                                        account_name,
    207                                        amount_ptr);
    208   }
    209   json_decref (json);
    210   return res;
    211 }