LCOV - code coverage report
Current view: top level - backend - taler-merchant-httpd_patch-management-instances-INSTANCE.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 36.8 % 231 85
Test Date: 2026-09-04 23:42:01 Functions: 50.0 % 4 2

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   (C) 2020-2025 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 src/backend/taler-merchant-httpd_patch-management-instances-INSTANCE.c
      22              :  * @brief implementing PATCH /instances/$ID request handling
      23              :  * @author Christian Grothoff
      24              :  */
      25              : #include "platform.h"
      26              : #include "taler-merchant-httpd_patch-management-instances-INSTANCE.h"
      27              : #include "taler-merchant-httpd_helper.h"
      28              : #include <taler/taler_json_lib.h>
      29              : #include <taler/taler_dbevents.h>
      30              : #include "taler-merchant-httpd_mfa.h"
      31              : #include "merchant-database/update_instance.h"
      32              : #include "merchant-database/start.h"
      33              : 
      34              : 
      35              : /**
      36              :  * How often do we retry the simple INSERT database transaction?
      37              :  */
      38              : #define MAX_RETRIES 3
      39              : 
      40              : 
      41              : /**
      42              :  * Free memory used by @a wm
      43              :  *
      44              :  * @param wm wire method to free
      45              :  */
      46              : static void
      47            0 : free_wm (struct TMH_WireMethod *wm)
      48              : {
      49            0 :   GNUNET_free (wm->payto_uri.full_payto);
      50            0 :   GNUNET_free (wm->wire_method);
      51            0 :   GNUNET_free (wm);
      52            0 : }
      53              : 
      54              : 
      55              : /**
      56              :  * PATCH configuration of an existing instance, given its configuration.
      57              :  *
      58              :  * @param mi instance to patch
      59              :  * @param mfa_check true if a MFA check is required
      60              :  * @param connection the MHD connection to handle
      61              :  * @param[in,out] hc context with further information about the request
      62              :  * @return MHD result code
      63              :  */
      64              : static enum MHD_Result
      65            4 : patch_instances_ID (struct TMH_MerchantInstance *mi,
      66              :                     bool mfa_check,
      67              :                     struct MHD_Connection *connection,
      68              :                     struct TMH_HandlerContext *hc)
      69              : {
      70              :   struct TALER_MERCHANTDB_InstanceSettings is;
      71              :   const char *name;
      72            4 :   struct TMH_WireMethod *wm_head = NULL;
      73            4 :   struct TMH_WireMethod *wm_tail = NULL;
      74            4 :   const char *iphone = NULL;
      75              :   bool no_transfer_delay;
      76              :   bool no_pay_delay;
      77              :   bool no_refund_delay;
      78              :   struct GNUNET_JSON_Specification spec[] = {
      79            4 :     GNUNET_JSON_spec_string ("name",
      80              :                              &name),
      81            4 :     GNUNET_JSON_spec_mark_optional (
      82              :       TALER_JSON_spec_web_url ("website",
      83              :                                (const char **) &is.website),
      84              :       NULL),
      85            4 :     GNUNET_JSON_spec_mark_optional (
      86              :       GNUNET_JSON_spec_string ("email",
      87              :                                (const char **) &is.email),
      88              :       NULL),
      89            4 :     GNUNET_JSON_spec_mark_optional (
      90              :       GNUNET_JSON_spec_string ("phone_number",
      91              :                                &iphone),
      92              :       NULL),
      93            4 :     GNUNET_JSON_spec_mark_optional (
      94              :       GNUNET_JSON_spec_string ("logo",
      95              :                                (const char **) &is.logo),
      96              :       NULL),
      97            4 :     GNUNET_JSON_spec_json ("address",
      98              :                            &is.address),
      99            4 :     GNUNET_JSON_spec_json ("jurisdiction",
     100              :                            &is.jurisdiction),
     101            4 :     GNUNET_JSON_spec_bool ("use_stefan",
     102              :                            &is.use_stefan),
     103            4 :     GNUNET_JSON_spec_mark_optional (
     104              :       GNUNET_JSON_spec_relative_time ("default_pay_delay",
     105              :                                       &is.default_pay_delay),
     106              :       &no_pay_delay),
     107            4 :     GNUNET_JSON_spec_mark_optional (
     108              :       GNUNET_JSON_spec_relative_time ("default_refund_delay",
     109              :                                       &is.default_refund_delay),
     110              :       &no_refund_delay),
     111            4 :     GNUNET_JSON_spec_mark_optional (
     112              :       GNUNET_JSON_spec_relative_time ("default_wire_transfer_delay",
     113              :                                       &is.default_wire_transfer_delay),
     114              :       &no_transfer_delay),
     115            4 :     GNUNET_JSON_spec_mark_optional (
     116              :       GNUNET_JSON_spec_time_rounder_interval (
     117              :         "default_wire_transfer_rounding_interval",
     118              :         &is.default_wire_transfer_rounding_interval),
     119              :       NULL),
     120            4 :     GNUNET_JSON_spec_end ()
     121              :   };
     122              :   enum GNUNET_DB_QueryStatus qs;
     123              : 
     124            4 :   GNUNET_assert (NULL != mi);
     125            4 :   memset (&is,
     126              :           0,
     127              :           sizeof (is));
     128              :   {
     129              :     enum GNUNET_GenericReturnValue res;
     130              : 
     131            4 :     res = TALER_MHD_parse_json_data (connection,
     132            4 :                                      hc->request_body,
     133              :                                      spec);
     134            4 :     if (GNUNET_OK != res)
     135              :       return (GNUNET_NO == res)
     136              :              ? MHD_YES
     137            0 :              : MHD_NO;
     138              :   }
     139            4 :   if (! TMH_location_object_valid (is.address))
     140              :   {
     141            0 :     GNUNET_break_op (0);
     142            0 :     GNUNET_JSON_parse_free (spec);
     143            0 :     return TALER_MHD_reply_with_error (connection,
     144              :                                        MHD_HTTP_BAD_REQUEST,
     145              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     146              :                                        "address");
     147              :   }
     148            4 :   if ( (NULL != is.logo) &&
     149            0 :        (! TALER_MERCHANT_image_data_url_valid (is.logo)) )
     150              :   {
     151            0 :     GNUNET_break_op (0);
     152            0 :     GNUNET_JSON_parse_free (spec);
     153            0 :     return TALER_MHD_reply_with_error (connection,
     154              :                                        MHD_HTTP_BAD_REQUEST,
     155              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     156              :                                        "logo");
     157              :   }
     158              : 
     159            4 :   if (! TMH_location_object_valid (is.jurisdiction))
     160              :   {
     161            0 :     GNUNET_break_op (0);
     162            0 :     GNUNET_JSON_parse_free (spec);
     163            0 :     return TALER_MHD_reply_with_error (connection,
     164              :                                        MHD_HTTP_BAD_REQUEST,
     165              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     166              :                                        "jurisdiction");
     167              :   }
     168              : 
     169            4 :   if (no_transfer_delay)
     170            0 :     is.default_wire_transfer_delay = mi->settings.default_wire_transfer_delay;
     171            4 :   if (no_pay_delay)
     172            0 :     is.default_pay_delay = mi->settings.default_pay_delay;
     173            4 :   if (no_refund_delay)
     174            0 :     is.default_refund_delay = mi->settings.default_refund_delay;
     175            4 :   if (GNUNET_TIME_relative_is_forever (is.default_pay_delay))
     176              :   {
     177            0 :     GNUNET_break_op (0);
     178            0 :     GNUNET_JSON_parse_free (spec);
     179            0 :     return TALER_MHD_reply_with_error (connection,
     180              :                                        MHD_HTTP_BAD_REQUEST,
     181              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     182              :                                        "default_pay_delay");
     183              :   }
     184            4 :   if (GNUNET_TIME_relative_is_forever (is.default_refund_delay))
     185              :   {
     186            0 :     GNUNET_break_op (0);
     187            0 :     GNUNET_JSON_parse_free (spec);
     188            0 :     return TALER_MHD_reply_with_error (connection,
     189              :                                        MHD_HTTP_BAD_REQUEST,
     190              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     191              :                                        "default_refund_delay");
     192              :   }
     193            4 :   if (GNUNET_TIME_relative_is_forever (is.default_wire_transfer_delay))
     194              :   {
     195            0 :     GNUNET_break_op (0);
     196            0 :     GNUNET_JSON_parse_free (spec);
     197            0 :     return TALER_MHD_reply_with_error (connection,
     198              :                                        MHD_HTTP_BAD_REQUEST,
     199              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     200              :                                        "default_wire_transfer_delay");
     201              :   }
     202            4 :   if (NULL != iphone)
     203              :   {
     204            0 :     is.phone = TALER_MERCHANT_phone_validate_normalize (iphone,
     205              :                                                         false);
     206            0 :     if (NULL == is.phone)
     207              :     {
     208            0 :       GNUNET_break_op (0);
     209            0 :       GNUNET_JSON_parse_free (spec);
     210            0 :       return TALER_MHD_reply_with_error (connection,
     211              :                                          MHD_HTTP_BAD_REQUEST,
     212              :                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
     213              :                                          "phone_number");
     214              :     }
     215            0 :     if ( (NULL != TMH_phone_regex) &&
     216              :          (0 !=
     217            0 :           regexec (&TMH_phone_rx,
     218            0 :                    is.phone,
     219              :                    0,
     220              :                    NULL,
     221              :                    0)) )
     222              :     {
     223            0 :       GNUNET_break_op (0);
     224            0 :       GNUNET_JSON_parse_free (spec);
     225            0 :       return TALER_MHD_reply_with_error (connection,
     226              :                                          MHD_HTTP_BAD_REQUEST,
     227              :                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
     228              :                                          "phone_number");
     229              :     }
     230              :   }
     231            4 :   if ( (NULL != is.email) &&
     232            0 :        (! TALER_MERCHANT_email_valid (is.email)) )
     233              :   {
     234            0 :     GNUNET_break_op (0);
     235            0 :     GNUNET_JSON_parse_free (spec);
     236            0 :     GNUNET_free (is.phone);
     237            0 :     return TALER_MHD_reply_with_error (connection,
     238              :                                        MHD_HTTP_BAD_REQUEST,
     239              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     240              :                                        "email");
     241              :   }
     242            4 :   if ( (NULL != is.phone) &&
     243            0 :        (NULL != mi->settings.phone) &&
     244            0 :        (0 == strcmp (mi->settings.phone,
     245            0 :                      is.phone)) )
     246            0 :     is.phone_validated = mi->settings.phone_validated;
     247            4 :   if ( (NULL != is.email) &&
     248            0 :        (NULL != mi->settings.email) &&
     249            0 :        (0 == strcmp (mi->settings.email,
     250            0 :                      is.email)) )
     251            0 :     is.email_validated = mi->settings.email_validated;
     252            4 :   if (mfa_check)
     253              :   {
     254            0 :     enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
     255            0 :     enum TEH_TanChannelSet mtc = TEH_mandatory_tan_channels;
     256              : 
     257            0 :     if ( (0 != (mtc & TMH_TCS_SMS)) &&
     258            0 :          (NULL != mi->settings.phone) &&
     259            0 :          (NULL == is.phone) )
     260              :     {
     261            0 :       GNUNET_break_op (0);
     262            0 :       GNUNET_JSON_parse_free (spec);
     263            0 :       GNUNET_free (is.phone);
     264            0 :       return TALER_MHD_reply_with_error (
     265              :         connection,
     266              :         MHD_HTTP_BAD_REQUEST,
     267              :         TALER_EC_GENERIC_PARAMETER_MISSING,
     268              :         "phone_number");
     269              :     }
     270            0 :     if ( (0 != (mtc & TMH_TCS_EMAIL)) &&
     271            0 :          (NULL != mi->settings.email) &&
     272            0 :          (NULL == is.email) )
     273              :     {
     274            0 :       GNUNET_break_op (0);
     275            0 :       GNUNET_JSON_parse_free (spec);
     276            0 :       GNUNET_free (is.phone);
     277            0 :       return TALER_MHD_reply_with_error (
     278              :         connection,
     279              :         MHD_HTTP_BAD_REQUEST,
     280              :         TALER_EC_GENERIC_PARAMETER_MISSING,
     281              :         "email");
     282              :     }
     283            0 :     if ( (is.phone_validated ||
     284            0 :           (NULL == is.phone) ) &&
     285            0 :          (0 != (mtc & TMH_TCS_SMS)) )
     286            0 :       mtc -= TMH_TCS_SMS;
     287            0 :     if ( (is.email_validated ||
     288            0 :           (NULL == is.email) ) &&
     289            0 :          (0 != (mtc & TMH_TCS_EMAIL)) )
     290            0 :       mtc -= TMH_TCS_EMAIL;
     291            0 :     switch (mtc)
     292              :     {
     293            0 :     case TMH_TCS_NONE:
     294            0 :       ret = GNUNET_OK;
     295            0 :       break;
     296            0 :     case TMH_TCS_SMS:
     297            0 :       GNUNET_assert (NULL != is.phone);
     298            0 :       is.phone_validated = true;
     299              :       /* validate new phone number, if possible require old e-mail
     300              :          address for authorization */
     301            0 :       ret = TMH_mfa_challenges_do (hc,
     302            0 :                                    mi->settings.id,
     303              :                                    TALER_MERCHANT_MFA_CO_ACCOUNT_CONFIGURATION,
     304              :                                    true,
     305              :                                    TALER_MERCHANT_MFA_CHANNEL_SMS,
     306              :                                    is.phone,
     307              :                                    0 == (TALER_MERCHANT_MFA_CHANNEL_EMAIL
     308            0 :                                          & TEH_mandatory_tan_channels)
     309              :                                    ? TALER_MERCHANT_MFA_CHANNEL_NONE
     310              :                                    : TALER_MERCHANT_MFA_CHANNEL_EMAIL,
     311              :                                    mi->settings.email,
     312              :                                    TALER_MERCHANT_MFA_CHANNEL_NONE);
     313            0 :       break;
     314            0 :     case TMH_TCS_EMAIL:
     315            0 :       GNUNET_assert (NULL != is.email);
     316            0 :       is.email_validated = true;
     317              :       /* validate new e-mail address, if possible require old phone
     318              :          address for authorization */
     319            0 :       ret = TMH_mfa_challenges_do (hc,
     320            0 :                                    mi->settings.id,
     321              :                                    TALER_MERCHANT_MFA_CO_ACCOUNT_CONFIGURATION,
     322              :                                    true,
     323              :                                    TALER_MERCHANT_MFA_CHANNEL_EMAIL,
     324              :                                    is.email,
     325              :                                    0 == (TALER_MERCHANT_MFA_CHANNEL_SMS
     326              :                                          & TEH_mandatory_tan_channels)
     327              :                                    ? TALER_MERCHANT_MFA_CHANNEL_NONE
     328              :                                    : TALER_MERCHANT_MFA_CHANNEL_SMS,
     329              :                                    mi->settings.phone,
     330              :                                    TALER_MERCHANT_MFA_CHANNEL_NONE);
     331            0 :       break;
     332            0 :     case TMH_TCS_EMAIL_AND_SMS:
     333            0 :       GNUNET_assert (NULL != is.phone);
     334            0 :       GNUNET_assert (NULL != is.email);
     335            0 :       is.phone_validated = true;
     336            0 :       is.email_validated = true;
     337              :       /* To change both, we require both old and both new
     338              :          addresses to consent */
     339            0 :       ret = TMH_mfa_challenges_do (hc,
     340            0 :                                    mi->settings.id,
     341              :                                    TALER_MERCHANT_MFA_CO_ACCOUNT_CONFIGURATION,
     342              :                                    true,
     343              :                                    TALER_MERCHANT_MFA_CHANNEL_EMAIL,
     344              :                                    mi->settings.email,
     345              :                                    TALER_MERCHANT_MFA_CHANNEL_EMAIL,
     346              :                                    is.email,
     347              :                                    TALER_MERCHANT_MFA_CHANNEL_SMS,
     348              :                                    mi->settings.phone,
     349              :                                    TALER_MERCHANT_MFA_CHANNEL_SMS,
     350              :                                    is.phone,
     351              :                                    TALER_MERCHANT_MFA_CHANNEL_NONE);
     352            0 :       break;
     353              :     }
     354            0 :     if (GNUNET_OK != ret)
     355              :     {
     356            0 :       GNUNET_JSON_parse_free (spec);
     357            0 :       GNUNET_free (is.phone);
     358              :       return (GNUNET_NO == ret)
     359              :         ? MHD_YES
     360            0 :         : MHD_NO;
     361              :     }
     362              :   }
     363              : 
     364            4 :   for (unsigned int retry = 0; retry<MAX_RETRIES; retry++)
     365              :   {
     366              :     /* Cleanup after earlier loops */
     367              :     {
     368              :       struct TMH_WireMethod *wm;
     369              : 
     370            4 :       while (NULL != (wm = wm_head))
     371              :       {
     372            0 :         GNUNET_CONTAINER_DLL_remove (wm_head,
     373              :                                      wm_tail,
     374              :                                      wm);
     375            0 :         free_wm (wm);
     376              :       }
     377              :     }
     378            4 :     if (GNUNET_OK !=
     379            4 :         TALER_MERCHANTDB_start (TMH_db,
     380              :                                 "PATCH /instances"))
     381              :     {
     382            0 :       GNUNET_JSON_parse_free (spec);
     383            0 :       GNUNET_free (is.phone);
     384            0 :       return TALER_MHD_reply_with_error (connection,
     385              :                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
     386              :                                          TALER_EC_GENERIC_DB_START_FAILED,
     387              :                                          NULL);
     388              :     }
     389              :     /* Check for equality of settings */
     390            4 :     if (! ( (0 == strcmp (mi->settings.name,
     391            2 :                           name)) &&
     392            2 :             ((mi->settings.email == is.email) ||
     393            0 :              (NULL != is.email && NULL != mi->settings.email &&
     394            0 :               0 == strcmp (mi->settings.email,
     395            0 :                            is.email))) &&
     396            2 :             ((mi->settings.phone == is.phone) ||
     397            0 :              (NULL != is.phone && NULL != mi->settings.phone &&
     398            0 :               0 == strcmp (mi->settings.phone,
     399            0 :                            is.phone))) &&
     400            2 :             ((mi->settings.website == is.website) ||
     401            0 :              (NULL != is.website && NULL != mi->settings.website &&
     402            0 :               0 == strcmp (mi->settings.website,
     403            0 :                            is.website))) &&
     404            2 :             ((mi->settings.logo == is.logo) ||
     405            0 :              (NULL != is.logo && NULL != mi->settings.logo &&
     406            0 :               0 == strcmp (mi->settings.logo,
     407            2 :                            is.logo))) &&
     408            2 :             (1 == json_equal (mi->settings.address,
     409            2 :                               is.address)) &&
     410            0 :             (1 == json_equal (mi->settings.jurisdiction,
     411            0 :                               is.jurisdiction)) &&
     412            0 :             (mi->settings.use_stefan == is.use_stefan) &&
     413            0 :             (GNUNET_TIME_relative_cmp (mi->settings.default_wire_transfer_delay,
     414              :                                        ==,
     415            0 :                                        is.default_wire_transfer_delay)) &&
     416            0 :             (GNUNET_TIME_relative_cmp (mi->settings.default_refund_delay,
     417              :                                        ==,
     418              :                                        is.default_refund_delay)) &&
     419            0 :             (GNUNET_TIME_relative_cmp (mi->settings.default_pay_delay,
     420              :                                        ==,
     421              :                                        is.default_pay_delay)) ) )
     422              :     {
     423            4 :       is.id = mi->settings.id;
     424            4 :       is.name = GNUNET_strdup (name);
     425            4 :       qs = TALER_MERCHANTDB_update_instance (TMH_db,
     426              :                                              &is);
     427            4 :       GNUNET_free (is.name);
     428            4 :       if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
     429              :       {
     430            0 :         TALER_MERCHANTDB_rollback (TMH_db);
     431            0 :         goto retry;
     432              :       }
     433              :     }
     434            4 :     qs = TALER_MERCHANTDB_commit (TMH_db);
     435            4 :     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
     436            4 :       qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     437            0 : retry:
     438            4 :     if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
     439            0 :       continue;
     440            4 :     break;
     441              :   } /* for(... MAX_RETRIES) */
     442            4 :   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
     443              :   {
     444              :     /* Hard error or retries exhausted: the transaction did not
     445              :        commit, so do NOT mutate our in-memory settings and report
     446              :        the failure to the client. */
     447            0 :     GNUNET_break (0);
     448            0 :     GNUNET_JSON_parse_free (spec);
     449            0 :     GNUNET_free (is.phone);
     450            0 :     return TALER_MHD_reply_with_error (connection,
     451              :                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
     452              :                                        TALER_EC_GENERIC_DB_COMMIT_FAILED,
     453              :                                        NULL);
     454              :   }
     455              :   /* Update our 'settings' */
     456            4 :   GNUNET_free (mi->settings.name);
     457            4 :   GNUNET_free (mi->settings.email);
     458            4 :   GNUNET_free (mi->settings.phone);
     459            4 :   GNUNET_free (mi->settings.website);
     460            4 :   GNUNET_free (mi->settings.logo);
     461            4 :   json_decref (mi->settings.address);
     462            4 :   json_decref (mi->settings.jurisdiction);
     463            4 :   is.id = mi->settings.id;
     464            4 :   mi->settings = is;
     465            4 :   mi->settings.address = json_incref (mi->settings.address);
     466            4 :   mi->settings.jurisdiction = json_incref (mi->settings.jurisdiction);
     467            4 :   mi->settings.name = GNUNET_strdup (name);
     468            4 :   if (NULL != is.email)
     469            0 :     mi->settings.email = GNUNET_strdup (is.email);
     470            4 :   mi->settings.phone = is.phone;
     471            4 :   is.phone = NULL;
     472            4 :   if (NULL != is.website)
     473            0 :     mi->settings.website = GNUNET_strdup (is.website);
     474            4 :   if (NULL != is.logo)
     475            0 :     mi->settings.logo = GNUNET_strdup (is.logo);
     476              : 
     477            4 :   GNUNET_JSON_parse_free (spec);
     478            4 :   TMH_reload_instances (mi->settings.id);
     479            4 :   return TALER_MHD_reply_static (connection,
     480              :                                  MHD_HTTP_NO_CONTENT,
     481              :                                  NULL,
     482              :                                  NULL,
     483              :                                  0);
     484              : }
     485              : 
     486              : 
     487              : enum MHD_Result
     488            0 : TMH_private_patch_instances_ID (const struct TMH_RequestHandler *rh,
     489              :                                 struct MHD_Connection *connection,
     490              :                                 struct TMH_HandlerContext *hc)
     491              : {
     492            0 :   struct TMH_MerchantInstance *mi = hc->instance;
     493              : 
     494            0 :   return patch_instances_ID (mi,
     495              :                              true,
     496              :                              connection,
     497              :                              hc);
     498              : }
     499              : 
     500              : 
     501              : enum MHD_Result
     502            4 : TMH_private_patch_instances_default_ID (const struct TMH_RequestHandler *rh,
     503              :                                         struct MHD_Connection *connection,
     504              :                                         struct TMH_HandlerContext *hc)
     505              : {
     506              :   struct TMH_MerchantInstance *mi;
     507              : 
     508            4 :   mi = TMH_lookup_instance (hc->infix);
     509            4 :   if (NULL == mi)
     510              :   {
     511            0 :     return TALER_MHD_reply_with_error (connection,
     512              :                                        MHD_HTTP_NOT_FOUND,
     513              :                                        TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
     514            0 :                                        hc->infix);
     515              :   }
     516            4 :   if (mi->deleted)
     517              :   {
     518            0 :     return TALER_MHD_reply_with_error (connection,
     519              :                                        MHD_HTTP_CONFLICT,
     520              :                                        TALER_EC_MERCHANT_PRIVATE_PATCH_INSTANCES_PURGE_REQUIRED,
     521            0 :                                        hc->infix);
     522              :   }
     523            4 :   return patch_instances_ID (mi,
     524              :                              false,
     525              :                              connection,
     526              :                              hc);
     527              : }
     528              : 
     529              : 
     530              : /* end of taler-merchant-httpd_patch-management-instances-INSTANCE.c */
        

Generated by: LCOV version 2.0-1