fakebank_bank_post_accounts_withdrawals.c (6333B)
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 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 (GNUNET_CRYPTO_QUALITY_NONCE, 83 &wo->wopid, 84 sizeof (wo->wopid)); 85 if (GNUNET_OK == 86 GNUNET_CONTAINER_multishortmap_put (h->wops, 87 &wo->wopid, 88 wo, 89 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) 90 91 92 93 break; 94 } 95 { 96 char *wopids; 97 char *uri; 98 MHD_RESULT res; 99 100 wopids = GNUNET_STRINGS_data_to_string_alloc (&wo->wopid, 101 sizeof (wo->wopid)); 102 GNUNET_asprintf (&uri, 103 "taler+http://withdraw/%s:%u/taler-integration/%s", 104 h->hostname, 105 (unsigned int) h->port, 106 wopids); 107 GNUNET_free (wopids); 108 res = TALER_MHD_REPLY_JSON_PACK ( 109 connection, 110 MHD_HTTP_OK, 111 GNUNET_JSON_pack_string ("taler_withdraw_uri", 112 uri), 113 GNUNET_JSON_pack_data_auto ("withdrawal_id", 114 &wo->wopid)); 115 GNUNET_assert (0 == 116 pthread_mutex_unlock (&h->big_lock)); 117 GNUNET_free (uri); 118 return res; 119 } 120 } 121 122 123 /** 124 * Handle POST /accounts/$account_name/withdrawals request. 125 * 126 * @param h our fakebank handle 127 * @param connection the connection 128 * @param account_name name of the account 129 * @param upload_data request data 130 * @param upload_data_size size of @a upload_data in bytes 131 * @param con_cls closure for request 132 * @return MHD result code 133 */ 134 MHD_RESULT 135 TALER_FAKEBANK_bank_post_account_withdrawals_ ( 136 struct TALER_FAKEBANK_Handle *h, 137 struct MHD_Connection *connection, 138 const char *account_name, 139 const void *upload_data, 140 size_t *upload_data_size, 141 void **con_cls) 142 { 143 struct ConnectionContext *cc = *con_cls; 144 enum GNUNET_MHD_PostResult pr; 145 json_t *json; 146 MHD_RESULT res; 147 148 if (NULL == cc) 149 { 150 cc = GNUNET_new (struct ConnectionContext); 151 cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup; 152 *con_cls = cc; 153 } 154 pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX, 155 connection, 156 &cc->ctx, 157 upload_data, 158 upload_data_size, 159 &json); 160 switch (pr) 161 { 162 case GNUNET_MHD_PR_OUT_OF_MEMORY: 163 GNUNET_break (0); 164 return MHD_NO; 165 case GNUNET_MHD_PR_CONTINUE: 166 return MHD_YES; 167 case GNUNET_MHD_PR_REQUEST_TOO_LARGE: 168 GNUNET_break (0); 169 return MHD_NO; 170 case GNUNET_MHD_PR_JSON_INVALID: 171 GNUNET_break (0); 172 return MHD_NO; 173 case GNUNET_MHD_PR_SUCCESS: 174 break; 175 } 176 177 { 178 struct TALER_Amount amount; 179 bool amount_missing; 180 struct TALER_Amount *amount_ptr; 181 enum GNUNET_GenericReturnValue ret; 182 struct GNUNET_JSON_Specification spec[] = { 183 GNUNET_JSON_spec_mark_optional ( 184 TALER_JSON_spec_amount ("amount", 185 h->currency, 186 &amount), 187 &amount_missing), 188 GNUNET_JSON_spec_end () 189 }; 190 191 if (GNUNET_OK != 192 (ret = TALER_MHD_parse_json_data (connection, 193 json, 194 spec))) 195 { 196 GNUNET_break_op (0); 197 json_decref (json); 198 return (GNUNET_NO == ret) ? MHD_YES : MHD_NO; 199 } 200 201 amount_ptr = amount_missing ? NULL : &amount; 202 203 res = do_post_account_withdrawals (h, 204 connection, 205 account_name, 206 amount_ptr); 207 } 208 json_decref (json); 209 return res; 210 }