merchant

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

taler-merchant-httpd_private-post-units.c (7315B)


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