Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2022, 2023 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file backenddb/pg_lookup_instances.c
18 : * @brief Implementation of the lookup_instances function for Postgres
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include <taler/taler_error_codes.h>
23 : #include <taler/taler_pq_lib.h>
24 : #include "pg_lookup_instances.h"
25 : #include "pg_helper.h"
26 :
27 :
28 : /**
29 : * Context for lookup_instances().
30 : */
31 : struct LookupInstancesContext
32 : {
33 : /**
34 : * Function to call with the results.
35 : */
36 : TALER_MERCHANTDB_InstanceCallback cb;
37 :
38 : /**
39 : * Closure for @e cb.
40 : */
41 : void *cb_cls;
42 :
43 : /**
44 : * Database context.
45 : */
46 : struct PostgresClosure *pg;
47 :
48 : /**
49 : * Set to the return value on errors.
50 : */
51 : enum GNUNET_DB_QueryStatus qs;
52 :
53 : };
54 :
55 :
56 : /**
57 : * Function to be called with the results of a SELECT statement
58 : * that has returned @a num_results results about instances.
59 : *
60 : * @param cls of type `struct FindInstancesContext *`
61 : * @param result the postgres result
62 : * @param num_results the number of results in @a result
63 : */
64 : static void
65 94 : lookup_instances_cb (void *cls,
66 : PGresult *result,
67 : unsigned int num_results)
68 : {
69 94 : struct LookupInstancesContext *lic = cls;
70 :
71 162 : for (unsigned int i = 0; i < num_results; i++)
72 : {
73 : struct TALER_MERCHANTDB_InstanceSettings is;
74 : struct TALER_MERCHANTDB_InstanceAuthSettings ias;
75 : uint64_t instance_serial;
76 : struct TALER_MerchantPublicKeyP merchant_pub;
77 : struct TALER_MerchantPrivateKeyP merchant_priv;
78 : bool no_auth;
79 : bool no_salt;
80 : bool no_priv;
81 68 : struct GNUNET_PQ_ResultSpec rs[] = {
82 68 : GNUNET_PQ_result_spec_uint64 ("merchant_serial",
83 : &instance_serial),
84 68 : GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
85 : &merchant_pub),
86 68 : GNUNET_PQ_result_spec_allow_null (
87 : GNUNET_PQ_result_spec_auto_from_type ("auth_hash",
88 : &ias.auth_hash),
89 : &no_auth),
90 68 : GNUNET_PQ_result_spec_allow_null (
91 : GNUNET_PQ_result_spec_auto_from_type ("auth_salt",
92 : &ias.auth_salt),
93 : &no_salt),
94 68 : GNUNET_PQ_result_spec_allow_null (
95 : GNUNET_PQ_result_spec_auto_from_type ("merchant_priv",
96 : &merchant_priv),
97 : &no_priv),
98 68 : GNUNET_PQ_result_spec_string ("merchant_id",
99 : &is.id),
100 68 : GNUNET_PQ_result_spec_string ("merchant_name",
101 : &is.name),
102 68 : TALER_PQ_result_spec_json ("address",
103 : &is.address),
104 68 : TALER_PQ_result_spec_json ("jurisdiction",
105 : &is.jurisdiction),
106 68 : GNUNET_PQ_result_spec_bool ("use_stefan",
107 : &is.use_stefan),
108 68 : GNUNET_PQ_result_spec_relative_time (
109 : "default_wire_transfer_delay",
110 : &is.default_wire_transfer_delay),
111 68 : GNUNET_PQ_result_spec_relative_time ("default_pay_delay",
112 : &is.default_pay_delay),
113 68 : GNUNET_PQ_result_spec_allow_null (
114 : GNUNET_PQ_result_spec_string ("website",
115 : &is.website),
116 : NULL),
117 68 : GNUNET_PQ_result_spec_allow_null (
118 : GNUNET_PQ_result_spec_string ("email",
119 : &is.email),
120 : NULL),
121 68 : GNUNET_PQ_result_spec_allow_null (
122 : GNUNET_PQ_result_spec_string ("logo",
123 : &is.logo),
124 : NULL),
125 : GNUNET_PQ_result_spec_end
126 : };
127 :
128 68 : memset (&ias.auth_salt,
129 : 0,
130 : sizeof (ias.auth_salt));
131 68 : memset (&ias.auth_hash,
132 : 0,
133 : sizeof (ias.auth_hash));
134 68 : if (GNUNET_OK !=
135 68 : GNUNET_PQ_extract_result (result,
136 : rs,
137 : i))
138 : {
139 0 : GNUNET_break (0);
140 0 : lic->qs = GNUNET_DB_STATUS_HARD_ERROR;
141 0 : return;
142 : }
143 68 : lic->cb (lic->cb_cls,
144 : &merchant_pub,
145 : (no_priv) ? NULL : &merchant_priv,
146 : &is,
147 : &ias);
148 68 : GNUNET_PQ_cleanup_result (rs);
149 : }
150 : }
151 :
152 :
153 : enum GNUNET_DB_QueryStatus
154 14 : TMH_PG_lookup_instances (void *cls,
155 : bool active_only,
156 : TALER_MERCHANTDB_InstanceCallback cb,
157 : void *cb_cls)
158 : {
159 14 : struct PostgresClosure *pg = cls;
160 14 : struct LookupInstancesContext lic = {
161 : .cb = cb,
162 : .cb_cls = cb_cls,
163 : .pg = pg
164 : };
165 14 : struct GNUNET_PQ_QueryParam params[] = {
166 : GNUNET_PQ_query_param_end
167 : };
168 : enum GNUNET_DB_QueryStatus qs;
169 :
170 14 : check_connection (pg);
171 14 : PREPARE (pg,
172 : "lookup_instances",
173 : "SELECT"
174 : " mi.merchant_serial"
175 : ",mi.merchant_pub"
176 : ",mi.auth_hash"
177 : ",mi.auth_salt"
178 : ",mi.merchant_id"
179 : ",mi.merchant_name"
180 : ",mi.address"
181 : ",mi.jurisdiction"
182 : ",mi.use_stefan"
183 : ",mi.default_wire_transfer_delay"
184 : ",mi.default_pay_delay"
185 : ",mi.website"
186 : ",mi.email"
187 : ",mi.logo"
188 : ",mk.merchant_priv"
189 : " FROM merchant_instances mi"
190 : " LEFT JOIN merchant_keys mk"
191 : " USING (merchant_serial)");
192 14 : PREPARE (pg,
193 : "lookup_active_instances",
194 : "SELECT "
195 : " mi.merchant_serial"
196 : ",mi.merchant_pub"
197 : ",mi.auth_hash"
198 : ",mi.auth_salt"
199 : ",mi.merchant_id"
200 : ",mi.merchant_name"
201 : ",mi.address"
202 : ",mi.jurisdiction"
203 : ",mi.use_stefan"
204 : ",mi.default_wire_transfer_delay"
205 : ",mi.default_pay_delay"
206 : ",mi.website"
207 : ",mi.email"
208 : ",mi.logo"
209 : ",mk.merchant_priv"
210 : " FROM merchant_instances mi"
211 : " JOIN merchant_keys mk"
212 : " USING (merchant_serial)");
213 14 : qs = GNUNET_PQ_eval_prepared_multi_select (
214 : pg->conn,
215 : active_only
216 : ? "lookup_active_instances"
217 : : "lookup_instances",
218 : params,
219 : &lookup_instances_cb,
220 : &lic);
221 14 : if (0 > lic.qs)
222 0 : return lic.qs;
223 14 : return qs;
224 : }
225 :
226 :
227 : enum GNUNET_DB_QueryStatus
228 80 : TMH_PG_lookup_instance (void *cls,
229 : const char *id,
230 : bool active_only,
231 : TALER_MERCHANTDB_InstanceCallback cb,
232 : void *cb_cls)
233 : {
234 80 : struct PostgresClosure *pg = cls;
235 80 : struct LookupInstancesContext lic = {
236 : .cb = cb,
237 : .cb_cls = cb_cls,
238 : .pg = pg
239 : };
240 80 : struct GNUNET_PQ_QueryParam params[] = {
241 80 : GNUNET_PQ_query_param_string (id),
242 : GNUNET_PQ_query_param_end
243 : };
244 : enum GNUNET_DB_QueryStatus qs;
245 :
246 80 : check_connection (pg);
247 80 : PREPARE (pg,
248 : "lookup_instance",
249 : "SELECT"
250 : " mi.merchant_serial"
251 : ",mi.merchant_pub"
252 : ",mi.auth_hash"
253 : ",mi.auth_salt"
254 : ",mi.merchant_id"
255 : ",mi.merchant_name"
256 : ",mi.address"
257 : ",mi.jurisdiction"
258 : ",mi.use_stefan"
259 : ",mi.default_wire_transfer_delay"
260 : ",mi.default_pay_delay"
261 : ",mi.website"
262 : ",mi.email"
263 : ",mi.logo"
264 : ",mk.merchant_priv"
265 : " FROM merchant_instances mi"
266 : " LEFT JOIN merchant_keys mk"
267 : " USING (merchant_serial)"
268 : " WHERE merchant_id=$1");
269 80 : PREPARE (pg,
270 : "lookup_active_instance",
271 : "SELECT"
272 : " mi.merchant_serial"
273 : ",mi.merchant_pub"
274 : ",mi.auth_hash"
275 : ",mi.auth_salt"
276 : ",mi.merchant_id"
277 : ",mi.merchant_name"
278 : ",mi.user_type"
279 : ",mi.address"
280 : ",mi.jurisdiction"
281 : ",mi.use_stefan"
282 : ",mi.default_wire_transfer_delay"
283 : ",mi.default_pay_delay"
284 : ",mi.website"
285 : ",mi.email"
286 : ",mi.logo"
287 : ",mk.merchant_priv"
288 : " FROM merchant_instances mi"
289 : " JOIN merchant_keys mk"
290 : " USING (merchant_serial)"
291 : " WHERE merchant_id=$1");
292 80 : qs = GNUNET_PQ_eval_prepared_multi_select (
293 : pg->conn,
294 : active_only
295 : ? "lookup_active_instance"
296 : : "lookup_instance",
297 : params,
298 : &lookup_instances_cb,
299 : &lic);
300 80 : if (0 > lic.qs)
301 0 : return lic.qs;
302 80 : return qs;
303 : }
|