Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2022--2025 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 98 : lookup_instances_cb (void *cls,
66 : PGresult *result,
67 : unsigned int num_results)
68 : {
69 98 : struct LookupInstancesContext *lic = cls;
70 :
71 169 : 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 71 : struct GNUNET_PQ_ResultSpec rs[] = {
82 71 : GNUNET_PQ_result_spec_uint64 ("merchant_serial",
83 : &instance_serial),
84 71 : GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
85 : &merchant_pub),
86 71 : GNUNET_PQ_result_spec_allow_null (
87 : GNUNET_PQ_result_spec_auto_from_type ("auth_hash",
88 : &ias.auth_hash),
89 : &no_auth),
90 71 : GNUNET_PQ_result_spec_allow_null (
91 : GNUNET_PQ_result_spec_auto_from_type ("auth_salt",
92 : &ias.auth_salt),
93 : &no_salt),
94 71 : GNUNET_PQ_result_spec_allow_null (
95 : GNUNET_PQ_result_spec_auto_from_type ("merchant_priv",
96 : &merchant_priv),
97 : &no_priv),
98 71 : GNUNET_PQ_result_spec_string ("merchant_id",
99 : &is.id),
100 71 : GNUNET_PQ_result_spec_string ("merchant_name",
101 : &is.name),
102 71 : TALER_PQ_result_spec_json ("address",
103 : &is.address),
104 71 : TALER_PQ_result_spec_json ("jurisdiction",
105 : &is.jurisdiction),
106 71 : GNUNET_PQ_result_spec_bool ("use_stefan",
107 : &is.use_stefan),
108 71 : GNUNET_PQ_result_spec_bool ("phone_validated",
109 : &is.phone_validated),
110 71 : GNUNET_PQ_result_spec_bool ("email_validated",
111 : &is.email_validated),
112 71 : GNUNET_PQ_result_spec_relative_time (
113 : "default_wire_transfer_delay",
114 : &is.default_wire_transfer_delay),
115 71 : GNUNET_PQ_result_spec_relative_time ("default_pay_delay",
116 : &is.default_pay_delay),
117 71 : GNUNET_PQ_result_spec_allow_null (
118 : GNUNET_PQ_result_spec_string ("website",
119 : &is.website),
120 : NULL),
121 71 : GNUNET_PQ_result_spec_allow_null (
122 : GNUNET_PQ_result_spec_string ("email",
123 : &is.email),
124 : NULL),
125 71 : GNUNET_PQ_result_spec_allow_null (
126 : GNUNET_PQ_result_spec_string ("phone_number",
127 : &is.phone),
128 : NULL),
129 71 : GNUNET_PQ_result_spec_allow_null (
130 : GNUNET_PQ_result_spec_string ("logo",
131 : &is.logo),
132 : NULL),
133 : GNUNET_PQ_result_spec_end
134 : };
135 :
136 71 : memset (&ias.auth_salt,
137 : 0,
138 : sizeof (ias.auth_salt));
139 71 : memset (&ias.auth_hash,
140 : 0,
141 : sizeof (ias.auth_hash));
142 71 : if (GNUNET_OK !=
143 71 : GNUNET_PQ_extract_result (result,
144 : rs,
145 : i))
146 : {
147 0 : GNUNET_break (0);
148 0 : lic->qs = GNUNET_DB_STATUS_HARD_ERROR;
149 0 : return;
150 : }
151 71 : lic->cb (lic->cb_cls,
152 : &merchant_pub,
153 : (no_priv) ? NULL : &merchant_priv,
154 : &is,
155 : &ias);
156 71 : GNUNET_PQ_cleanup_result (rs);
157 : }
158 : }
159 :
160 :
161 : enum GNUNET_DB_QueryStatus
162 15 : TMH_PG_lookup_instances (void *cls,
163 : bool active_only,
164 : TALER_MERCHANTDB_InstanceCallback cb,
165 : void *cb_cls)
166 : {
167 15 : struct PostgresClosure *pg = cls;
168 15 : struct LookupInstancesContext lic = {
169 : .cb = cb,
170 : .cb_cls = cb_cls,
171 : .pg = pg
172 : };
173 15 : struct GNUNET_PQ_QueryParam params[] = {
174 : GNUNET_PQ_query_param_end
175 : };
176 : enum GNUNET_DB_QueryStatus qs;
177 :
178 15 : check_connection (pg);
179 15 : PREPARE (pg,
180 : "lookup_instances",
181 : "SELECT"
182 : " mi.merchant_serial"
183 : ",mi.merchant_pub"
184 : ",mi.auth_hash"
185 : ",mi.auth_salt"
186 : ",mi.merchant_id"
187 : ",mi.merchant_name"
188 : ",mi.address"
189 : ",mi.jurisdiction"
190 : ",mi.use_stefan"
191 : ",mi.default_wire_transfer_delay"
192 : ",mi.default_pay_delay"
193 : ",mi.website"
194 : ",mi.email"
195 : ",mi.phone_number"
196 : ",mi.phone_validated"
197 : ",mi.email_validated"
198 : ",mi.logo"
199 : ",mk.merchant_priv"
200 : " FROM merchant_instances mi"
201 : " LEFT JOIN merchant_keys mk"
202 : " USING (merchant_serial)");
203 15 : PREPARE (pg,
204 : "lookup_active_instances",
205 : "SELECT "
206 : " mi.merchant_serial"
207 : ",mi.merchant_pub"
208 : ",mi.auth_hash"
209 : ",mi.auth_salt"
210 : ",mi.merchant_id"
211 : ",mi.merchant_name"
212 : ",mi.address"
213 : ",mi.jurisdiction"
214 : ",mi.use_stefan"
215 : ",mi.default_wire_transfer_delay"
216 : ",mi.default_pay_delay"
217 : ",mi.website"
218 : ",mi.email"
219 : ",mi.phone_number"
220 : ",mi.phone_validated"
221 : ",mi.email_validated"
222 : ",mi.logo"
223 : ",mk.merchant_priv"
224 : " FROM merchant_instances mi"
225 : " JOIN merchant_keys mk"
226 : " USING (merchant_serial)");
227 15 : qs = GNUNET_PQ_eval_prepared_multi_select (
228 : pg->conn,
229 : active_only
230 : ? "lookup_active_instances"
231 : : "lookup_instances",
232 : params,
233 : &lookup_instances_cb,
234 : &lic);
235 15 : if (0 > lic.qs)
236 0 : return lic.qs;
237 15 : return qs;
238 : }
239 :
240 :
241 : enum GNUNET_DB_QueryStatus
242 83 : TMH_PG_lookup_instance (void *cls,
243 : const char *id,
244 : bool active_only,
245 : TALER_MERCHANTDB_InstanceCallback cb,
246 : void *cb_cls)
247 : {
248 83 : struct PostgresClosure *pg = cls;
249 83 : struct LookupInstancesContext lic = {
250 : .cb = cb,
251 : .cb_cls = cb_cls,
252 : .pg = pg
253 : };
254 83 : struct GNUNET_PQ_QueryParam params[] = {
255 83 : GNUNET_PQ_query_param_string (id),
256 : GNUNET_PQ_query_param_end
257 : };
258 : enum GNUNET_DB_QueryStatus qs;
259 :
260 83 : check_connection (pg);
261 83 : PREPARE (pg,
262 : "lookup_instance",
263 : "SELECT"
264 : " mi.merchant_serial"
265 : ",mi.merchant_pub"
266 : ",mi.auth_hash"
267 : ",mi.auth_salt"
268 : ",mi.merchant_id"
269 : ",mi.merchant_name"
270 : ",mi.address"
271 : ",mi.jurisdiction"
272 : ",mi.use_stefan"
273 : ",mi.default_wire_transfer_delay"
274 : ",mi.default_pay_delay"
275 : ",mi.website"
276 : ",mi.email"
277 : ",mi.phone_number"
278 : ",mi.phone_validated"
279 : ",mi.email_validated"
280 : ",mi.logo"
281 : ",mk.merchant_priv"
282 : " FROM merchant_instances mi"
283 : " LEFT JOIN merchant_keys mk"
284 : " USING (merchant_serial)"
285 : " WHERE merchant_id=$1");
286 83 : PREPARE (pg,
287 : "lookup_active_instance",
288 : "SELECT"
289 : " mi.merchant_serial"
290 : ",mi.merchant_pub"
291 : ",mi.auth_hash"
292 : ",mi.auth_salt"
293 : ",mi.merchant_id"
294 : ",mi.merchant_name"
295 : ",mi.address"
296 : ",mi.jurisdiction"
297 : ",mi.use_stefan"
298 : ",mi.default_wire_transfer_delay"
299 : ",mi.default_pay_delay"
300 : ",mi.website"
301 : ",mi.email"
302 : ",mi.phone_number"
303 : ",mi.phone_validated"
304 : ",mi.email_validated"
305 : ",mi.logo"
306 : ",mk.merchant_priv"
307 : " FROM merchant_instances mi"
308 : " JOIN merchant_keys mk"
309 : " USING (merchant_serial)"
310 : " WHERE merchant_id=$1");
311 83 : qs = GNUNET_PQ_eval_prepared_multi_select (
312 : pg->conn,
313 : active_only
314 : ? "lookup_active_instance"
315 : : "lookup_instance",
316 : params,
317 : &lookup_instances_cb,
318 : &lic);
319 83 : if (0 > lic.qs)
320 0 : return lic.qs;
321 83 : return qs;
322 : }
|