merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

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 }