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 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 5 : lookup_token_keys_cb (void *cls,
66 : PGresult *result,
67 : unsigned int num_results)
68 : {
69 5 : struct Context *ctx = cls;
70 :
71 10 : for (unsigned int i = 0; i < num_results; i++)
72 : {
73 : struct TALER_MERCHANTDB_TokenFamilyKeyDetails details;
74 : char *kind;
75 5 : struct GNUNET_PQ_ResultSpec rs[] = {
76 5 : GNUNET_PQ_result_spec_allow_null (
77 : GNUNET_PQ_result_spec_blind_sign_pub ("pub",
78 : &details.pub.public_key),
79 : NULL),
80 5 : GNUNET_PQ_result_spec_allow_null (
81 : GNUNET_PQ_result_spec_blind_sign_priv ("priv",
82 : &details.priv.private_key),
83 : NULL),
84 5 : GNUNET_PQ_result_spec_allow_null (
85 : GNUNET_PQ_result_spec_timestamp ("signature_validity_start",
86 : &details.signature_validity_start),
87 : NULL),
88 5 : GNUNET_PQ_result_spec_allow_null (
89 : GNUNET_PQ_result_spec_timestamp ("signature_validity_end",
90 : &details.signature_validity_end),
91 : NULL),
92 5 : 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 5 : GNUNET_PQ_result_spec_string ("slug",
97 : &details.token_family.slug),
98 5 : GNUNET_PQ_result_spec_string ("name",
99 : &details.token_family.name),
100 5 : GNUNET_PQ_result_spec_string ("description",
101 : &details.token_family.description),
102 5 : GNUNET_PQ_result_spec_string ("cipher_choice",
103 : &details.token_family.cipher_spec),
104 5 : TALER_PQ_result_spec_json ("description_i18n",
105 : &details.token_family.description_i18n),
106 5 : GNUNET_PQ_result_spec_timestamp ("valid_after",
107 : &details.token_family.valid_after),
108 5 : GNUNET_PQ_result_spec_timestamp ("valid_before",
109 : &details.token_family.valid_before),
110 5 : GNUNET_PQ_result_spec_relative_time ("duration",
111 : &details.token_family.duration),
112 5 : GNUNET_PQ_result_spec_relative_time ("validity_granularity",
113 : &details.token_family.
114 : validity_granularity),
115 5 : GNUNET_PQ_result_spec_relative_time ("start_offset",
116 : &details.token_family.start_offset),
117 5 : GNUNET_PQ_result_spec_string ("kind",
118 : &kind),
119 5 : GNUNET_PQ_result_spec_uint64 ("issued",
120 : &details.token_family.issued),
121 5 : GNUNET_PQ_result_spec_uint64 ("used",
122 : &details.token_family.used),
123 : GNUNET_PQ_result_spec_end
124 : };
125 :
126 5 : memset (&details,
127 : 0,
128 : sizeof (details));
129 5 : if (GNUNET_OK !=
130 5 : GNUNET_PQ_extract_result (result,
131 : rs,
132 : i))
133 : {
134 0 : GNUNET_break (0);
135 0 : ctx->extract_failed = true;
136 0 : return;
137 : }
138 5 : if (0 == strcmp (kind,
139 : "discount"))
140 1 : details.token_family.kind = TALER_MERCHANTDB_TFK_Discount;
141 4 : else if (0 == strcmp (kind,
142 : "subscription"))
143 4 : details.token_family.kind = TALER_MERCHANTDB_TFK_Subscription;
144 : else
145 : {
146 0 : GNUNET_break (0);
147 0 : GNUNET_free (kind);
148 0 : GNUNET_PQ_cleanup_result (rs);
149 0 : return;
150 : }
151 5 : ctx->cb (ctx->cb_cls,
152 : &details);
153 5 : GNUNET_PQ_cleanup_result (rs);
154 : }
155 : }
156 :
157 :
158 : enum GNUNET_DB_QueryStatus
159 5 : 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 5 : struct PostgresClosure *pg = cls;
169 5 : struct GNUNET_PQ_QueryParam params[] = {
170 5 : GNUNET_PQ_query_param_string (instance_id),
171 5 : GNUNET_PQ_query_param_string (token_family_slug),
172 5 : GNUNET_PQ_query_param_timestamp (&start_time),
173 5 : GNUNET_PQ_query_param_timestamp (&end_time),
174 : GNUNET_PQ_query_param_end
175 : };
176 5 : struct Context ctx = {
177 : .pg = pg,
178 : .cb = cb,
179 : .cb_cls = cb_cls
180 : };
181 : enum GNUNET_DB_QueryStatus qs;
182 :
183 5 : check_connection (pg);
184 5 : 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"
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 5 : 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 5 : if (ctx.extract_failed)
222 0 : return GNUNET_DB_STATUS_HARD_ERROR;
223 5 : return qs;
224 : }
|