iterate_instances.c (9226B)
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 lookup_instances_cb (void *cls, 65 PGresult *result, 66 unsigned int num_results) 67 { 68 struct LookupInstancesContext *lic = cls; 69 70 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 struct GNUNET_PQ_ResultSpec rs[] = { 82 GNUNET_PQ_result_spec_uint64 ("merchant_serial", 83 &instance_serial), 84 GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", 85 &merchant_pub), 86 GNUNET_PQ_result_spec_allow_null ( 87 GNUNET_PQ_result_spec_auto_from_type ("auth_hash", 88 &ias.auth_hash), 89 &no_auth), 90 GNUNET_PQ_result_spec_allow_null ( 91 GNUNET_PQ_result_spec_auto_from_type ("auth_salt", 92 &ias.auth_salt), 93 &no_salt), 94 GNUNET_PQ_result_spec_allow_null ( 95 GNUNET_PQ_result_spec_auto_from_type ("merchant_priv", 96 &merchant_priv), 97 &no_priv), 98 GNUNET_PQ_result_spec_string ("merchant_id", 99 &is.id), 100 GNUNET_PQ_result_spec_string ("merchant_name", 101 &is.name), 102 TALER_PQ_result_spec_json ("address", 103 &is.address), 104 TALER_PQ_result_spec_json ("jurisdiction", 105 &is.jurisdiction), 106 GNUNET_PQ_result_spec_bool ("use_stefan", 107 &is.use_stefan), 108 GNUNET_PQ_result_spec_bool ("phone_validated", 109 &is.phone_validated), 110 GNUNET_PQ_result_spec_bool ("email_validated", 111 &is.email_validated), 112 GNUNET_PQ_result_spec_relative_time ( 113 "default_wire_transfer_delay", 114 &is.default_wire_transfer_delay), 115 GNUNET_PQ_result_spec_relative_time ("default_pay_delay", 116 &is.default_pay_delay), 117 GNUNET_PQ_result_spec_relative_time ("default_refund_delay", 118 &is.default_refund_delay), 119 GNUNET_PQ_result_spec_allow_null ( 120 GNUNET_PQ_result_spec_string ("website", 121 &is.website), 122 NULL), 123 GNUNET_PQ_result_spec_allow_null ( 124 GNUNET_PQ_result_spec_string ("email", 125 &is.email), 126 NULL), 127 GNUNET_PQ_result_spec_allow_null ( 128 GNUNET_PQ_result_spec_string ("phone_number", 129 &is.phone), 130 NULL), 131 GNUNET_PQ_result_spec_allow_null ( 132 GNUNET_PQ_result_spec_string ("logo", 133 &is.logo), 134 NULL), 135 GNUNET_PQ_result_spec_string ( 136 "default_wire_transfer_rounding_interval", 137 &dwtri), 138 GNUNET_PQ_result_spec_end 139 }; 140 141 memset (&ias.auth_salt, 142 0, 143 sizeof (ias.auth_salt)); 144 memset (&ias.auth_hash, 145 0, 146 sizeof (ias.auth_hash)); 147 if (GNUNET_OK != 148 GNUNET_PQ_extract_result (result, 149 rs, 150 i)) 151 { 152 GNUNET_break (0); 153 lic->qs = GNUNET_DB_STATUS_HARD_ERROR; 154 return; 155 } 156 if (GNUNET_OK != 157 GNUNET_TIME_string_to_round_interval ( 158 dwtri, 159 &is.default_wire_transfer_rounding_interval)) 160 { 161 GNUNET_break (0); 162 lic->qs = GNUNET_DB_STATUS_HARD_ERROR; 163 GNUNET_PQ_cleanup_result (rs); 164 return; 165 } 166 if ( (NULL != is.website) && 167 (! TALER_is_web_url (is.website)) ) 168 { 169 GNUNET_break (0); /* merchant-0052 migration should have 170 prevented this... */ 171 GNUNET_free (is.website); 172 } 173 lic->cb (lic->cb_cls, 174 &merchant_pub, 175 (no_priv) ? NULL : &merchant_priv, 176 &is, 177 &ias); 178 GNUNET_PQ_cleanup_result (rs); 179 } 180 } 181 182 183 enum GNUNET_DB_QueryStatus 184 TALER_MERCHANTDB_iterate_instances ( 185 struct TALER_MERCHANTDB_PostgresContext *pg, 186 bool active_only, 187 TALER_MERCHANTDB_InstanceCallback cb, 188 void *cb_cls) 189 { 190 struct LookupInstancesContext lic = { 191 .cb = cb, 192 .cb_cls = cb_cls, 193 .pg = pg 194 }; 195 struct GNUNET_PQ_QueryParam params[] = { 196 GNUNET_PQ_query_param_bool (active_only), 197 GNUNET_PQ_query_param_end 198 }; 199 enum GNUNET_DB_QueryStatus qs; 200 201 PREPARE (pg, 202 "iterate_instances", 203 "SELECT" 204 " merchant_serial" 205 " ,merchant_pub" 206 " ,auth_hash" 207 " ,auth_salt" 208 " ,merchant_priv" 209 " ,merchant_id" 210 " ,merchant_name" 211 " ,address::TEXT" 212 " ,jurisdiction::TEXT" 213 " ,use_stefan" 214 " ,phone_validated" 215 " ,email_validated" 216 " ,default_wire_transfer_delay" 217 " ,default_pay_delay" 218 " ,default_refund_delay" 219 " ,website" 220 " ,email" 221 " ,phone_number" 222 " ,logo" 223 " ,default_wire_transfer_rounding_interval::TEXT" 224 " FROM merchant.merchant_instances" 225 " WHERE (NOT $1 OR merchant_priv IS NOT NULL)"); 226 qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, 227 "iterate_instances", 228 params, 229 &lookup_instances_cb, 230 &lic); 231 if (0 > lic.qs) 232 return lic.qs; 233 return qs; 234 } 235 236 237 enum GNUNET_DB_QueryStatus 238 TALER_MERCHANTDB_iterate_instances_by_id ( 239 struct TALER_MERCHANTDB_PostgresContext *pg, 240 const char *id, 241 bool active_only, 242 TALER_MERCHANTDB_InstanceCallback cb, 243 void *cb_cls) 244 { 245 struct LookupInstancesContext lic = { 246 .cb = cb, 247 .cb_cls = cb_cls, 248 .pg = pg 249 }; 250 struct GNUNET_PQ_QueryParam params[] = { 251 GNUNET_PQ_query_param_bool (active_only), 252 GNUNET_PQ_query_param_string (id), 253 GNUNET_PQ_query_param_end 254 }; 255 enum GNUNET_DB_QueryStatus qs; 256 257 PREPARE (pg, 258 "iterate_instances_by_id", 259 "SELECT" 260 " merchant_serial" 261 " ,merchant_pub" 262 " ,auth_hash" 263 " ,auth_salt" 264 " ,merchant_priv" 265 " ,merchant_id" 266 " ,merchant_name" 267 " ,address::TEXT" 268 " ,jurisdiction::TEXT" 269 " ,use_stefan" 270 " ,phone_validated" 271 " ,email_validated" 272 " ,default_wire_transfer_delay" 273 " ,default_pay_delay" 274 " ,default_refund_delay" 275 " ,website" 276 " ,email" 277 " ,phone_number" 278 " ,logo" 279 " ,default_wire_transfer_rounding_interval::TEXT" 280 " FROM merchant.merchant_instances" 281 " WHERE (merchant_id = $2)" 282 " AND (NOT $1 OR merchant_priv IS NOT NULL)"); 283 qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, 284 "iterate_instances_by_id", 285 params, 286 &lookup_instances_cb, 287 &lic); 288 if (0 > lic.qs) 289 return lic.qs; 290 return qs; 291 }