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