LCOV - code coverage report
Current view: top level - backend - taler-merchant-httpd_private-post-account.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 37 84 44.0 %
Date: 2025-06-23 16:22:09 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   (C) 2020-2024 Taler Systems SA
       4             : 
       5             :   TALER is free software; you can redistribute it and/or modify
       6             :   it under the terms of the GNU Affero General Public License as
       7             :   published by the Free Software Foundation; either version 3,
       8             :   or (at your option) any later version.
       9             : 
      10             :   TALER is distributed in the hope that it will be useful, but
      11             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :   GNU General Public License for more details.
      14             : 
      15             :   You should have received a copy of the GNU General Public
      16             :   License along with TALER; see the file COPYING.  If not,
      17             :   see <http://www.gnu.org/licenses/>
      18             : */
      19             : 
      20             : /**
      21             :  * @file taler-merchant-httpd_private-post-account.c
      22             :  * @brief implementing POST /private/accounts request handling
      23             :  * @author Christian Grothoff
      24             :  */
      25             : #include "platform.h"
      26             : #include "taler-merchant-httpd_private-post-account.h"
      27             : #include "taler-merchant-httpd_helper.h"
      28             : #include "taler_merchant_bank_lib.h"
      29             : #include <taler/taler_dbevents.h>
      30             : #include <taler/taler_json_lib.h>
      31             : 
      32             : 
      33             : MHD_RESULT
      34          20 : TMH_private_post_account (const struct TMH_RequestHandler *rh,
      35             :                           struct MHD_Connection *connection,
      36             :                           struct TMH_HandlerContext *hc)
      37             : {
      38          20 :   struct TMH_MerchantInstance *mi = hc->instance;
      39          20 :   const char *credit_facade_url = NULL;
      40          20 :   const json_t *credit_facade_credentials = NULL;
      41             :   struct TALER_FullPayto uri;
      42             :   struct GNUNET_JSON_Specification ispec[] = {
      43          20 :     TALER_JSON_spec_full_payto_uri ("payto_uri",
      44             :                                     &uri),
      45          20 :     GNUNET_JSON_spec_mark_optional (
      46             :       TALER_JSON_spec_web_url ("credit_facade_url",
      47             :                                &credit_facade_url),
      48             :       NULL),
      49          20 :     GNUNET_JSON_spec_mark_optional (
      50             :       GNUNET_JSON_spec_object_const ("credit_facade_credentials",
      51             :                                      &credit_facade_credentials),
      52             :       NULL),
      53          20 :     GNUNET_JSON_spec_end ()
      54             :   };
      55             :   struct TMH_WireMethod *wm;
      56             : 
      57             :   {
      58             :     enum GNUNET_GenericReturnValue res;
      59             : 
      60          20 :     res = TALER_MHD_parse_json_data (connection,
      61          20 :                                      hc->request_body,
      62             :                                      ispec);
      63          20 :     if (GNUNET_OK != res)
      64             :       return (GNUNET_NO == res)
      65             :              ? MHD_YES
      66           0 :              : MHD_NO;
      67             :   }
      68             : 
      69             :   {
      70             :     char *err;
      71             : 
      72          20 :     if (NULL !=
      73          20 :         (err = TALER_payto_validate (uri)))
      74             :     {
      75             :       MHD_RESULT mret;
      76             : 
      77           0 :       GNUNET_break_op (0);
      78           0 :       mret = TALER_MHD_reply_with_error (connection,
      79             :                                          MHD_HTTP_BAD_REQUEST,
      80             :                                          TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
      81             :                                          err);
      82           0 :       GNUNET_free (err);
      83           0 :       return mret;
      84             :     }
      85             :   }
      86             : 
      87          20 :   if ( (NULL == credit_facade_url) !=
      88             :        (NULL == credit_facade_credentials) )
      89             :   {
      90           0 :     GNUNET_break_op (0);
      91           0 :     return TALER_MHD_reply_with_error (connection,
      92             :                                        MHD_HTTP_BAD_REQUEST,
      93             :                                        TALER_EC_GENERIC_PARAMETER_MISSING,
      94           0 :                                        (NULL == credit_facade_url)
      95             :                                        ? "credit_facade_url"
      96             :                                        : "credit_facade_credentials");
      97             :   }
      98          20 :   if ( (NULL != credit_facade_url) ||
      99          18 :        (NULL != credit_facade_credentials) )
     100             :   {
     101             :     struct TALER_MERCHANT_BANK_AuthenticationData auth;
     102             : 
     103           2 :     if (GNUNET_OK !=
     104           2 :         TALER_MERCHANT_BANK_auth_parse_json (credit_facade_credentials,
     105             :                                              credit_facade_url,
     106             :                                              &auth))
     107             :     {
     108           0 :       GNUNET_break_op (0);
     109           0 :       return TALER_MHD_reply_with_error (connection,
     110             :                                          MHD_HTTP_BAD_REQUEST,
     111             :                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
     112             :                                          "credit_facade_url or credit_facade_credentials");
     113             :     }
     114           2 :     TALER_MERCHANT_BANK_auth_free (&auth);
     115             :   }
     116             : 
     117             :   /* convert provided payto URI into internal data structure with salts */
     118          20 :   wm = TMH_setup_wire_account (uri,
     119             :                                credit_facade_url,
     120             :                                credit_facade_credentials);
     121          20 :   GNUNET_assert (NULL != wm);
     122             :   {
     123          20 :     struct TALER_MERCHANTDB_AccountDetails ad = {
     124             :       .payto_uri = wm->payto_uri,
     125             :       .salt = wm->wire_salt,
     126          20 :       .instance_id = mi->settings.id,
     127             :       .h_wire = wm->h_wire,
     128          20 :       .credit_facade_url = wm->credit_facade_url,
     129          20 :       .credit_facade_credentials = wm->credit_facade_credentials,
     130          20 :       .active = wm->active
     131             :     };
     132             :     enum GNUNET_DB_QueryStatus qs;
     133             : 
     134          20 :     qs = TMH_db->insert_account (TMH_db->cls,
     135             :                                  &ad);
     136          20 :     switch (qs)
     137             :     {
     138          20 :     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     139          20 :       break;
     140           0 :     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     141             :       /* conflict: account exists */
     142             :       {
     143             :         struct TALER_MERCHANTDB_AccountDetails adx;
     144             : 
     145           0 :         qs = TMH_db->select_account_by_uri (TMH_db->cls,
     146           0 :                                             mi->settings.id,
     147             :                                             ad.payto_uri,
     148             :                                             &adx);
     149             :         switch (qs)
     150             :         {
     151           0 :         case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     152           0 :           if ( (0 == TALER_full_payto_cmp (adx.payto_uri,
     153           0 :                                            ad.payto_uri) ) &&
     154           0 :                ( (adx.credit_facade_credentials ==
     155           0 :                   ad.credit_facade_credentials) ||
     156           0 :                  ( (NULL != adx.credit_facade_credentials) &&
     157           0 :                    (NULL != ad.credit_facade_credentials) &&
     158           0 :                    (1 == json_equal (adx.credit_facade_credentials,
     159           0 :                                      ad.credit_facade_credentials)) ) ) &&
     160           0 :                ( (adx.credit_facade_url == ad.credit_facade_url) ||
     161           0 :                  ( (NULL != adx.credit_facade_url) &&
     162           0 :                    (NULL != ad.credit_facade_url) &&
     163           0 :                    (0 == strcmp (adx.credit_facade_url,
     164           0 :                                  ad.credit_facade_url)) ) ) )
     165             :           {
     166           0 :             TMH_wire_method_free (wm);
     167           0 :             GNUNET_free (adx.payto_uri.full_payto);
     168           0 :             GNUNET_free (adx.credit_facade_url);
     169           0 :             json_decref (adx.credit_facade_credentials);
     170           0 :             return TALER_MHD_REPLY_JSON_PACK (
     171             :               connection,
     172             :               MHD_HTTP_OK,
     173             :               GNUNET_JSON_pack_data_auto (
     174             :                 "salt",
     175             :                 &adx.salt),
     176             :               GNUNET_JSON_pack_data_auto (
     177             :                 "h_wire",
     178             :                 &adx.h_wire));
     179             :           }
     180           0 :           GNUNET_free (adx.payto_uri.full_payto);
     181           0 :           GNUNET_free (adx.credit_facade_url);
     182           0 :           json_decref (adx.credit_facade_credentials);
     183           0 :           break;
     184           0 :         case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     185             :         case GNUNET_DB_STATUS_SOFT_ERROR:
     186             :         case GNUNET_DB_STATUS_HARD_ERROR:
     187           0 :           GNUNET_break (0);
     188           0 :           TMH_wire_method_free (wm);
     189           0 :           return TALER_MHD_reply_with_error (connection,
     190             :                                              MHD_HTTP_INTERNAL_SERVER_ERROR,
     191             :                                              TALER_EC_GENERIC_DB_FETCH_FAILED,
     192             :                                              "select_account");
     193             :         }
     194             :       }
     195           0 :       TMH_wire_method_free (wm);
     196           0 :       return TALER_MHD_reply_with_error (connection,
     197             :                                          MHD_HTTP_CONFLICT,
     198             :                                          TALER_EC_MERCHANT_PRIVATE_ACCOUNT_EXISTS,
     199           0 :                                          uri.full_payto);
     200           0 :     case GNUNET_DB_STATUS_SOFT_ERROR:
     201             :     case GNUNET_DB_STATUS_HARD_ERROR:
     202           0 :       GNUNET_break (0);
     203           0 :       TMH_wire_method_free (wm);
     204           0 :       return TALER_MHD_reply_with_error (connection,
     205             :                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
     206             :                                          TALER_EC_GENERIC_DB_STORE_FAILED,
     207             :                                          "insert_account");
     208             :     }
     209             :   }
     210             : 
     211             :   {
     212          20 :     struct GNUNET_DB_EventHeaderP es = {
     213          20 :       .size = htons (sizeof (es)),
     214          20 :       .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED)
     215             :     };
     216             : 
     217          20 :     TMH_db->event_notify (TMH_db->cls,
     218             :                           &es,
     219             :                           NULL,
     220             :                           0);
     221             :   }
     222             :   /* Finally, also update our running process */
     223          20 :   GNUNET_CONTAINER_DLL_insert (mi->wm_head,
     224             :                                mi->wm_tail,
     225             :                                wm);
     226             :   /* Note: we may not need to do this, as we notified
     227             :      about the account change above. But also hardly hurts. */
     228          20 :   TMH_reload_instances (mi->settings.id);
     229          20 :   return TALER_MHD_REPLY_JSON_PACK (connection,
     230             :                                     MHD_HTTP_OK,
     231             :                                     GNUNET_JSON_pack_data_auto ("salt",
     232             :                                                                 &wm->wire_salt),
     233             :                                     GNUNET_JSON_pack_data_auto ("h_wire",
     234             :                                                                 &wm->h_wire));
     235             : }
     236             : 
     237             : 
     238             : /* end of taler-merchant-httpd_private-post-account.c */

Generated by: LCOV version 1.16