merchant

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

get_token_family_key.c (8457B)


      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/get_token_family_key.c
     18  * @brief Implementation of the get_token_family_key function for Postgres
     19  * @author Christian Blättler
     20  */
     21 #include "platform.h"
     22 #include <gnunet/gnunet_pq_lib.h>
     23 #include <gnunet/gnunet_time_lib.h>
     24 #include <string.h>
     25 #include <taler/taler_error_codes.h>
     26 #include <taler/taler_dbevents.h>
     27 #include <taler/taler_pq_lib.h>
     28 #include "merchant-database/get_token_family_key.h"
     29 #include "merchant-database/start.h"
     30 #include "helper.h"
     31 
     32 
     33 enum GNUNET_DB_QueryStatus
     34 TALER_MERCHANTDB_lock_token_family (
     35   struct TALER_MERCHANTDB_PostgresContext *pg,
     36   const char *token_family_slug,
     37   bool *started_transaction)
     38 {
     39   struct GNUNET_PQ_QueryParam params[] = {
     40     GNUNET_PQ_query_param_string (token_family_slug),
     41     GNUNET_PQ_query_param_end
     42   };
     43 
     44   *started_transaction = false;
     45   GNUNET_assert (NULL != pg->current_merchant_id);
     46   if (NULL == pg->transaction_name)
     47   {
     48     if (GNUNET_OK !=
     49         TALER_MERCHANTDB_start_read_committed (pg,
     50                                                "ensure token family key"))
     51       return GNUNET_DB_STATUS_HARD_ERROR;
     52     *started_transaction = true;
     53   }
     54   /* Touch the parent even when no keys exist. A plain SELECT FOR UPDATE
     55      would allow a caller with an older SERIALIZABLE snapshot to miss keys
     56      inserted by the previous lock holder. Updating the row forces that
     57      caller to fail with a serialization error instead of minting a duplicate.
     58      Under READ COMMITTED the subsequent lookup sees the committed key. */
     59   TMH_PQ_prepare_anon (pg,
     60                        "UPDATE merchant_token_families"
     61                        " SET issued=issued"
     62                        " WHERE slug=$1");
     63   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
     64                                              "",
     65                                              params);
     66 }
     67 
     68 
     69 enum GNUNET_DB_QueryStatus
     70 TALER_MERCHANTDB_get_token_family_key (
     71   struct TALER_MERCHANTDB_PostgresContext *pg,
     72   const char *instance_id,
     73   const char *token_family_slug,
     74   struct GNUNET_TIME_Timestamp valid_at,
     75   struct GNUNET_TIME_Timestamp sign_until,
     76   struct TALER_MERCHANTDB_TokenFamilyKeyDetails *details)
     77 {
     78   struct GNUNET_PQ_QueryParam params[] = {
     79     GNUNET_PQ_query_param_string (token_family_slug),
     80     GNUNET_PQ_query_param_timestamp (&valid_at),
     81     GNUNET_PQ_query_param_timestamp (&sign_until),
     82     GNUNET_PQ_query_param_end
     83   };
     84   char *kind;
     85   struct GNUNET_PQ_ResultSpec rs[] = {
     86     GNUNET_PQ_result_spec_allow_null (
     87       GNUNET_PQ_result_spec_blind_sign_pub ("pub",
     88                                             &details->pub.public_key),
     89       NULL),
     90     GNUNET_PQ_result_spec_allow_null (
     91       GNUNET_PQ_result_spec_blind_sign_priv ("priv",
     92                                              &details->priv.private_key),
     93       NULL),
     94     GNUNET_PQ_result_spec_allow_null (
     95       GNUNET_PQ_result_spec_timestamp ("signature_validity_start",
     96                                        &details->signature_validity_start),
     97       NULL),
     98     GNUNET_PQ_result_spec_allow_null (
     99       GNUNET_PQ_result_spec_timestamp ("signature_validity_end",
    100                                        &details->signature_validity_end),
    101       NULL),
    102     GNUNET_PQ_result_spec_allow_null (
    103       GNUNET_PQ_result_spec_timestamp ("private_key_deleted_at",
    104                                        &details->private_key_deleted_at),
    105       NULL),
    106     GNUNET_PQ_result_spec_string ("slug",
    107                                   &details->token_family.slug),
    108     GNUNET_PQ_result_spec_string ("name",
    109                                   &details->token_family.name),
    110     GNUNET_PQ_result_spec_string ("cipher_choice",
    111                                   &details->token_family.cipher_spec),
    112     GNUNET_PQ_result_spec_string ("description",
    113                                   &details->token_family.description),
    114     TALER_PQ_result_spec_json ("description_i18n",
    115                                &details->token_family.description_i18n),
    116     GNUNET_PQ_result_spec_timestamp ("valid_after",
    117                                      &details->token_family.valid_after),
    118     GNUNET_PQ_result_spec_timestamp ("valid_before",
    119                                      &details->token_family.valid_before),
    120     GNUNET_PQ_result_spec_relative_time ("duration",
    121                                          &details->token_family.duration),
    122     GNUNET_PQ_result_spec_relative_time ("validity_granularity",
    123                                          &details->token_family.
    124                                          validity_granularity),
    125     GNUNET_PQ_result_spec_relative_time ("start_offset",
    126                                          &details->token_family.start_offset),
    127     GNUNET_PQ_result_spec_string ("kind",
    128                                   &kind),
    129     GNUNET_PQ_result_spec_uint64 ("issued",
    130                                   &details->token_family.issued),
    131     GNUNET_PQ_result_spec_uint64 ("used",
    132                                   &details->token_family.used),
    133     GNUNET_PQ_result_spec_end
    134   };
    135   enum GNUNET_DB_QueryStatus qs;
    136 
    137   GNUNET_assert (NULL != pg->current_merchant_id);
    138   GNUNET_assert (0 == strcmp (instance_id,
    139                               pg->current_merchant_id));
    140   TMH_PQ_prepare_anon (pg,
    141                        "SELECT"
    142                        " h_pub"
    143                        ",pub"
    144                        ",priv"
    145                        ",cipher_choice"
    146                        ",mtfk.signature_validity_start"
    147                        ",mtfk.signature_validity_end"
    148                        ",mtfk.private_key_deleted_at"
    149                        ",slug"
    150                        ",name"
    151                        ",description"
    152                        ",description_i18n::TEXT"
    153                        ",mtf.valid_after"
    154                        ",mtf.valid_before"
    155                        ",duration"
    156                        ",validity_granularity"
    157                        ",start_offset"
    158                        ",kind"
    159                        ",issued"
    160                        ",used"
    161                        " FROM merchant_token_families mtf"
    162                        " LEFT JOIN merchant_token_family_keys mtfk"
    163                        "  ON ( (mtf.token_family_serial = mtfk.token_family_serial)"
    164                        "   AND ($2 >= mtfk.signature_validity_start)"
    165                        "   AND ($2 <= mtfk.signature_validity_end)"
    166                        "   AND ($3 <= mtfk.private_key_deleted_at) )"
    167                        " WHERE slug=$1"
    168                        " ORDER BY mtfk.signature_validity_start ASC"
    169                        " LIMIT 1");
    170   memset (details,
    171           0,
    172           sizeof (*details));
    173   qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
    174                                                  "",
    175                                                  params,
    176                                                  rs);
    177   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
    178   {
    179     if (0 == strcmp (kind,
    180                      "discount"))
    181     {
    182       details->token_family.kind = TALER_MERCHANTDB_TFK_Discount;
    183     }
    184     else if (0 == strcmp (kind,
    185                           "subscription"))
    186     {
    187       details->token_family.kind = TALER_MERCHANTDB_TFK_Subscription;
    188     }
    189     else
    190     {
    191       GNUNET_free (kind);
    192       GNUNET_free (details->token_family.slug);
    193       GNUNET_free (details->token_family.name);
    194       GNUNET_free (details->token_family.description);
    195       json_decref (details->token_family.description_i18n);
    196       GNUNET_CRYPTO_blind_sign_pub_decref (details->pub.public_key);
    197       GNUNET_CRYPTO_blind_sign_priv_decref (details->priv.private_key);
    198       GNUNET_free (details->token_family.cipher_spec);
    199       GNUNET_break (0);
    200       return GNUNET_DB_STATUS_HARD_ERROR;
    201     }
    202     GNUNET_free (kind);
    203   }
    204   return qs;
    205 }