merchant

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

taler-merchant-httpd_patch-private-units-UNIT.c (8455B)


      1 /*
      2   This file is part of TALER
      3   (C) 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 Affero 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 src/backend/taler-merchant-httpd_patch-private-units-UNIT.c
     18  * @brief implement PATCH /private/units/$UNIT
     19  * @author Bohdan Potuzhnyi
     20  */
     21 #include "platform.h"
     22 #include "taler-merchant-httpd_patch-private-units-UNIT.h"
     23 #include "taler-merchant-httpd_helper.h"
     24 #include <taler/taler_json_lib.h>
     25 #include "merchant-database/update_unit.h"
     26 
     27 #define TMH_MAX_UNIT_PRECISION_LEVEL 6
     28 
     29 
     30 enum MHD_Result
     31 TMH_private_patch_units_ID (const struct TMH_RequestHandler *rh,
     32                             struct MHD_Connection *connection,
     33                             struct TMH_HandlerContext *hc)
     34 {
     35   struct TMH_MerchantInstance *mi = hc->instance;
     36   const char *unit_id = hc->infix;
     37   struct TALER_MERCHANTDB_UnitDetails nud = { 0 };
     38   bool unit_allow_fraction_missing = true;
     39   bool unit_precision_missing = true;
     40   bool unit_active_missing = true;
     41   struct GNUNET_JSON_Specification spec[] = {
     42     GNUNET_JSON_spec_mark_optional (
     43       GNUNET_JSON_spec_string ("unit_name_long",
     44                                (const char **) &nud.unit_name_long),
     45       NULL),
     46     GNUNET_JSON_spec_mark_optional (
     47       GNUNET_JSON_spec_json ("unit_name_long_i18n",
     48                              &nud.unit_name_long_i18n),
     49       NULL),
     50     GNUNET_JSON_spec_mark_optional (
     51       GNUNET_JSON_spec_string ("unit_name_short",
     52                                (const char **) &nud.unit_name_short),
     53       NULL),
     54     GNUNET_JSON_spec_mark_optional (
     55       GNUNET_JSON_spec_json ("unit_name_short_i18n",
     56                              &nud.unit_name_short_i18n),
     57       NULL),
     58     GNUNET_JSON_spec_mark_optional (
     59       GNUNET_JSON_spec_bool ("unit_allow_fraction",
     60                              &nud.unit_allow_fraction),
     61       &unit_allow_fraction_missing),
     62     GNUNET_JSON_spec_mark_optional (
     63       GNUNET_JSON_spec_uint32 ("unit_precision_level",
     64                                &nud.unit_precision_level),
     65       &unit_precision_missing),
     66     GNUNET_JSON_spec_mark_optional (
     67       GNUNET_JSON_spec_bool ("unit_active",
     68                              &nud.unit_active),
     69       &unit_active_missing),
     70     GNUNET_JSON_spec_end ()
     71   };
     72   enum GNUNET_GenericReturnValue res;
     73   const bool *unit_allow_fraction_ptr = NULL;
     74   const uint32_t *unit_precision_ptr = NULL;
     75   const bool *unit_active_ptr = NULL;
     76   enum GNUNET_DB_QueryStatus qs;
     77   bool no_instance = false;
     78   bool no_unit = false;
     79   bool builtin_conflict = false;
     80   enum MHD_Result ret = MHD_YES;
     81 
     82   (void) rh;
     83   GNUNET_assert (NULL != mi);
     84   GNUNET_assert (NULL != unit_id);
     85 
     86   res = TALER_MHD_parse_json_data (connection,
     87                                    hc->request_body,
     88                                    spec);
     89   if (GNUNET_OK != res)
     90     return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
     91 
     92   if (NULL == nud.unit_name_long &&
     93       NULL == nud.unit_name_long_i18n &&
     94       NULL == nud.unit_name_short &&
     95       NULL == nud.unit_name_short_i18n &&
     96       unit_allow_fraction_missing &&
     97       unit_precision_missing &&
     98       unit_active_missing)
     99   {
    100     ret = TALER_MHD_reply_static (connection,
    101                                   MHD_HTTP_NO_CONTENT,
    102                                   NULL,
    103                                   NULL,
    104                                   0);
    105     goto cleanup;
    106   }
    107 
    108   if (! unit_precision_missing)
    109   {
    110     if (nud.unit_precision_level > TMH_MAX_UNIT_PRECISION_LEVEL)
    111     {
    112       GNUNET_break_op (0);
    113       ret = TALER_MHD_reply_with_error (connection,
    114                                         MHD_HTTP_BAD_REQUEST,
    115                                         TALER_EC_GENERIC_PARAMETER_MALFORMED,
    116                                         "unit_precision_level");
    117       goto cleanup;
    118     }
    119     unit_precision_ptr = &nud.unit_precision_level;
    120   }
    121 
    122   if (! unit_allow_fraction_missing)
    123   {
    124     unit_allow_fraction_ptr = &nud.unit_allow_fraction;
    125     if (! nud.unit_allow_fraction)
    126     {
    127       nud.unit_precision_level = 0;
    128       unit_precision_missing = false;
    129       unit_precision_ptr = &nud.unit_precision_level;
    130     }
    131   }
    132 
    133   if (! unit_active_missing)
    134     unit_active_ptr = &nud.unit_active;
    135 
    136   if (NULL != nud.unit_name_long_i18n)
    137   {
    138     if (! TALER_JSON_check_i18n (nud.unit_name_long_i18n))
    139     {
    140       GNUNET_break_op (0);
    141       ret = TALER_MHD_reply_with_error (connection,
    142                                         MHD_HTTP_BAD_REQUEST,
    143                                         TALER_EC_GENERIC_PARAMETER_MALFORMED,
    144                                         "unit_name_long_i18n");
    145       goto cleanup;
    146     }
    147   }
    148 
    149   if (NULL != nud.unit_name_short_i18n)
    150   {
    151     if (! TALER_JSON_check_i18n (nud.unit_name_short_i18n))
    152     {
    153       GNUNET_break_op (0);
    154       ret = TALER_MHD_reply_with_error (connection,
    155                                         MHD_HTTP_BAD_REQUEST,
    156                                         TALER_EC_GENERIC_PARAMETER_MALFORMED,
    157                                         "unit_name_short_i18n");
    158       goto cleanup;
    159     }
    160   }
    161 
    162   qs = TALER_MERCHANTDB_update_unit (TMH_db,
    163                                      mi->settings.id,
    164                                      unit_id,
    165                                      nud.unit_name_long,
    166                                      nud.unit_name_long_i18n,
    167                                      nud.unit_name_short,
    168                                      nud.unit_name_short_i18n,
    169                                      unit_allow_fraction_ptr,
    170                                      unit_precision_ptr,
    171                                      unit_active_ptr,
    172                                      &no_instance,
    173                                      &no_unit,
    174                                      &builtin_conflict);
    175   switch (qs)
    176   {
    177   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
    178     break;
    179   case GNUNET_DB_STATUS_SOFT_ERROR:
    180     GNUNET_break (0);
    181     ret = TALER_MHD_reply_with_error (connection,
    182                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
    183                                       TALER_EC_GENERIC_DB_SOFT_FAILURE,
    184                                       "update_unit");
    185     goto cleanup;
    186   case GNUNET_DB_STATUS_HARD_ERROR:
    187   default:
    188     GNUNET_break (0);
    189     ret = TALER_MHD_reply_with_error (connection,
    190                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
    191                                       TALER_EC_GENERIC_DB_STORE_FAILED,
    192                                       "update_unit");
    193     goto cleanup;
    194   }
    195 
    196   if (no_instance)
    197   {
    198     ret = TALER_MHD_reply_with_error (connection,
    199                                       MHD_HTTP_NOT_FOUND,
    200                                       TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
    201                                       mi->settings.id);
    202     goto cleanup;
    203   }
    204   if (no_unit)
    205   {
    206     ret = TALER_MHD_reply_with_error (connection,
    207                                       MHD_HTTP_NOT_FOUND,
    208                                       TALER_EC_MERCHANT_GENERIC_UNIT_UNKNOWN,
    209                                       unit_id);
    210     goto cleanup;
    211   }
    212   if (builtin_conflict)
    213   {
    214     ret = TALER_MHD_reply_with_error (connection,
    215                                       MHD_HTTP_CONFLICT,
    216                                       TALER_EC_MERCHANT_GENERIC_UNIT_BUILTIN,
    217                                       unit_id);
    218     goto cleanup;
    219   }
    220 
    221   ret = TALER_MHD_reply_static (connection,
    222                                 MHD_HTTP_NO_CONTENT,
    223                                 NULL,
    224                                 NULL,
    225                                 0);
    226 
    227 cleanup:
    228   if (NULL != nud.unit_name_long_i18n)
    229   {
    230     json_decref (nud.unit_name_long_i18n);
    231     nud.unit_name_long_i18n = NULL;
    232   }
    233   if (NULL != nud.unit_name_short_i18n)
    234   {
    235     json_decref (nud.unit_name_short_i18n);
    236     nud.unit_name_short_i18n = NULL;
    237   }
    238   GNUNET_JSON_parse_free (spec);
    239   return ret;
    240 }
    241 
    242 
    243 /* end of taler-merchant-httpd_patch-private-units-UNIT.c */