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 enum 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 (&wo->wopid,
83 : sizeof (wo->wopid));
84 0 : if (GNUNET_OK ==
85 0 : GNUNET_CONTAINER_multishortmap_put (h->wops,
86 0 : &wo->wopid,
87 : wo,
88 : GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
89 :
90 :
91 :
92 0 : break;
93 : }
94 : {
95 : char *wopids;
96 : char *uri;
97 : enum MHD_Result res;
98 :
99 0 : wopids = GNUNET_STRINGS_data_to_string_alloc (&wo->wopid,
100 : sizeof (wo->wopid));
101 0 : GNUNET_asprintf (&uri,
102 : "taler+http://withdraw/%s:%u/taler-integration/%s",
103 : h->hostname,
104 0 : (unsigned int) h->port,
105 : wopids);
106 0 : GNUNET_free (wopids);
107 0 : 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 0 : GNUNET_assert (0 ==
115 : pthread_mutex_unlock (&h->big_lock));
116 0 : GNUNET_free (uri);
117 0 : 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 0 : 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 0 : struct ConnectionContext *cc = *con_cls;
143 : enum GNUNET_MHD_PostResult pr;
144 : json_t *json;
145 : enum MHD_Result res;
146 :
147 0 : if (NULL == cc)
148 : {
149 0 : cc = GNUNET_new (struct ConnectionContext);
150 0 : cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup;
151 0 : *con_cls = cc;
152 : }
153 0 : pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX,
154 : connection,
155 : &cc->ctx,
156 : upload_data,
157 : upload_data_size,
158 : &json);
159 0 : switch (pr)
160 : {
161 0 : case GNUNET_MHD_PR_OUT_OF_MEMORY:
162 0 : GNUNET_break (0);
163 0 : return MHD_NO;
164 0 : case GNUNET_MHD_PR_CONTINUE:
165 0 : return MHD_YES;
166 0 : case GNUNET_MHD_PR_REQUEST_TOO_LARGE:
167 0 : GNUNET_break (0);
168 0 : return MHD_NO;
169 0 : case GNUNET_MHD_PR_JSON_INVALID:
170 0 : GNUNET_break (0);
171 0 : return MHD_NO;
172 0 : case GNUNET_MHD_PR_SUCCESS:
173 0 : 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 0 : GNUNET_JSON_spec_mark_optional (
183 : TALER_JSON_spec_amount ("amount",
184 0 : h->currency,
185 : &amount),
186 : &amount_missing),
187 0 : GNUNET_JSON_spec_end ()
188 : };
189 :
190 0 : if (GNUNET_OK !=
191 0 : (ret = TALER_MHD_parse_json_data (connection,
192 : json,
193 : spec)))
194 : {
195 0 : GNUNET_break_op (0);
196 0 : json_decref (json);
197 0 : return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
198 : }
199 :
200 0 : amount_ptr = amount_missing ? NULL : &amount;
201 :
202 0 : res = do_post_account_withdrawals (h,
203 : connection,
204 : account_name,
205 : amount_ptr);
206 : }
207 0 : json_decref (json);
208 0 : return res;
209 : }
|