merchant

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

pg_lookup_instances.c (10631B)


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