Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2022--2026 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 src/backenddb/iterate_instances.c
18 : * @brief Implementation of the iterate_instances function for Postgres
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include <taler/taler_pq_lib.h>
23 : #include "merchant-database/iterate_instances.h"
24 : #include "helper.h"
25 :
26 :
27 : /**
28 : * Context for iterate_instances().
29 : */
30 : struct LookupInstancesContext
31 : {
32 : /**
33 : * Function to call with the results.
34 : */
35 : TALER_MERCHANTDB_InstanceCallback cb;
36 :
37 : /**
38 : * Closure for @e cb.
39 : */
40 : void *cb_cls;
41 :
42 : /**
43 : * Database context.
44 : */
45 : struct TALER_MERCHANTDB_PostgresContext *pg;
46 :
47 : /**
48 : * Set to the return value on errors.
49 : */
50 : enum GNUNET_DB_QueryStatus qs;
51 :
52 : };
53 :
54 :
55 : /**
56 : * Function to be called with the results of a SELECT statement
57 : * that has returned @a num_results results about instances.
58 : *
59 : * @param cls of type `struct LookupInstancesContext *`
60 : * @param result the postgres result
61 : * @param num_results the number of results in @a result
62 : */
63 : static void
64 126 : lookup_instances_cb (void *cls,
65 : PGresult *result,
66 : unsigned int num_results)
67 : {
68 126 : struct LookupInstancesContext *lic = cls;
69 :
70 221 : for (unsigned int i = 0; i < num_results; i++)
71 : {
72 : struct TALER_MERCHANTDB_InstanceSettings is;
73 : struct TALER_MERCHANTDB_InstanceAuthSettings ias;
74 : uint64_t instance_serial;
75 : struct TALER_MerchantPublicKeyP merchant_pub;
76 : struct TALER_MerchantPrivateKeyP merchant_priv;
77 : bool no_auth;
78 : bool no_salt;
79 : bool no_priv;
80 : char *dwtri;
81 95 : struct GNUNET_PQ_ResultSpec rs[] = {
82 95 : GNUNET_PQ_result_spec_uint64 ("merchant_serial",
83 : &instance_serial),
84 95 : GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
85 : &merchant_pub),
86 95 : GNUNET_PQ_result_spec_allow_null (
87 : GNUNET_PQ_result_spec_auto_from_type ("auth_hash",
88 : &ias.auth_hash),
89 : &no_auth),
90 95 : GNUNET_PQ_result_spec_allow_null (
91 : GNUNET_PQ_result_spec_auto_from_type ("auth_salt",
92 : &ias.auth_salt),
93 : &no_salt),
94 95 : GNUNET_PQ_result_spec_allow_null (
95 : GNUNET_PQ_result_spec_auto_from_type ("merchant_priv",
96 : &merchant_priv),
97 : &no_priv),
98 95 : GNUNET_PQ_result_spec_string ("merchant_id",
99 : &is.id),
100 95 : GNUNET_PQ_result_spec_string ("merchant_name",
101 : &is.name),
102 95 : TALER_PQ_result_spec_json ("address",
103 : &is.address),
104 95 : TALER_PQ_result_spec_json ("jurisdiction",
105 : &is.jurisdiction),
106 95 : GNUNET_PQ_result_spec_bool ("use_stefan",
107 : &is.use_stefan),
108 95 : GNUNET_PQ_result_spec_bool ("phone_validated",
109 : &is.phone_validated),
110 95 : GNUNET_PQ_result_spec_bool ("email_validated",
111 : &is.email_validated),
112 95 : GNUNET_PQ_result_spec_relative_time (
113 : "default_wire_transfer_delay",
114 : &is.default_wire_transfer_delay),
115 95 : GNUNET_PQ_result_spec_relative_time ("default_pay_delay",
116 : &is.default_pay_delay),
117 95 : GNUNET_PQ_result_spec_relative_time ("default_refund_delay",
118 : &is.default_refund_delay),
119 95 : GNUNET_PQ_result_spec_allow_null (
120 : GNUNET_PQ_result_spec_string ("website",
121 : &is.website),
122 : NULL),
123 95 : GNUNET_PQ_result_spec_allow_null (
124 : GNUNET_PQ_result_spec_string ("email",
125 : &is.email),
126 : NULL),
127 95 : GNUNET_PQ_result_spec_allow_null (
128 : GNUNET_PQ_result_spec_string ("phone_number",
129 : &is.phone),
130 : NULL),
131 95 : GNUNET_PQ_result_spec_allow_null (
132 : GNUNET_PQ_result_spec_string ("logo",
133 : &is.logo),
134 : NULL),
135 95 : GNUNET_PQ_result_spec_string (
136 : "default_wire_transfer_rounding_interval",
137 : &dwtri),
138 : GNUNET_PQ_result_spec_end
139 : };
140 :
141 95 : memset (&ias.auth_salt,
142 : 0,
143 : sizeof (ias.auth_salt));
144 95 : memset (&ias.auth_hash,
145 : 0,
146 : sizeof (ias.auth_hash));
147 95 : if (GNUNET_OK !=
148 95 : GNUNET_PQ_extract_result (result,
149 : rs,
150 : i))
151 : {
152 0 : GNUNET_break (0);
153 0 : lic->qs = GNUNET_DB_STATUS_HARD_ERROR;
154 0 : return;
155 : }
156 95 : if (GNUNET_OK !=
157 95 : GNUNET_TIME_string_to_round_interval (
158 : dwtri,
159 : &is.default_wire_transfer_rounding_interval))
160 : {
161 0 : GNUNET_break (0);
162 0 : lic->qs = GNUNET_DB_STATUS_HARD_ERROR;
163 0 : return;
164 : }
165 95 : lic->cb (lic->cb_cls,
166 : &merchant_pub,
167 : (no_priv) ? NULL : &merchant_priv,
168 : &is,
169 : &ias);
170 95 : GNUNET_PQ_cleanup_result (rs);
171 : }
172 : }
173 :
174 :
175 : enum GNUNET_DB_QueryStatus
176 28 : TALER_MERCHANTDB_iterate_instances (
177 : struct TALER_MERCHANTDB_PostgresContext *pg,
178 : bool active_only,
179 : TALER_MERCHANTDB_InstanceCallback cb,
180 : void *cb_cls)
181 : {
182 28 : struct LookupInstancesContext lic = {
183 : .cb = cb,
184 : .cb_cls = cb_cls,
185 : .pg = pg
186 : };
187 28 : struct GNUNET_PQ_QueryParam params[] = {
188 28 : GNUNET_PQ_query_param_bool (active_only),
189 : GNUNET_PQ_query_param_end
190 : };
191 : enum GNUNET_DB_QueryStatus qs;
192 :
193 28 : PREPARE (pg,
194 : "iterate_instances",
195 : "SELECT"
196 : " merchant_serial"
197 : " ,merchant_pub"
198 : " ,auth_hash"
199 : " ,auth_salt"
200 : " ,merchant_priv"
201 : " ,merchant_id"
202 : " ,merchant_name"
203 : " ,address::TEXT"
204 : " ,jurisdiction::TEXT"
205 : " ,use_stefan"
206 : " ,phone_validated"
207 : " ,email_validated"
208 : " ,default_wire_transfer_delay"
209 : " ,default_pay_delay"
210 : " ,default_refund_delay"
211 : " ,website"
212 : " ,email"
213 : " ,phone_number"
214 : " ,logo"
215 : " ,default_wire_transfer_rounding_interval::TEXT"
216 : " FROM merchant.merchant_instances"
217 : " WHERE (NOT $1 OR merchant_priv IS NOT NULL)");
218 28 : qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
219 : "iterate_instances",
220 : params,
221 : &lookup_instances_cb,
222 : &lic);
223 28 : if (0 > lic.qs)
224 0 : return lic.qs;
225 28 : return qs;
226 : }
227 :
228 :
229 : enum GNUNET_DB_QueryStatus
230 98 : TALER_MERCHANTDB_iterate_instances_by_id (
231 : struct TALER_MERCHANTDB_PostgresContext *pg,
232 : const char *id,
233 : bool active_only,
234 : TALER_MERCHANTDB_InstanceCallback cb,
235 : void *cb_cls)
236 : {
237 98 : struct LookupInstancesContext lic = {
238 : .cb = cb,
239 : .cb_cls = cb_cls,
240 : .pg = pg
241 : };
242 98 : struct GNUNET_PQ_QueryParam params[] = {
243 98 : GNUNET_PQ_query_param_bool (active_only),
244 98 : GNUNET_PQ_query_param_string (id),
245 : GNUNET_PQ_query_param_end
246 : };
247 : enum GNUNET_DB_QueryStatus qs;
248 :
249 98 : PREPARE (pg,
250 : "iterate_instances_by_id",
251 : "SELECT"
252 : " merchant_serial"
253 : " ,merchant_pub"
254 : " ,auth_hash"
255 : " ,auth_salt"
256 : " ,merchant_priv"
257 : " ,merchant_id"
258 : " ,merchant_name"
259 : " ,address::TEXT"
260 : " ,jurisdiction::TEXT"
261 : " ,use_stefan"
262 : " ,phone_validated"
263 : " ,email_validated"
264 : " ,default_wire_transfer_delay"
265 : " ,default_pay_delay"
266 : " ,default_refund_delay"
267 : " ,website"
268 : " ,email"
269 : " ,phone_number"
270 : " ,logo"
271 : " ,default_wire_transfer_rounding_interval::TEXT"
272 : " FROM merchant.merchant_instances"
273 : " WHERE (merchant_id = $2)"
274 : " AND (NOT $1 OR merchant_priv IS NOT NULL)");
275 98 : qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
276 : "iterate_instances_by_id",
277 : params,
278 : &lookup_instances_cb,
279 : &lic);
280 98 : if (0 > lic.qs)
281 0 : return lic.qs;
282 98 : return qs;
283 : }
|