pg_lookup_token_family_keys.c (7446B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 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_token_family_keys.c 18 * @brief Implementation of the lookup_token_family_keys function for Postgres 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" 22 #include <taler/taler_error_codes.h> 23 #include <taler/taler_dbevents.h> 24 #include <taler/taler_pq_lib.h> 25 #include "pg_lookup_token_family_keys.h" 26 #include "pg_helper.h" 27 28 29 /** 30 * Closure for lookup_token_keys_cb(). 31 */ 32 struct Context 33 { 34 /** 35 * Postgres handle. 36 */ 37 struct PostgresClosure *pg; 38 39 /** 40 * Function to call on each result. 41 */ 42 TALER_MERCHANTDB_TokenKeyCallback cb; 43 44 /** 45 * Closure for @e cb. 46 */ 47 void *cb_cls; 48 49 /** 50 * Did database result extraction fail? 51 */ 52 bool extract_failed; 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 products. 59 * 60 * @param[in,out] cls of type `struct LookupProductsContext *` 61 * @param result the postgres result 62 * @param num_results the number of results in @a result 63 */ 64 static void 65 lookup_token_keys_cb (void *cls, 66 PGresult *result, 67 unsigned int num_results) 68 { 69 struct Context *ctx = cls; 70 71 for (unsigned int i = 0; i < num_results; i++) 72 { 73 struct TALER_MERCHANTDB_TokenFamilyKeyDetails details; 74 char *kind; 75 struct GNUNET_PQ_ResultSpec rs[] = { 76 GNUNET_PQ_result_spec_allow_null ( 77 GNUNET_PQ_result_spec_blind_sign_pub ("pub", 78 &details.pub.public_key), 79 NULL), 80 GNUNET_PQ_result_spec_allow_null ( 81 GNUNET_PQ_result_spec_blind_sign_priv ("priv", 82 &details.priv.private_key), 83 NULL), 84 GNUNET_PQ_result_spec_allow_null ( 85 GNUNET_PQ_result_spec_timestamp ("signature_validity_start", 86 &details.signature_validity_start), 87 NULL), 88 GNUNET_PQ_result_spec_allow_null ( 89 GNUNET_PQ_result_spec_timestamp ("signature_validity_end", 90 &details.signature_validity_end), 91 NULL), 92 GNUNET_PQ_result_spec_allow_null ( 93 GNUNET_PQ_result_spec_timestamp ("private_key_deleted_at", 94 &details.private_key_deleted_at), 95 NULL), 96 GNUNET_PQ_result_spec_string ("slug", 97 &details.token_family.slug), 98 GNUNET_PQ_result_spec_string ("name", 99 &details.token_family.name), 100 GNUNET_PQ_result_spec_string ("description", 101 &details.token_family.description), 102 GNUNET_PQ_result_spec_string ("cipher_choice", 103 &details.token_family.cipher_spec), 104 TALER_PQ_result_spec_json ("description_i18n", 105 &details.token_family.description_i18n), 106 GNUNET_PQ_result_spec_timestamp ("valid_after", 107 &details.token_family.valid_after), 108 GNUNET_PQ_result_spec_timestamp ("valid_before", 109 &details.token_family.valid_before), 110 GNUNET_PQ_result_spec_relative_time ("duration", 111 &details.token_family.duration), 112 GNUNET_PQ_result_spec_relative_time ("validity_granularity", 113 &details.token_family. 114 validity_granularity), 115 GNUNET_PQ_result_spec_relative_time ("start_offset", 116 &details.token_family.start_offset), 117 GNUNET_PQ_result_spec_string ("kind", 118 &kind), 119 GNUNET_PQ_result_spec_uint64 ("issued", 120 &details.token_family.issued), 121 GNUNET_PQ_result_spec_uint64 ("used", 122 &details.token_family.used), 123 GNUNET_PQ_result_spec_end 124 }; 125 126 memset (&details, 127 0, 128 sizeof (details)); 129 if (GNUNET_OK != 130 GNUNET_PQ_extract_result (result, 131 rs, 132 i)) 133 { 134 GNUNET_break (0); 135 ctx->extract_failed = true; 136 return; 137 } 138 if (0 == strcmp (kind, 139 "discount")) 140 details.token_family.kind = TALER_MERCHANTDB_TFK_Discount; 141 else if (0 == strcmp (kind, 142 "subscription")) 143 details.token_family.kind = TALER_MERCHANTDB_TFK_Subscription; 144 else 145 { 146 GNUNET_break (0); 147 GNUNET_free (kind); 148 GNUNET_PQ_cleanup_result (rs); 149 return; 150 } 151 ctx->cb (ctx->cb_cls, 152 &details); 153 GNUNET_PQ_cleanup_result (rs); 154 } 155 } 156 157 158 enum GNUNET_DB_QueryStatus 159 TMH_PG_lookup_token_family_keys ( 160 void *cls, 161 const char *instance_id, 162 const char *token_family_slug, 163 struct GNUNET_TIME_Timestamp start_time, 164 struct GNUNET_TIME_Timestamp end_time, 165 TALER_MERCHANTDB_TokenKeyCallback cb, 166 void *cb_cls) 167 { 168 struct PostgresClosure *pg = cls; 169 struct GNUNET_PQ_QueryParam params[] = { 170 GNUNET_PQ_query_param_string (instance_id), 171 GNUNET_PQ_query_param_string (token_family_slug), 172 GNUNET_PQ_query_param_timestamp (&start_time), 173 GNUNET_PQ_query_param_timestamp (&end_time), 174 GNUNET_PQ_query_param_end 175 }; 176 struct Context ctx = { 177 .pg = pg, 178 .cb = cb, 179 .cb_cls = cb_cls 180 }; 181 enum GNUNET_DB_QueryStatus qs; 182 183 check_connection (pg); 184 PREPARE (pg, 185 "lookup_token_family_keys", 186 "SELECT" 187 " h_pub" 188 ",mtfk.pub" 189 ",mtfk.priv" 190 ",cipher_choice" 191 ",mtfk.signature_validity_start" 192 ",mtfk.signature_validity_end" 193 ",mtfk.private_key_deleted_at" 194 ",slug" 195 ",name" 196 ",description" 197 ",description_i18n::TEXT" 198 ",mtf.valid_after" 199 ",mtf.valid_before" 200 ",duration" 201 ",validity_granularity" 202 ",start_offset" 203 ",kind" 204 ",issued" 205 ",used" 206 " FROM merchant_token_families mtf" 207 " LEFT JOIN merchant_token_family_keys mtfk" 208 " USING (token_family_serial)" 209 " JOIN merchant_instances mi" 210 " USING (merchant_serial)" 211 " WHERE mi.merchant_id=$1" 212 " AND slug=$2" 213 " AND COALESCE ($3 <= mtfk.signature_validity_end, TRUE)" 214 " AND COALESCE ($4 >= mtfk.signature_validity_start, TRUE);"); 215 qs = GNUNET_PQ_eval_prepared_multi_select ( 216 pg->conn, 217 "lookup_token_family_keys", 218 params, 219 &lookup_token_keys_cb, 220 &ctx); 221 if (ctx.extract_failed) 222 return GNUNET_DB_STATUS_HARD_ERROR; 223 return qs; 224 }