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