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