merchant

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

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


      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_unit = false;
     78   bool builtin_conflict = false;
     79   enum MHD_Result ret = MHD_YES;
     80 
     81   (void) rh;
     82   GNUNET_assert (NULL != mi);
     83   GNUNET_assert (NULL != unit_id);
     84 
     85   res = TALER_MHD_parse_json_data (connection,
     86                                    hc->request_body,
     87                                    spec);
     88   if (GNUNET_OK != res)
     89     return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
     90 
     91   if (NULL == nud.unit_name_long &&
     92       NULL == nud.unit_name_long_i18n &&
     93       NULL == nud.unit_name_short &&
     94       NULL == nud.unit_name_short_i18n &&
     95       unit_allow_fraction_missing &&
     96       unit_precision_missing &&
     97       unit_active_missing)
     98   {
     99     ret = TALER_MHD_reply_static (connection,
    100                                   MHD_HTTP_NO_CONTENT,
    101                                   NULL,
    102                                   NULL,
    103                                   0);
    104     goto cleanup;
    105   }
    106 
    107   if (! unit_precision_missing)
    108   {
    109     if (nud.unit_precision_level > TMH_MAX_UNIT_PRECISION_LEVEL)
    110     {
    111       GNUNET_break_op (0);
    112       ret = TALER_MHD_reply_with_error (connection,
    113                                         MHD_HTTP_BAD_REQUEST,
    114                                         TALER_EC_GENERIC_PARAMETER_MALFORMED,
    115                                         "unit_precision_level");
    116       goto cleanup;
    117     }
    118     unit_precision_ptr = &nud.unit_precision_level;
    119   }
    120 
    121   if (! unit_allow_fraction_missing)
    122   {
    123     unit_allow_fraction_ptr = &nud.unit_allow_fraction;
    124     if (! nud.unit_allow_fraction)
    125     {
    126       nud.unit_precision_level = 0;
    127       unit_precision_missing = false;
    128       unit_precision_ptr = &nud.unit_precision_level;
    129     }
    130   }
    131 
    132   if (! unit_active_missing)
    133     unit_active_ptr = &nud.unit_active;
    134 
    135   if (NULL != nud.unit_name_long_i18n)
    136   {
    137     if (! TALER_JSON_check_i18n (nud.unit_name_long_i18n))
    138     {
    139       GNUNET_break_op (0);
    140       ret = TALER_MHD_reply_with_error (connection,
    141                                         MHD_HTTP_BAD_REQUEST,
    142                                         TALER_EC_GENERIC_PARAMETER_MALFORMED,
    143                                         "unit_name_long_i18n");
    144       goto cleanup;
    145     }
    146   }
    147 
    148   if (NULL != nud.unit_name_short_i18n)
    149   {
    150     if (! TALER_JSON_check_i18n (nud.unit_name_short_i18n))
    151     {
    152       GNUNET_break_op (0);
    153       ret = TALER_MHD_reply_with_error (connection,
    154                                         MHD_HTTP_BAD_REQUEST,
    155                                         TALER_EC_GENERIC_PARAMETER_MALFORMED,
    156                                         "unit_name_short_i18n");
    157       goto cleanup;
    158     }
    159   }
    160 
    161   qs = TALER_MERCHANTDB_update_unit (TMH_db,
    162                                      mi->settings.id,
    163                                      unit_id,
    164                                      nud.unit_name_long,
    165                                      nud.unit_name_long_i18n,
    166                                      nud.unit_name_short,
    167                                      nud.unit_name_short_i18n,
    168                                      unit_allow_fraction_ptr,
    169                                      unit_precision_ptr,
    170                                      unit_active_ptr,
    171                                      &no_unit,
    172                                      &builtin_conflict);
    173   switch (qs)
    174   {
    175   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
    176     break;
    177   case GNUNET_DB_STATUS_SOFT_ERROR:
    178     GNUNET_break (0);
    179     ret = TALER_MHD_reply_with_error (connection,
    180                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
    181                                       TALER_EC_GENERIC_DB_SOFT_FAILURE,
    182                                       "update_unit");
    183     goto cleanup;
    184   case GNUNET_DB_STATUS_HARD_ERROR:
    185   default:
    186     GNUNET_break (0);
    187     ret = TALER_MHD_reply_with_error (connection,
    188                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
    189                                       TALER_EC_GENERIC_DB_STORE_FAILED,
    190                                       "update_unit");
    191     goto cleanup;
    192   }
    193 
    194   if (no_unit)
    195   {
    196     ret = TALER_MHD_reply_with_error (connection,
    197                                       MHD_HTTP_NOT_FOUND,
    198                                       TALER_EC_MERCHANT_GENERIC_UNIT_UNKNOWN,
    199                                       unit_id);
    200     goto cleanup;
    201   }
    202   if (builtin_conflict)
    203   {
    204     ret = TALER_MHD_reply_with_error (connection,
    205                                       MHD_HTTP_CONFLICT,
    206                                       TALER_EC_MERCHANT_GENERIC_UNIT_BUILTIN,
    207                                       unit_id);
    208     goto cleanup;
    209   }
    210 
    211   ret = TALER_MHD_reply_static (connection,
    212                                 MHD_HTTP_NO_CONTENT,
    213                                 NULL,
    214                                 NULL,
    215                                 0);
    216 
    217 cleanup:
    218   if (NULL != nud.unit_name_long_i18n)
    219   {
    220     json_decref (nud.unit_name_long_i18n);
    221     nud.unit_name_long_i18n = NULL;
    222   }
    223   if (NULL != nud.unit_name_short_i18n)
    224   {
    225     json_decref (nud.unit_name_short_i18n);
    226     nud.unit_name_short_i18n = NULL;
    227   }
    228   GNUNET_JSON_parse_free (spec);
    229   return ret;
    230 }
    231 
    232 
    233 /* end of taler-merchant-httpd_patch-private-units-UNIT.c */