Line data Source code
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 0 : 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 0 : GNUNET_assert (0 ==
55 : pthread_mutex_lock (&h->big_lock));
56 0 : acc = TALER_FAKEBANK_lookup_account_ (h,
57 : account_name,
58 : NULL);
59 0 : if (NULL == acc)
60 : {
61 0 : GNUNET_assert (0 ==
62 : pthread_mutex_unlock (&h->big_lock));
63 0 : return TALER_MHD_reply_with_error (connection,
64 : MHD_HTTP_NOT_FOUND,
65 : TALER_EC_BANK_UNKNOWN_ACCOUNT,
66 : account_name);
67 : }
68 0 : wo = GNUNET_new (struct WithdrawalOperation);
69 0 : wo->debit_account = acc;
70 0 : if (NULL != amount)
71 : {
72 0 : wo->amount = GNUNET_new (struct TALER_Amount);
73 0 : *wo->amount = *amount;
74 : }
75 0 : if (NULL == h->wops)
76 : {
77 0 : h->wops = GNUNET_CONTAINER_multishortmap_create (32,
78 : GNUNET_YES);
79 : }
80 : while (1)
81 : {
82 0 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
83 0 : &wo->wopid,
84 : sizeof (wo->wopid));
85 0 : if (GNUNET_OK ==
86 0 : GNUNET_CONTAINER_multishortmap_put (h->wops,
87 0 : &wo->wopid,
88 : wo,
89 : GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
90 :
91 :
92 :
93 0 : break;
94 : }
95 : {
96 : char *wopids;
97 : char *uri;
98 : MHD_RESULT res;
99 :
100 0 : wopids = GNUNET_STRINGS_data_to_string_alloc (&wo->wopid,
101 : sizeof (wo->wopid));
102 0 : GNUNET_asprintf (&uri,
103 : "taler+http://withdraw/%s:%u/taler-integration/%s",
104 : h->hostname,
105 0 : (unsigned int) h->port,
106 : wopids);
107 0 : GNUNET_free (wopids);
108 0 : 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 0 : GNUNET_assert (0 ==
116 : pthread_mutex_unlock (&h->big_lock));
117 0 : GNUNET_free (uri);
118 0 : 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 0 : 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 0 : struct ConnectionContext *cc = *con_cls;
144 : enum GNUNET_MHD_PostResult pr;
145 : json_t *json;
146 : MHD_RESULT res;
147 :
148 0 : if (NULL == cc)
149 : {
150 0 : cc = GNUNET_new (struct ConnectionContext);
151 0 : cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup;
152 0 : *con_cls = cc;
153 : }
154 0 : pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX,
155 : connection,
156 : &cc->ctx,
157 : upload_data,
158 : upload_data_size,
159 : &json);
160 0 : switch (pr)
161 : {
162 0 : case GNUNET_MHD_PR_OUT_OF_MEMORY:
163 0 : GNUNET_break (0);
164 0 : return MHD_NO;
165 0 : case GNUNET_MHD_PR_CONTINUE:
166 0 : return MHD_YES;
167 0 : case GNUNET_MHD_PR_REQUEST_TOO_LARGE:
168 0 : GNUNET_break (0);
169 0 : return MHD_NO;
170 0 : case GNUNET_MHD_PR_JSON_INVALID:
171 0 : GNUNET_break (0);
172 0 : return MHD_NO;
173 0 : case GNUNET_MHD_PR_SUCCESS:
174 0 : 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 0 : GNUNET_JSON_spec_mark_optional (
184 : TALER_JSON_spec_amount ("amount",
185 0 : h->currency,
186 : &amount),
187 : &amount_missing),
188 0 : GNUNET_JSON_spec_end ()
189 : };
190 :
191 0 : if (GNUNET_OK !=
192 0 : (ret = TALER_MHD_parse_json_data (connection,
193 : json,
194 : spec)))
195 : {
196 0 : GNUNET_break_op (0);
197 0 : json_decref (json);
198 0 : return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
199 : }
200 :
201 0 : amount_ptr = amount_missing ? NULL : &amount;
202 :
203 0 : res = do_post_account_withdrawals (h,
204 : connection,
205 : account_name,
206 : amount_ptr);
207 : }
208 0 : json_decref (json);
209 0 : return res;
210 : }
|