Line data Source code
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/iterate_token_family_keys.c
18 : * @brief Implementation of the iterate_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/iterate_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 5 : lookup_token_keys_cb (void *cls,
64 : PGresult *result,
65 : unsigned int num_results)
66 : {
67 5 : struct Context *ctx = cls;
68 :
69 10 : for (unsigned int i = 0; i < num_results; i++)
70 : {
71 : struct TALER_MERCHANTDB_TokenFamilyKeyDetails details;
72 : char *kind;
73 5 : struct GNUNET_PQ_ResultSpec rs[] = {
74 5 : GNUNET_PQ_result_spec_allow_null (
75 : GNUNET_PQ_result_spec_blind_sign_pub ("pub",
76 : &details.pub.public_key),
77 : NULL),
78 5 : GNUNET_PQ_result_spec_allow_null (
79 : GNUNET_PQ_result_spec_blind_sign_priv ("priv",
80 : &details.priv.private_key),
81 : NULL),
82 5 : GNUNET_PQ_result_spec_allow_null (
83 : GNUNET_PQ_result_spec_timestamp ("signature_validity_start",
84 : &details.signature_validity_start),
85 : NULL),
86 5 : GNUNET_PQ_result_spec_allow_null (
87 : GNUNET_PQ_result_spec_timestamp ("signature_validity_end",
88 : &details.signature_validity_end),
89 : NULL),
90 5 : 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 5 : GNUNET_PQ_result_spec_string ("slug",
95 : &details.token_family.slug),
96 5 : GNUNET_PQ_result_spec_string ("name",
97 : &details.token_family.name),
98 5 : GNUNET_PQ_result_spec_string ("description",
99 : &details.token_family.description),
100 5 : GNUNET_PQ_result_spec_string ("cipher_choice",
101 : &details.token_family.cipher_spec),
102 5 : TALER_PQ_result_spec_json ("description_i18n",
103 : &details.token_family.description_i18n),
104 5 : GNUNET_PQ_result_spec_timestamp ("valid_after",
105 : &details.token_family.valid_after),
106 5 : GNUNET_PQ_result_spec_timestamp ("valid_before",
107 : &details.token_family.valid_before),
108 5 : GNUNET_PQ_result_spec_relative_time ("duration",
109 : &details.token_family.duration),
110 5 : GNUNET_PQ_result_spec_relative_time ("validity_granularity",
111 : &details.token_family.
112 : validity_granularity),
113 5 : GNUNET_PQ_result_spec_relative_time ("start_offset",
114 : &details.token_family.start_offset),
115 5 : GNUNET_PQ_result_spec_string ("kind",
116 : &kind),
117 5 : GNUNET_PQ_result_spec_uint64 ("issued",
118 : &details.token_family.issued),
119 5 : GNUNET_PQ_result_spec_uint64 ("used",
120 : &details.token_family.used),
121 : GNUNET_PQ_result_spec_end
122 : };
123 :
124 5 : memset (&details,
125 : 0,
126 : sizeof (details));
127 5 : if (GNUNET_OK !=
128 5 : GNUNET_PQ_extract_result (result,
129 : rs,
130 : i))
131 : {
132 0 : GNUNET_break (0);
133 0 : ctx->extract_failed = true;
134 0 : return;
135 : }
136 5 : if (0 == strcmp (kind,
137 : "discount"))
138 1 : details.token_family.kind = TALER_MERCHANTDB_TFK_Discount;
139 4 : else if (0 == strcmp (kind,
140 : "subscription"))
141 4 : details.token_family.kind = TALER_MERCHANTDB_TFK_Subscription;
142 : else
143 : {
144 0 : GNUNET_break (0);
145 0 : GNUNET_free (kind);
146 0 : GNUNET_PQ_cleanup_result (rs);
147 0 : return;
148 : }
149 5 : ctx->cb (ctx->cb_cls,
150 : &details);
151 5 : GNUNET_PQ_cleanup_result (rs);
152 : }
153 : }
154 :
155 :
156 : enum GNUNET_DB_QueryStatus
157 5 : TALER_MERCHANTDB_iterate_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 5 : struct GNUNET_PQ_QueryParam params[] = {
167 5 : GNUNET_PQ_query_param_string (token_family_slug),
168 5 : GNUNET_PQ_query_param_timestamp (&start_time),
169 5 : GNUNET_PQ_query_param_timestamp (&end_time),
170 : GNUNET_PQ_query_param_end
171 : };
172 5 : struct Context ctx = {
173 : .pg = pg,
174 : .cb = cb,
175 : .cb_cls = cb_cls
176 : };
177 : enum GNUNET_DB_QueryStatus qs;
178 :
179 5 : GNUNET_assert (NULL != pg->current_merchant_id);
180 5 : GNUNET_assert (0 == strcmp (instance_id,
181 : pg->current_merchant_id));
182 5 : TMH_PQ_prepare_anon (pg,
183 : "SELECT"
184 : " h_pub"
185 : ",mtfk.pub"
186 : ",mtfk.priv"
187 : ",cipher_choice"
188 : ",mtfk.signature_validity_start"
189 : ",mtfk.signature_validity_end"
190 : ",mtfk.private_key_deleted_at"
191 : ",slug"
192 : ",name"
193 : ",description"
194 : ",description_i18n::TEXT"
195 : ",mtf.valid_after"
196 : ",mtf.valid_before"
197 : ",duration"
198 : ",validity_granularity"
199 : ",start_offset"
200 : ",kind"
201 : ",issued"
202 : ",used"
203 : " FROM merchant_token_families mtf"
204 : " LEFT JOIN merchant_token_family_keys mtfk"
205 : " USING (token_family_serial)"
206 : " WHERE slug=$1"
207 : " AND COALESCE ($2 <= mtfk.signature_validity_end, TRUE)"
208 : " AND COALESCE ($3 >= mtfk.signature_validity_start, TRUE);");
209 5 : qs = GNUNET_PQ_eval_prepared_multi_select (
210 : pg->conn,
211 : "",
212 : params,
213 : &lookup_token_keys_cb,
214 : &ctx);
215 5 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
216 : "Lookup of MTFK %s with valid [%llu,%llu] got %d\n",
217 : token_family_slug,
218 : (unsigned long long) start_time.abs_time.abs_value_us,
219 : (unsigned long long) end_time.abs_time.abs_value_us,
220 : (int) qs);
221 5 : if (ctx.extract_failed)
222 0 : return GNUNET_DB_STATUS_HARD_ERROR;
223 5 : return qs;
224 : }
|