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

Generated by: LCOV version 2.0-1