exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

exchangedb_accounts.c (8078B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2018-2021 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 exchangedb/exchangedb_accounts.c
     18  * @brief Logic to parse account information from the configuration
     19  * @author Christian Grothoff
     20  */
     21 #include "exchangedb_lib.h"
     22 
     23 
     24 /**
     25  * Information we keep for each supported account of the exchange.
     26  */
     27 struct WireAccount
     28 {
     29   /**
     30    * Accounts are kept in a DLL.
     31    */
     32   struct WireAccount *next;
     33 
     34   /**
     35    * Plugins are kept in a DLL.
     36    */
     37   struct WireAccount *prev;
     38 
     39   /**
     40    * Externally visible account information.
     41    */
     42   struct TALER_EXCHANGEDB_AccountInfo ai;
     43 
     44   /**
     45    * Authentication data. Only parsed if
     46    * #TALER_EXCHANGEDB_ALO_AUTHDATA was set.
     47    */
     48   struct TALER_BANK_AuthenticationData auth;
     49 
     50   /**
     51    * Name of the section that configures this account.
     52    */
     53   char *section_name;
     54 
     55   /**
     56    * Name of the wire method underlying the account.
     57    */
     58   char *method;
     59 
     60   /**
     61    * Full payto://-URI of the account.
     62    */
     63   struct TALER_FullPayto payto_uri;
     64 
     65 };
     66 
     67 
     68 /**
     69  * Head of list of wire accounts of the exchange.
     70  */
     71 static struct WireAccount *wa_head;
     72 
     73 /**
     74  * Tail of list of wire accounts of the exchange.
     75  */
     76 static struct WireAccount *wa_tail;
     77 
     78 
     79 void
     80 TALER_EXCHANGEDB_find_accounts (TALER_EXCHANGEDB_AccountCallback cb,
     81                                 void *cb_cls)
     82 {
     83   for (struct WireAccount *wa = wa_head;
     84        NULL != wa;
     85        wa = wa->next)
     86     cb (cb_cls,
     87         &wa->ai);
     88 }
     89 
     90 
     91 const struct TALER_EXCHANGEDB_AccountInfo *
     92 TALER_EXCHANGEDB_find_account_by_method (const char *method)
     93 {
     94   for (struct WireAccount *wa = wa_head;
     95        NULL != wa;
     96        wa = wa->next)
     97     if (0 == strcmp (method,
     98                      wa->method))
     99       return &wa->ai;
    100   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    101               "No wire account known for method `%s'\n",
    102               method);
    103   return NULL;
    104 }
    105 
    106 
    107 const struct TALER_EXCHANGEDB_AccountInfo *
    108 TALER_EXCHANGEDB_find_account_by_payto_uri (
    109   const struct TALER_FullPayto url)
    110 {
    111   char *method;
    112   const struct TALER_EXCHANGEDB_AccountInfo *ai;
    113 
    114   method = TALER_payto_get_method (url.full_payto);
    115   if (NULL == method)
    116   {
    117     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    118                 "Invalid payto:// URL `%s'\n",
    119                 url.full_payto);
    120     return NULL;
    121   }
    122   ai = TALER_EXCHANGEDB_find_account_by_method (method);
    123   GNUNET_free (method);
    124   return ai;
    125 }
    126 
    127 
    128 /**
    129  * Closure for #add_account_cb().
    130  */
    131 struct LoaderContext
    132 {
    133   /**
    134    * Configuration to use.
    135    */
    136   const struct GNUNET_CONFIGURATION_Handle *cfg;
    137 
    138   /**
    139    * true if we are to load the authentication data
    140    * for the access to the bank account.
    141    */
    142   bool load_auth_data;
    143 
    144   /**
    145    * Load accounts enabled for CREDIT.
    146    */
    147   bool credit;
    148 
    149   /**
    150    * Load accounts enabled for DEBIT.
    151    */
    152   bool debit;
    153 
    154   /**
    155    * Loader status (set by callback).
    156    */
    157   enum GNUNET_GenericReturnValue res;
    158 };
    159 
    160 
    161 /**
    162  * Function called with information about a wire account.  Adds
    163  * the account to our list.
    164  *
    165  * @param cls closure, a `struct LoaderContext`
    166  * @param section section to parse account information from
    167  */
    168 static void
    169 add_account_cb (void *cls,
    170                 const char *section)
    171 {
    172   struct LoaderContext *lc = cls;
    173   const struct GNUNET_CONFIGURATION_Handle *cfg = lc->cfg;
    174   struct WireAccount *wa;
    175   char *payto_uri;
    176   char *method;
    177   bool debit;
    178   bool credit;
    179   struct TALER_FullPayto full_payto;
    180   char *err;
    181 
    182   if (0 != strncasecmp (section,
    183                         "exchange-account-",
    184                         strlen ("exchange-account-")))
    185     return;
    186 
    187   debit = (GNUNET_YES ==
    188            GNUNET_CONFIGURATION_get_value_yesno (lc->cfg,
    189                                                  section,
    190                                                  "ENABLE_DEBIT"));
    191   credit = (GNUNET_YES ==
    192             GNUNET_CONFIGURATION_get_value_yesno (lc->cfg,
    193                                                   section,
    194                                                   "ENABLE_CREDIT"));
    195   if (! ( ( (debit) &&
    196             (lc->debit) ) ||
    197           ( (credit) &&
    198             (lc->credit) ) ) )
    199     return; /* not enabled for us, skip */
    200   if (GNUNET_OK !=
    201       GNUNET_CONFIGURATION_get_value_string (cfg,
    202                                              section,
    203                                              "PAYTO_URI",
    204                                              &payto_uri))
    205   {
    206     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
    207                                section,
    208                                "PAYTO_URI");
    209     return;
    210   }
    211   full_payto.full_payto = payto_uri;
    212   if (NULL != (err = TALER_payto_validate (full_payto)))
    213   {
    214     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    215                 "payto URI in config ([%s]/PAYTO_URI) malformed: %s\n",
    216                 section,
    217                 err);
    218     lc->res = GNUNET_SYSERR;
    219     GNUNET_free (payto_uri);
    220     GNUNET_free (err);
    221     return;
    222   }
    223   if (NULL == (method = TALER_payto_get_method (payto_uri)))
    224   {
    225     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    226                 "payto URI in config ([%s]/PAYTO_URI) malformed: no method!?\n",
    227                 section);
    228     lc->res = GNUNET_SYSERR;
    229     GNUNET_free (payto_uri);
    230     return;
    231   }
    232   wa = GNUNET_new (struct WireAccount);
    233   wa->section_name = GNUNET_strdup (section);
    234   wa->payto_uri = full_payto;
    235   wa->method = method;
    236   wa->ai.debit_enabled = debit;
    237   wa->ai.credit_enabled = credit;
    238   wa->ai.auth = NULL;
    239   wa->ai.section_name = wa->section_name;
    240   wa->ai.method = wa->method;
    241   wa->ai.payto_uri = full_payto;
    242   if (lc->load_auth_data)
    243   {
    244     char *csn;
    245 
    246     GNUNET_asprintf (&csn,
    247                      "exchange-accountcredentials-%s",
    248                      &section[strlen ("exchange-account-")]);
    249     if (GNUNET_OK !=
    250         TALER_BANK_auth_parse_cfg (cfg,
    251                                    csn,
    252                                    &wa->auth))
    253     {
    254       GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
    255                   "Failed to load exchange account credentials from section `%s'\n",
    256                   csn);
    257       GNUNET_free (csn);
    258       GNUNET_free (wa->section_name);
    259       GNUNET_free (wa->method);
    260       GNUNET_free (wa);
    261       return;
    262     }
    263     wa->ai.auth = &wa->auth;
    264     GNUNET_free (csn);
    265   }
    266   GNUNET_CONTAINER_DLL_insert (wa_head,
    267                                wa_tail,
    268                                wa);
    269 }
    270 
    271 
    272 enum GNUNET_GenericReturnValue
    273 TALER_EXCHANGEDB_load_accounts (
    274   const struct GNUNET_CONFIGURATION_Handle *cfg,
    275   enum TALER_EXCHANGEDB_AccountLoaderOptions options)
    276 {
    277   struct LoaderContext lc = {
    278     .cfg = cfg,
    279     .debit = 0 != (options & TALER_EXCHANGEDB_ALO_DEBIT),
    280     .credit = 0 != (options & TALER_EXCHANGEDB_ALO_CREDIT),
    281     .load_auth_data = 0 != (options & TALER_EXCHANGEDB_ALO_AUTHDATA),
    282   };
    283 
    284   GNUNET_CONFIGURATION_iterate_sections (cfg,
    285                                          &add_account_cb,
    286                                          &lc);
    287   if (GNUNET_SYSERR == lc.res)
    288     return GNUNET_SYSERR;
    289   if (NULL == wa_head)
    290     return GNUNET_NO;
    291   return GNUNET_OK;
    292 }
    293 
    294 
    295 void
    296 TALER_EXCHANGEDB_unload_accounts (void)
    297 {
    298   struct WireAccount *wa;
    299 
    300   while (NULL != (wa = wa_head))
    301   {
    302     GNUNET_CONTAINER_DLL_remove (wa_head,
    303                                  wa_tail,
    304                                  wa);
    305     if (NULL != wa->ai.auth)
    306       TALER_BANK_auth_free (&wa->auth);
    307     GNUNET_free (wa->section_name);
    308     GNUNET_free (wa->payto_uri.full_payto);
    309     GNUNET_free (wa->method);
    310     GNUNET_free (wa);
    311   }
    312 }
    313 
    314 
    315 /* end of exchangedb_accounts.c */