merchant

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

iterate_instances.c (9226B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2022--2026 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_instances.c
     18  * @brief Implementation of the iterate_instances function for Postgres
     19  * @author Christian Grothoff
     20  */
     21 #include "platform.h"
     22 #include <taler/taler_pq_lib.h>
     23 #include "merchant-database/iterate_instances.h"
     24 #include "helper.h"
     25 
     26 
     27 /**
     28  * Context for iterate_instances().
     29  */
     30 struct LookupInstancesContext
     31 {
     32   /**
     33    * Function to call with the results.
     34    */
     35   TALER_MERCHANTDB_InstanceCallback cb;
     36 
     37   /**
     38    * Closure for @e cb.
     39    */
     40   void *cb_cls;
     41 
     42   /**
     43    * Database context.
     44    */
     45   struct TALER_MERCHANTDB_PostgresContext *pg;
     46 
     47   /**
     48    * Set to the return value on errors.
     49    */
     50   enum GNUNET_DB_QueryStatus qs;
     51 
     52 };
     53 
     54 
     55 /**
     56  * Function to be called with the results of a SELECT statement
     57  * that has returned @a num_results results about instances.
     58  *
     59  * @param cls of type `struct LookupInstancesContext *`
     60  * @param result the postgres result
     61  * @param num_results the number of results in @a result
     62  */
     63 static void
     64 lookup_instances_cb (void *cls,
     65                      PGresult *result,
     66                      unsigned int num_results)
     67 {
     68   struct LookupInstancesContext *lic = cls;
     69 
     70   for (unsigned int i = 0; i < num_results; i++)
     71   {
     72     struct TALER_MERCHANTDB_InstanceSettings is;
     73     struct TALER_MERCHANTDB_InstanceAuthSettings ias;
     74     uint64_t instance_serial;
     75     struct TALER_MerchantPublicKeyP merchant_pub;
     76     struct TALER_MerchantPrivateKeyP merchant_priv;
     77     bool no_auth;
     78     bool no_salt;
     79     bool no_priv;
     80     char *dwtri;
     81     struct GNUNET_PQ_ResultSpec rs[] = {
     82       GNUNET_PQ_result_spec_uint64 ("merchant_serial",
     83                                     &instance_serial),
     84       GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
     85                                             &merchant_pub),
     86       GNUNET_PQ_result_spec_allow_null (
     87         GNUNET_PQ_result_spec_auto_from_type ("auth_hash",
     88                                               &ias.auth_hash),
     89         &no_auth),
     90       GNUNET_PQ_result_spec_allow_null (
     91         GNUNET_PQ_result_spec_auto_from_type ("auth_salt",
     92                                               &ias.auth_salt),
     93         &no_salt),
     94       GNUNET_PQ_result_spec_allow_null (
     95         GNUNET_PQ_result_spec_auto_from_type ("merchant_priv",
     96                                               &merchant_priv),
     97         &no_priv),
     98       GNUNET_PQ_result_spec_string ("merchant_id",
     99                                     &is.id),
    100       GNUNET_PQ_result_spec_string ("merchant_name",
    101                                     &is.name),
    102       TALER_PQ_result_spec_json ("address",
    103                                  &is.address),
    104       TALER_PQ_result_spec_json ("jurisdiction",
    105                                  &is.jurisdiction),
    106       GNUNET_PQ_result_spec_bool ("use_stefan",
    107                                   &is.use_stefan),
    108       GNUNET_PQ_result_spec_bool ("phone_validated",
    109                                   &is.phone_validated),
    110       GNUNET_PQ_result_spec_bool ("email_validated",
    111                                   &is.email_validated),
    112       GNUNET_PQ_result_spec_relative_time (
    113         "default_wire_transfer_delay",
    114         &is.default_wire_transfer_delay),
    115       GNUNET_PQ_result_spec_relative_time ("default_pay_delay",
    116                                            &is.default_pay_delay),
    117       GNUNET_PQ_result_spec_relative_time ("default_refund_delay",
    118                                            &is.default_refund_delay),
    119       GNUNET_PQ_result_spec_allow_null (
    120         GNUNET_PQ_result_spec_string ("website",
    121                                       &is.website),
    122         NULL),
    123       GNUNET_PQ_result_spec_allow_null (
    124         GNUNET_PQ_result_spec_string ("email",
    125                                       &is.email),
    126         NULL),
    127       GNUNET_PQ_result_spec_allow_null (
    128         GNUNET_PQ_result_spec_string ("phone_number",
    129                                       &is.phone),
    130         NULL),
    131       GNUNET_PQ_result_spec_allow_null (
    132         GNUNET_PQ_result_spec_string ("logo",
    133                                       &is.logo),
    134         NULL),
    135       GNUNET_PQ_result_spec_string (
    136         "default_wire_transfer_rounding_interval",
    137         &dwtri),
    138       GNUNET_PQ_result_spec_end
    139     };
    140 
    141     memset (&ias.auth_salt,
    142             0,
    143             sizeof (ias.auth_salt));
    144     memset (&ias.auth_hash,
    145             0,
    146             sizeof (ias.auth_hash));
    147     if (GNUNET_OK !=
    148         GNUNET_PQ_extract_result (result,
    149                                   rs,
    150                                   i))
    151     {
    152       GNUNET_break (0);
    153       lic->qs = GNUNET_DB_STATUS_HARD_ERROR;
    154       return;
    155     }
    156     if (GNUNET_OK !=
    157         GNUNET_TIME_string_to_round_interval (
    158           dwtri,
    159           &is.default_wire_transfer_rounding_interval))
    160     {
    161       GNUNET_break (0);
    162       lic->qs = GNUNET_DB_STATUS_HARD_ERROR;
    163       GNUNET_PQ_cleanup_result (rs);
    164       return;
    165     }
    166     if ( (NULL != is.website) &&
    167          (! TALER_is_web_url (is.website)) )
    168     {
    169       GNUNET_break (0); /* merchant-0052 migration should have
    170                            prevented this... */
    171       GNUNET_free (is.website);
    172     }
    173     lic->cb (lic->cb_cls,
    174              &merchant_pub,
    175              (no_priv) ? NULL : &merchant_priv,
    176              &is,
    177              &ias);
    178     GNUNET_PQ_cleanup_result (rs);
    179   }
    180 }
    181 
    182 
    183 enum GNUNET_DB_QueryStatus
    184 TALER_MERCHANTDB_iterate_instances (
    185   struct TALER_MERCHANTDB_PostgresContext *pg,
    186   bool active_only,
    187   TALER_MERCHANTDB_InstanceCallback cb,
    188   void *cb_cls)
    189 {
    190   struct LookupInstancesContext lic = {
    191     .cb = cb,
    192     .cb_cls = cb_cls,
    193     .pg = pg
    194   };
    195   struct GNUNET_PQ_QueryParam params[] = {
    196     GNUNET_PQ_query_param_bool (active_only),
    197     GNUNET_PQ_query_param_end
    198   };
    199   enum GNUNET_DB_QueryStatus qs;
    200 
    201   PREPARE (pg,
    202            "iterate_instances",
    203            "SELECT"
    204            "  merchant_serial"
    205            " ,merchant_pub"
    206            " ,auth_hash"
    207            " ,auth_salt"
    208            " ,merchant_priv"
    209            " ,merchant_id"
    210            " ,merchant_name"
    211            " ,address::TEXT"
    212            " ,jurisdiction::TEXT"
    213            " ,use_stefan"
    214            " ,phone_validated"
    215            " ,email_validated"
    216            " ,default_wire_transfer_delay"
    217            " ,default_pay_delay"
    218            " ,default_refund_delay"
    219            " ,website"
    220            " ,email"
    221            " ,phone_number"
    222            " ,logo"
    223            " ,default_wire_transfer_rounding_interval::TEXT"
    224            "  FROM merchant.merchant_instances"
    225            " WHERE (NOT $1 OR merchant_priv IS NOT NULL)");
    226   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    227                                              "iterate_instances",
    228                                              params,
    229                                              &lookup_instances_cb,
    230                                              &lic);
    231   if (0 > lic.qs)
    232     return lic.qs;
    233   return qs;
    234 }
    235 
    236 
    237 enum GNUNET_DB_QueryStatus
    238 TALER_MERCHANTDB_iterate_instances_by_id (
    239   struct TALER_MERCHANTDB_PostgresContext *pg,
    240   const char *id,
    241   bool active_only,
    242   TALER_MERCHANTDB_InstanceCallback cb,
    243   void *cb_cls)
    244 {
    245   struct LookupInstancesContext lic = {
    246     .cb = cb,
    247     .cb_cls = cb_cls,
    248     .pg = pg
    249   };
    250   struct GNUNET_PQ_QueryParam params[] = {
    251     GNUNET_PQ_query_param_bool (active_only),
    252     GNUNET_PQ_query_param_string (id),
    253     GNUNET_PQ_query_param_end
    254   };
    255   enum GNUNET_DB_QueryStatus qs;
    256 
    257   PREPARE (pg,
    258            "iterate_instances_by_id",
    259            "SELECT"
    260            "  merchant_serial"
    261            " ,merchant_pub"
    262            " ,auth_hash"
    263            " ,auth_salt"
    264            " ,merchant_priv"
    265            " ,merchant_id"
    266            " ,merchant_name"
    267            " ,address::TEXT"
    268            " ,jurisdiction::TEXT"
    269            " ,use_stefan"
    270            " ,phone_validated"
    271            " ,email_validated"
    272            " ,default_wire_transfer_delay"
    273            " ,default_pay_delay"
    274            " ,default_refund_delay"
    275            " ,website"
    276            " ,email"
    277            " ,phone_number"
    278            " ,logo"
    279            " ,default_wire_transfer_rounding_interval::TEXT"
    280            "  FROM merchant.merchant_instances"
    281            " WHERE (merchant_id = $2)"
    282            "   AND (NOT $1 OR merchant_priv IS NOT NULL)");
    283   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    284                                              "iterate_instances_by_id",
    285                                              params,
    286                                              &lookup_instances_cb,
    287                                              &lic);
    288   if (0 > lic.qs)
    289     return lic.qs;
    290   return qs;
    291 }