LCOV - code coverage report
Current view: top level - bank-lib - fakebank_bank_post_withdrawals_id_op.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 105 0.0 %
Date: 2025-06-22 12:09:43 Functions: 0 3 0.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 1.16