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