LCOV - code coverage report
Current view: top level - lib - merchant_api_get-management-instances-INSTANCE.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 115 0
Test Date: 2026-04-12 12:58:13 Functions: 0.0 % 5 0

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2014-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 Lesser General Public License as published by the Free Software
       7              :   Foundation; either version 2.1, 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 Lesser General Public License for more details.
      12              : 
      13              :   You should have received a copy of the GNU Lesser General Public License along with
      14              :   TALER; see the file COPYING.LGPL.  If not, see
      15              :   <http://www.gnu.org/licenses/>
      16              : */
      17              : /**
      18              :  * @file merchant_api_get-management-instances-INSTANCE.c
      19              :  * @brief Implementation of the GET /management/instances/$INSTANCE request
      20              :  * @author Christian Grothoff
      21              :  */
      22              : #include "taler/platform.h"
      23              : #include <curl/curl.h>
      24              : #include <jansson.h>
      25              : #include <microhttpd.h> /* just for HTTP status codes */
      26              : #include <gnunet/gnunet_util_lib.h>
      27              : #include <gnunet/gnunet_curl_lib.h>
      28              : #include <taler/merchant/get-management-instances-INSTANCE.h>
      29              : #include "merchant_api_curl_defaults.h"
      30              : #include <taler/taler_json_lib.h>
      31              : 
      32              : 
      33              : /**
      34              :  * Maximum number of accounts permitted.
      35              :  */
      36              : #define MAX_ACCOUNTS 1024
      37              : 
      38              : 
      39              : /**
      40              :  * Handle for a GET /management/instances/$INSTANCE operation.
      41              :  */
      42              : struct TALER_MERCHANT_GetManagementInstanceHandle
      43              : {
      44              :   /**
      45              :    * Base URL of the merchant backend.
      46              :    */
      47              :   char *base_url;
      48              : 
      49              :   /**
      50              :    * Instance identifier to query.
      51              :    */
      52              :   char *instance_id;
      53              : 
      54              :   /**
      55              :    * The full URL for this request.
      56              :    */
      57              :   char *url;
      58              : 
      59              :   /**
      60              :    * Handle for the request.
      61              :    */
      62              :   struct GNUNET_CURL_Job *job;
      63              : 
      64              :   /**
      65              :    * Function to call with the result.
      66              :    */
      67              :   TALER_MERCHANT_GetManagementInstanceCallback cb;
      68              : 
      69              :   /**
      70              :    * Closure for @a cb.
      71              :    */
      72              :   TALER_MERCHANT_GET_MANAGEMENT_INSTANCE_RESULT_CLOSURE *cb_cls;
      73              : 
      74              :   /**
      75              :    * Reference to the execution context.
      76              :    */
      77              :   struct GNUNET_CURL_Context *ctx;
      78              : };
      79              : 
      80              : 
      81              : /**
      82              :  * Parse account information from @a ia.
      83              :  *
      84              :  * @param ia JSON array (or NULL!) with account data
      85              :  * @param[in,out] igr partially filled response
      86              :  * @param gmi operation handle
      87              :  * @return #GNUNET_OK on success
      88              :  */
      89              : static enum GNUNET_GenericReturnValue
      90            0 : parse_accounts (const json_t *ia,
      91              :                 struct TALER_MERCHANT_GetManagementInstanceResponse *igr,
      92              :                 struct TALER_MERCHANT_GetManagementInstanceHandle *gmi)
      93              : {
      94            0 :   unsigned int accounts_len = (unsigned int) json_array_size (ia);
      95              : 
      96            0 :   if ( (json_array_size (ia) != (size_t) accounts_len) ||
      97              :        (accounts_len > MAX_ACCOUNTS) )
      98              :   {
      99            0 :     GNUNET_break (0);
     100            0 :     return GNUNET_SYSERR;
     101              :   }
     102            0 :   {
     103            0 :     struct TALER_MERCHANT_ManagementAccountEntry accounts[
     104            0 :       GNUNET_NZL (accounts_len)];
     105              :     size_t index;
     106              :     json_t *value;
     107              : 
     108            0 :     memset (accounts,
     109              :             0,
     110              :             sizeof (accounts));
     111            0 :     json_array_foreach (ia, index, value) {
     112            0 :       struct TALER_MERCHANT_ManagementAccountEntry *ae =
     113              :         &accounts[index];
     114              :       struct GNUNET_JSON_Specification spec[] = {
     115            0 :         TALER_JSON_spec_full_payto_uri ("payto_uri",
     116              :                                         &ae->payto_uri),
     117            0 :         GNUNET_JSON_spec_mark_optional (
     118              :           GNUNET_JSON_spec_string (
     119              :             "credit_facade_url",
     120              :             &ae->credit_facade_url),
     121              :           NULL),
     122            0 :         GNUNET_JSON_spec_fixed_auto ("h_wire",
     123              :                                      &ae->h_wire),
     124            0 :         GNUNET_JSON_spec_fixed_auto ("salt",
     125              :                                      &ae->salt),
     126            0 :         GNUNET_JSON_spec_bool ("active",
     127              :                                &ae->active),
     128            0 :         GNUNET_JSON_spec_end ()
     129              :       };
     130              : 
     131            0 :       if (GNUNET_OK !=
     132            0 :           GNUNET_JSON_parse (value,
     133              :                              spec,
     134              :                              NULL, NULL))
     135              :       {
     136            0 :         GNUNET_break_op (0);
     137            0 :         return GNUNET_SYSERR;
     138              :       }
     139              :     }
     140            0 :     igr->details.ok.accounts_length = accounts_len;
     141            0 :     igr->details.ok.accounts = accounts;
     142            0 :     gmi->cb (gmi->cb_cls,
     143              :              igr);
     144            0 :     gmi->cb = NULL;
     145              :   }
     146            0 :   return GNUNET_OK;
     147              : }
     148              : 
     149              : 
     150              : /**
     151              :  * Function called when we're done processing the
     152              :  * HTTP GET /management/instances/$INSTANCE request.
     153              :  *
     154              :  * @param cls the `struct TALER_MERCHANT_GetManagementInstanceHandle`
     155              :  * @param response_code HTTP response code, 0 on error
     156              :  * @param response response body, NULL if not in JSON
     157              :  */
     158              : static void
     159            0 : handle_get_instance_finished (void *cls,
     160              :                               long response_code,
     161              :                               const void *response)
     162              : {
     163            0 :   struct TALER_MERCHANT_GetManagementInstanceHandle *gmi = cls;
     164            0 :   const json_t *json = response;
     165            0 :   struct TALER_MERCHANT_GetManagementInstanceResponse igr = {
     166            0 :     .hr.http_status = (unsigned int) response_code,
     167              :     .hr.reply = json
     168              :   };
     169              : 
     170            0 :   gmi->job = NULL;
     171            0 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     172              :               "Got /management/instances/$INSTANCE response with status code %u\n",
     173              :               (unsigned int) response_code);
     174            0 :   switch (response_code)
     175              :   {
     176            0 :   case MHD_HTTP_OK:
     177              :     {
     178              :       const json_t *address;
     179              :       const json_t *jurisdiction;
     180              :       const json_t *accounts;
     181              :       struct GNUNET_JSON_Specification spec[] = {
     182            0 :         GNUNET_JSON_spec_string (
     183              :           "name",
     184              :           &igr.details.ok.details.name),
     185            0 :         GNUNET_JSON_spec_fixed_auto (
     186              :           "merchant_pub",
     187              :           &igr.details.ok.details.merchant_pub),
     188            0 :         GNUNET_JSON_spec_object_const (
     189              :           "address",
     190              :           &address),
     191            0 :         GNUNET_JSON_spec_object_const (
     192              :           "jurisdiction",
     193              :           &jurisdiction),
     194            0 :         GNUNET_JSON_spec_bool (
     195              :           "use_stefan",
     196              :           &igr.details.ok.details.use_stefan),
     197            0 :         GNUNET_JSON_spec_relative_time (
     198              :           "default_wire_transfer_delay",
     199              :           &igr.details.ok.details.default_wire_transfer_delay),
     200            0 :         GNUNET_JSON_spec_relative_time (
     201              :           "default_pay_delay",
     202              :           &igr.details.ok.details.default_pay_delay),
     203            0 :         GNUNET_JSON_spec_mark_optional (
     204              :           GNUNET_JSON_spec_relative_time (
     205              :             "default_refund_delay",
     206              :             &igr.details.ok.details.default_refund_delay),
     207              :           NULL),
     208            0 :         GNUNET_JSON_spec_mark_optional (
     209              :           GNUNET_JSON_spec_time_rounder_interval (
     210              :             "default_wire_transfer_rounding_interval",
     211              :             &igr.details.ok.details.default_wire_transfer_rounding_interval),
     212              :           NULL),
     213            0 :         GNUNET_JSON_spec_mark_optional (
     214              :           GNUNET_JSON_spec_string (
     215              :             "email",
     216              :             &igr.details.ok.details.email),
     217              :           NULL),
     218            0 :         GNUNET_JSON_spec_mark_optional (
     219              :           GNUNET_JSON_spec_bool (
     220              :             "email_validated",
     221              :             &igr.details.ok.details.email_validated),
     222              :           NULL),
     223            0 :         GNUNET_JSON_spec_mark_optional (
     224              :           GNUNET_JSON_spec_string (
     225              :             "phone_number",
     226              :             &igr.details.ok.details.phone_number),
     227              :           NULL),
     228            0 :         GNUNET_JSON_spec_mark_optional (
     229              :           GNUNET_JSON_spec_bool (
     230              :             "phone_validated",
     231              :             &igr.details.ok.details.phone_validated),
     232              :           NULL),
     233            0 :         GNUNET_JSON_spec_mark_optional (
     234              :           GNUNET_JSON_spec_string (
     235              :             "website",
     236              :             &igr.details.ok.details.website),
     237              :           NULL),
     238            0 :         GNUNET_JSON_spec_mark_optional (
     239              :           GNUNET_JSON_spec_string (
     240              :             "logo",
     241              :             &igr.details.ok.details.logo),
     242              :           NULL),
     243            0 :         GNUNET_JSON_spec_array_const (
     244              :           "accounts",
     245              :           &accounts),
     246            0 :         GNUNET_JSON_spec_end ()
     247              :       };
     248              : 
     249            0 :       if (GNUNET_OK !=
     250            0 :           GNUNET_JSON_parse (json,
     251              :                              spec,
     252              :                              NULL, NULL))
     253              :       {
     254            0 :         GNUNET_break_op (0);
     255            0 :         igr.hr.http_status = 0;
     256            0 :         igr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     257            0 :         break;
     258              :       }
     259            0 :       igr.details.ok.details.address = address;
     260            0 :       igr.details.ok.details.jurisdiction = jurisdiction;
     261            0 :       if (GNUNET_OK ==
     262            0 :           parse_accounts (accounts,
     263              :                           &igr,
     264              :                           gmi))
     265              :       {
     266            0 :         TALER_MERCHANT_get_management_instance_cancel (gmi);
     267            0 :         return;
     268              :       }
     269            0 :       igr.hr.http_status = 0;
     270            0 :       igr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     271            0 :       break;
     272              :     }
     273            0 :   case MHD_HTTP_UNAUTHORIZED:
     274            0 :     igr.hr.ec = TALER_JSON_get_error_code (json);
     275            0 :     igr.hr.hint = TALER_JSON_get_error_hint (json);
     276            0 :     break;
     277            0 :   case MHD_HTTP_NOT_FOUND:
     278            0 :     igr.hr.ec = TALER_JSON_get_error_code (json);
     279            0 :     igr.hr.hint = TALER_JSON_get_error_hint (json);
     280            0 :     break;
     281            0 :   default:
     282            0 :     igr.hr.ec = TALER_JSON_get_error_code (json);
     283            0 :     igr.hr.hint = TALER_JSON_get_error_hint (json);
     284            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     285              :                 "Unexpected response code %u/%d\n",
     286              :                 (unsigned int) response_code,
     287              :                 (int) igr.hr.ec);
     288            0 :     break;
     289              :   }
     290            0 :   gmi->cb (gmi->cb_cls,
     291              :            &igr);
     292            0 :   TALER_MERCHANT_get_management_instance_cancel (gmi);
     293              : }
     294              : 
     295              : 
     296              : struct TALER_MERCHANT_GetManagementInstanceHandle *
     297            0 : TALER_MERCHANT_get_management_instance_create (
     298              :   struct GNUNET_CURL_Context *ctx,
     299              :   const char *url,
     300              :   const char *instance_id)
     301              : {
     302              :   struct TALER_MERCHANT_GetManagementInstanceHandle *gmi;
     303              : 
     304            0 :   gmi = GNUNET_new (struct TALER_MERCHANT_GetManagementInstanceHandle);
     305            0 :   gmi->ctx = ctx;
     306            0 :   gmi->base_url = GNUNET_strdup (url);
     307            0 :   if (NULL != instance_id)
     308            0 :     gmi->instance_id = GNUNET_strdup (instance_id);
     309            0 :   return gmi;
     310              : }
     311              : 
     312              : 
     313              : enum TALER_ErrorCode
     314            0 : TALER_MERCHANT_get_management_instance_start (
     315              :   struct TALER_MERCHANT_GetManagementInstanceHandle *gmi,
     316              :   TALER_MERCHANT_GetManagementInstanceCallback cb,
     317              :   TALER_MERCHANT_GET_MANAGEMENT_INSTANCE_RESULT_CLOSURE *cb_cls)
     318              : {
     319              :   CURL *eh;
     320              : 
     321            0 :   gmi->cb = cb;
     322            0 :   gmi->cb_cls = cb_cls;
     323            0 :   if (NULL != gmi->instance_id)
     324              :   {
     325              :     char *path;
     326              : 
     327            0 :     GNUNET_asprintf (&path,
     328              :                      "instances/%s/private",
     329              :                      gmi->instance_id);
     330            0 :     gmi->url = TALER_url_join (gmi->base_url,
     331              :                                path,
     332              :                                NULL);
     333            0 :     GNUNET_free (path);
     334              :   }
     335              :   else
     336              :   {
     337            0 :     gmi->url = TALER_url_join (gmi->base_url,
     338              :                                "private",
     339              :                                NULL);
     340              :   }
     341            0 :   if (NULL == gmi->url)
     342            0 :     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
     343            0 :   eh = TALER_MERCHANT_curl_easy_get_ (gmi->url);
     344            0 :   if (NULL == eh)
     345            0 :     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
     346            0 :   gmi->job = GNUNET_CURL_job_add (gmi->ctx,
     347              :                                   eh,
     348              :                                   &handle_get_instance_finished,
     349              :                                   gmi);
     350            0 :   if (NULL == gmi->job)
     351            0 :     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
     352            0 :   return TALER_EC_NONE;
     353              : }
     354              : 
     355              : 
     356              : void
     357            0 : TALER_MERCHANT_get_management_instance_cancel (
     358              :   struct TALER_MERCHANT_GetManagementInstanceHandle *gmi)
     359              : {
     360            0 :   if (NULL != gmi->job)
     361              :   {
     362            0 :     GNUNET_CURL_job_cancel (gmi->job);
     363            0 :     gmi->job = NULL;
     364              :   }
     365            0 :   GNUNET_free (gmi->url);
     366            0 :   GNUNET_free (gmi->instance_id);
     367            0 :   GNUNET_free (gmi->base_url);
     368            0 :   GNUNET_free (gmi);
     369            0 : }
     370              : 
     371              : 
     372              : /* end of merchant_api_get-management-instances-INSTANCE.c */
        

Generated by: LCOV version 2.0-1