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 }