LCOV - code coverage report
Current view: top level - bank-lib - fakebank_bank_post_withdrawals_id_op.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 105 0
Test Date: 2026-01-12 22:36:41 Functions: 0.0 % 3 0

            Line data    Source code
       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_bank_post_withdrawals_id_op.c
      21              :  * @brief implement bank API POST /accounts/$ACCOUNT/withdrawals/$WID/$OP endpoint(s)
      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_withdrawals_id_op.h"
      33              : #include "fakebank_common_lookup.h"
      34              : #include "fakebank_common_lp.h"
      35              : #include "fakebank_common_make_admin_transfer.h"
      36              : 
      37              : 
      38              : /**
      39              :  * Handle POST /accounts/$ACC/withdrawals/{withdrawal_id}/confirm request.
      40              :  *
      41              :  * @param h our fakebank handle
      42              :  * @param connection the connection
      43              :  * @param account name of the account
      44              :  * @param withdrawal_id the withdrawal operation identifier
      45              :  * @param body uploaded JSON body, NULL if none
      46              :  * @return MHD result code
      47              :  */
      48              : static MHD_RESULT
      49            0 : bank_withdrawals_confirm (
      50              :   struct TALER_FAKEBANK_Handle *h,
      51              :   struct MHD_Connection *connection,
      52              :   const char *account,
      53              :   const char *withdrawal_id,
      54              :   const json_t *body)
      55              : {
      56              :   const struct Account *acc;
      57              :   struct WithdrawalOperation *wo;
      58              :   struct TALER_Amount amount;
      59            0 :   bool amount_missing = true;
      60              :   struct GNUNET_JSON_Specification spec[] = {
      61            0 :     GNUNET_JSON_spec_mark_optional (
      62              :       TALER_JSON_spec_amount ("amount",
      63            0 :                               h->currency,
      64              :                               &amount),
      65              :       &amount_missing),
      66            0 :     GNUNET_JSON_spec_end ()
      67              :   };
      68              :   enum GNUNET_GenericReturnValue ret;
      69              : 
      70            0 :   if ( (NULL != body) &&
      71              :        (GNUNET_OK !=
      72            0 :         (ret = TALER_MHD_parse_json_data (connection,
      73              :                                           body,
      74              :                                           spec))) )
      75              :   {
      76            0 :     GNUNET_break_op (0);
      77            0 :     return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
      78              :   }
      79              : 
      80            0 :   GNUNET_assert (0 ==
      81              :                  pthread_mutex_lock (&h->big_lock));
      82            0 :   acc = TALER_FAKEBANK_lookup_account_ (h,
      83              :                                         account,
      84              :                                         NULL);
      85            0 :   if (NULL == acc)
      86              :   {
      87            0 :     GNUNET_assert (0 ==
      88              :                    pthread_mutex_unlock (&h->big_lock));
      89            0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
      90              :                 "Account %s is unknown\n",
      91              :                 account);
      92            0 :     return TALER_MHD_reply_with_error (connection,
      93              :                                        MHD_HTTP_NOT_FOUND,
      94              :                                        TALER_EC_BANK_UNKNOWN_ACCOUNT,
      95              :                                        account);
      96              :   }
      97            0 :   wo = TALER_FAKEBANK_lookup_withdrawal_operation_ (h,
      98              :                                                     withdrawal_id);
      99            0 :   if ( (NULL == wo) ||
     100            0 :        (acc != wo->debit_account) )
     101              :   {
     102            0 :     GNUNET_assert (0 ==
     103              :                    pthread_mutex_unlock (&h->big_lock));
     104            0 :     return TALER_MHD_reply_with_error (connection,
     105              :                                        MHD_HTTP_NOT_FOUND,
     106              :                                        TALER_EC_BANK_TRANSACTION_NOT_FOUND,
     107              :                                        withdrawal_id);
     108              :   }
     109            0 :   if (NULL == wo->exchange_account)
     110              :   {
     111            0 :     GNUNET_assert (0 ==
     112              :                    pthread_mutex_unlock (&h->big_lock));
     113            0 :     return TALER_MHD_reply_with_error (connection,
     114              :                                        MHD_HTTP_BAD_REQUEST,
     115              :                                        TALER_EC_BANK_POST_WITHDRAWAL_OPERATION_REQUIRED,
     116              :                                        NULL);
     117              :   }
     118            0 :   if ( (NULL != wo->amount) &&
     119            0 :        (! amount_missing) &&
     120            0 :        (0 != TALER_amount_cmp (&amount,
     121            0 :                                wo->amount)) )
     122              :   {
     123            0 :     GNUNET_assert (0 ==
     124              :                    pthread_mutex_unlock (&h->big_lock));
     125            0 :     return TALER_MHD_reply_with_error (connection,
     126              :                                        MHD_HTTP_CONFLICT,
     127              :                                        TALER_EC_BANK_CONFIRM_ABORT_CONFLICT,
     128              :                                        "amount inconsistent");
     129              :   }
     130            0 :   if ( (NULL == wo->amount) &&
     131              :        (amount_missing) )
     132              :   {
     133            0 :     GNUNET_assert (0 ==
     134              :                    pthread_mutex_unlock (&h->big_lock));
     135            0 :     return TALER_MHD_reply_with_error (connection,
     136              :                                        MHD_HTTP_CONFLICT,
     137              :                                        TALER_EC_BANK_CONFIRM_ABORT_CONFLICT,
     138              :                                        "amount required");
     139              :   }
     140            0 :   if (NULL == wo->amount)
     141              :   {
     142            0 :     GNUNET_assert (! amount_missing);
     143            0 :     wo->amount = GNUNET_new (struct TALER_Amount);
     144            0 :     *wo->amount = amount;
     145              :   }
     146            0 :   if (wo->aborted)
     147              :   {
     148            0 :     GNUNET_assert (0 ==
     149              :                    pthread_mutex_unlock (&h->big_lock));
     150            0 :     return TALER_MHD_reply_with_error (connection,
     151              :                                        MHD_HTTP_CONFLICT,
     152              :                                        TALER_EC_BANK_CONFIRM_ABORT_CONFLICT,
     153              :                                        withdrawal_id);
     154              :   }
     155            0 :   GNUNET_assert (0 ==
     156              :                  pthread_mutex_unlock (&h->big_lock));
     157            0 :   if (GNUNET_OK !=
     158            0 :       TALER_FAKEBANK_make_admin_transfer_ (
     159              :         h,
     160            0 :         wo->debit_account->account_name,
     161            0 :         wo->exchange_account->account_name,
     162            0 :         wo->amount,
     163            0 :         &wo->reserve_pub,
     164              :         &wo->row_id,
     165              :         &wo->timestamp))
     166              :   {
     167            0 :     return TALER_MHD_reply_with_error (connection,
     168              :                                        MHD_HTTP_CONFLICT,
     169              :                                        TALER_EC_BANK_DUPLICATE_RESERVE_PUB_SUBJECT,
     170              :                                        NULL);
     171              :   }
     172              :   /* Re-acquiring the lock and continuing to operate on 'wo'
     173              :      is currently (!) acceptable because we NEVER free 'wo'
     174              :      until shutdown. We may want to revise this if keeping
     175              :      all withdraw operations in RAM becomes an issue... */
     176            0 :   GNUNET_assert (0 ==
     177              :                  pthread_mutex_lock (&h->big_lock));
     178            0 :   wo->confirmation_done = true;
     179            0 :   TALER_FAKEBANK_notify_withdrawal_ (h,
     180              :                                      wo);
     181            0 :   GNUNET_assert (0 ==
     182              :                  pthread_mutex_unlock (&h->big_lock));
     183            0 :   return TALER_MHD_reply_static (connection,
     184              :                                  MHD_HTTP_NO_CONTENT,
     185              :                                  NULL,
     186              :                                  NULL,
     187              :                                  0);
     188              : }
     189              : 
     190              : 
     191              : /**
     192              :  * Handle POST /accounts/$ACC/withdrawals/{withdrawal_id}/abort request.
     193              :  *
     194              :  * @param h our fakebank handle
     195              :  * @param connection the connection
     196              :  * @param account name of the account
     197              :  * @param withdrawal_id the withdrawal operation identifier
     198              :  * @param body uploaded JSON body, NULL if none
     199              :  * @return MHD result code
     200              :  */
     201              : static MHD_RESULT
     202            0 : bank_withdrawals_abort (
     203              :   struct TALER_FAKEBANK_Handle *h,
     204              :   struct MHD_Connection *connection,
     205              :   const char *account,
     206              :   const char *withdrawal_id,
     207              :   const json_t *body)
     208              : {
     209              :   struct WithdrawalOperation *wo;
     210              :   const struct Account *acc;
     211              : 
     212            0 :   GNUNET_assert (0 ==
     213              :                  pthread_mutex_lock (&h->big_lock));
     214            0 :   acc = TALER_FAKEBANK_lookup_account_ (h,
     215              :                                         account,
     216              :                                         NULL);
     217            0 :   if (NULL == acc)
     218              :   {
     219            0 :     GNUNET_assert (0 ==
     220              :                    pthread_mutex_unlock (&h->big_lock));
     221            0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     222              :                 "Account %s is unknown\n",
     223              :                 account);
     224            0 :     return TALER_MHD_reply_with_error (connection,
     225              :                                        MHD_HTTP_NOT_FOUND,
     226              :                                        TALER_EC_BANK_UNKNOWN_ACCOUNT,
     227              :                                        account);
     228              :   }
     229            0 :   wo = TALER_FAKEBANK_lookup_withdrawal_operation_ (h,
     230              :                                                     withdrawal_id);
     231            0 :   if ( (NULL == wo) ||
     232            0 :        (acc != wo->debit_account) )
     233              :   {
     234            0 :     GNUNET_assert (0 ==
     235              :                    pthread_mutex_unlock (&h->big_lock));
     236            0 :     return TALER_MHD_reply_with_error (connection,
     237              :                                        MHD_HTTP_NOT_FOUND,
     238              :                                        TALER_EC_BANK_TRANSACTION_NOT_FOUND,
     239              :                                        withdrawal_id);
     240              :   }
     241            0 :   if (wo->confirmation_done)
     242              :   {
     243            0 :     GNUNET_assert (0 ==
     244              :                    pthread_mutex_unlock (&h->big_lock));
     245            0 :     return TALER_MHD_reply_with_error (connection,
     246              :                                        MHD_HTTP_CONFLICT,
     247              :                                        TALER_EC_BANK_ABORT_CONFIRM_CONFLICT,
     248              :                                        withdrawal_id);
     249              :   }
     250            0 :   wo->aborted = true;
     251            0 :   TALER_FAKEBANK_notify_withdrawal_ (h,
     252              :                                      wo);
     253            0 :   GNUNET_assert (0 ==
     254              :                  pthread_mutex_unlock (&h->big_lock));
     255            0 :   return TALER_MHD_reply_static (connection,
     256              :                                  MHD_HTTP_NO_CONTENT,
     257              :                                  NULL,
     258              :                                  NULL,
     259              :                                  0);
     260              : }
     261              : 
     262              : 
     263              : MHD_RESULT
     264            0 : TALER_FAKEBANK_bank_withdrawals_id_op_ (
     265              :   struct TALER_FAKEBANK_Handle *h,
     266              :   struct MHD_Connection *connection,
     267              :   const char *account,
     268              :   const char *withdrawal_id,
     269              :   const char *op,
     270              :   const char *upload_data,
     271              :   size_t *upload_data_size,
     272              :   void **con_cls)
     273              : {
     274            0 :   struct ConnectionContext *cc = *con_cls;
     275            0 :   json_t *json = NULL;
     276              : 
     277            0 :   if (NULL == cc)
     278              :   {
     279            0 :     cc = GNUNET_new (struct ConnectionContext);
     280            0 :     cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup;
     281            0 :     *con_cls = cc;
     282              :   }
     283            0 :   if (0 != *upload_data_size)
     284              :   {
     285              :     enum GNUNET_MHD_PostResult pr;
     286              : 
     287            0 :     pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX,
     288              :                                  connection,
     289              :                                  &cc->ctx,
     290              :                                  upload_data,
     291              :                                  upload_data_size,
     292              :                                  &json);
     293            0 :     switch (pr)
     294              :     {
     295            0 :     case GNUNET_MHD_PR_OUT_OF_MEMORY:
     296            0 :       GNUNET_break (0);
     297            0 :       return MHD_NO;
     298            0 :     case GNUNET_MHD_PR_CONTINUE:
     299            0 :       return MHD_YES;
     300            0 :     case GNUNET_MHD_PR_REQUEST_TOO_LARGE:
     301            0 :       GNUNET_break (0);
     302            0 :       return MHD_NO;
     303            0 :     case GNUNET_MHD_PR_JSON_INVALID:
     304            0 :       GNUNET_break (0);
     305            0 :       return MHD_NO;
     306            0 :     case GNUNET_MHD_PR_SUCCESS:
     307            0 :       break;
     308              :     }
     309              :   }
     310              : 
     311            0 :   if (0 == strcmp (op,
     312              :                    "/confirm"))
     313              :   {
     314              :     MHD_RESULT res;
     315              : 
     316            0 :     res = bank_withdrawals_confirm (h,
     317              :                                     connection,
     318              :                                     account,
     319              :                                     withdrawal_id,
     320              :                                     json);
     321            0 :     json_decref (json);
     322            0 :     return res;
     323              :   }
     324            0 :   if (0 == strcmp (op,
     325              :                    "/abort"))
     326              :   {
     327              :     MHD_RESULT res;
     328              : 
     329            0 :     res = bank_withdrawals_abort (h,
     330              :                                   connection,
     331              :                                   account,
     332              :                                   withdrawal_id,
     333              :                                   json);
     334            0 :     json_decref (json);
     335            0 :     return res;
     336              :   }
     337            0 :   GNUNET_break_op (0);
     338            0 :   json_decref (json);
     339            0 :   return TALER_MHD_reply_with_error (connection,
     340              :                                      MHD_HTTP_NOT_FOUND,
     341              :                                      TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
     342              :                                      op);
     343              : }
        

Generated by: LCOV version 2.0-1