LCOV - code coverage report
Current view: top level - backend - taler-merchant-httpd_private-post-instances.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 48.3 % 234 113
Test Date: 2025-11-06 19:31:41 Functions: 66.7 % 3 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 taler-merchant-httpd_private-post-instances.c
      22              :  * @brief implementing POST /instances request handling
      23              :  * @author Christian Grothoff
      24              :  */
      25              : #include "platform.h"
      26              : #include "taler-merchant-httpd_private-post-instances.h"
      27              : #include "taler-merchant-httpd_helper.h"
      28              : #include "taler-merchant-httpd.h"
      29              : #include "taler-merchant-httpd_mfa.h"
      30              : #include "taler_merchant_bank_lib.h"
      31              : #include <taler/taler_dbevents.h>
      32              : #include <taler/taler_json_lib.h>
      33              : #include <regex.h>
      34              : 
      35              : /**
      36              :  * How often do we retry the simple INSERT database transaction?
      37              :  */
      38              : #define MAX_RETRIES 3
      39              : 
      40              : 
      41              : /**
      42              :  * Generate an instance, given its configuration.
      43              :  *
      44              :  * @param rh context of the handler
      45              :  * @param connection the MHD connection to handle
      46              :  * @param[in,out] hc context with further information about the request
      47              :  * @param login_token_expiration set to how long a login token validity
      48              :  *   should be, use zero if no login token should be created
      49              :  * @param validation_needed true if self-provisioned and
      50              :  *   email/phone registration is required before the
      51              :  *   instance can become fully active
      52              :  * @return MHD result code
      53              :  */
      54              : static MHD_RESULT
      55           33 : post_instances (const struct TMH_RequestHandler *rh,
      56              :                 struct MHD_Connection *connection,
      57              :                 struct TMH_HandlerContext *hc,
      58              :                 struct GNUNET_TIME_Relative login_token_expiration,
      59              :                 bool validation_needed)
      60              : {
      61           33 :   struct TALER_MERCHANTDB_InstanceSettings is = { 0 };
      62              :   struct TALER_MERCHANTDB_InstanceAuthSettings ias;
      63           33 :   const char *auth_password = NULL;
      64           33 :   struct TMH_WireMethod *wm_head = NULL;
      65           33 :   struct TMH_WireMethod *wm_tail = NULL;
      66              :   const json_t *jauth;
      67              :   bool no_pay_delay;
      68              :   bool no_refund_delay;
      69              :   bool no_transfer_delay;
      70              :   bool no_rounding_interval;
      71              :   struct GNUNET_JSON_Specification spec[] = {
      72           33 :     GNUNET_JSON_spec_string ("id",
      73              :                              (const char **) &is.id),
      74           33 :     GNUNET_JSON_spec_string ("name",
      75              :                              (const char **) &is.name),
      76           33 :     GNUNET_JSON_spec_mark_optional (
      77              :       GNUNET_JSON_spec_string ("email",
      78              :                                (const char **) &is.email),
      79              :       NULL),
      80           33 :     GNUNET_JSON_spec_mark_optional (
      81              :       GNUNET_JSON_spec_string ("phone_number",
      82              :                                (const char **) &is.phone),
      83              :       NULL),
      84           33 :     GNUNET_JSON_spec_mark_optional (
      85              :       GNUNET_JSON_spec_string ("website",
      86              :                                (const char **) &is.website),
      87              :       NULL),
      88           33 :     GNUNET_JSON_spec_mark_optional (
      89              :       GNUNET_JSON_spec_string ("logo",
      90              :                                (const char **) &is.logo),
      91              :       NULL),
      92           33 :     GNUNET_JSON_spec_object_const ("auth",
      93              :                                    &jauth),
      94           33 :     GNUNET_JSON_spec_json ("address",
      95              :                            &is.address),
      96           33 :     GNUNET_JSON_spec_json ("jurisdiction",
      97              :                            &is.jurisdiction),
      98           33 :     GNUNET_JSON_spec_bool ("use_stefan",
      99              :                            &is.use_stefan),
     100           33 :     GNUNET_JSON_spec_mark_optional (
     101              :       GNUNET_JSON_spec_relative_time ("default_pay_delay",
     102              :                                       &is.default_pay_delay),
     103              :       &no_pay_delay),
     104           33 :     GNUNET_JSON_spec_mark_optional (
     105              :       GNUNET_JSON_spec_relative_time ("default_refund_delay",
     106              :                                       &is.default_refund_delay),
     107              :       &no_refund_delay),
     108           33 :     GNUNET_JSON_spec_mark_optional (
     109              :       GNUNET_JSON_spec_relative_time ("default_wire_transfer_delay",
     110              :                                       &is.default_wire_transfer_delay),
     111              :       &no_transfer_delay),
     112           33 :     GNUNET_JSON_spec_mark_optional (
     113              :       GNUNET_JSON_spec_time_rounder_interval (
     114              :         "default_wire_transfer_rounding_interval",
     115              :         &is.default_wire_transfer_rounding_interval),
     116              :       &no_rounding_interval),
     117           33 :     GNUNET_JSON_spec_end ()
     118              :   };
     119              : 
     120              :   {
     121              :     enum GNUNET_GenericReturnValue res;
     122              : 
     123           33 :     res = TALER_MHD_parse_json_data (connection,
     124           33 :                                      hc->request_body,
     125              :                                      spec);
     126           33 :     if (GNUNET_OK != res)
     127              :       return (GNUNET_NO == res)
     128              :              ? MHD_YES
     129            0 :              : MHD_NO;
     130              :   }
     131           33 :   if (no_pay_delay)
     132            0 :     is.default_pay_delay = TMH_default_pay_delay;
     133           33 :   if (no_refund_delay)
     134           14 :     is.default_refund_delay = TMH_default_refund_delay;
     135           33 :   if (no_transfer_delay)
     136            0 :     is.default_wire_transfer_delay = TMH_default_wire_transfer_delay;
     137           33 :   if (no_rounding_interval)
     138              :     is.default_wire_transfer_rounding_interval
     139           14 :       = TMH_default_wire_transfer_rounding_interval;
     140              :   {
     141              :     enum GNUNET_GenericReturnValue ret;
     142              : 
     143           33 :     ret = TMH_check_auth_config (connection,
     144              :                                  jauth,
     145              :                                  &auth_password);
     146           33 :     if (GNUNET_OK != ret)
     147              :     {
     148            0 :       GNUNET_JSON_parse_free (spec);
     149            0 :       return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
     150              :     }
     151              :   }
     152              : 
     153              :   /* check 'id' well-formed */
     154              :   {
     155              :     static bool once;
     156              :     static regex_t reg;
     157           33 :     bool id_wellformed = true;
     158              : 
     159           33 :     if (! once)
     160              :     {
     161           15 :       once = true;
     162           15 :       GNUNET_assert (0 ==
     163              :                      regcomp (&reg,
     164              :                               "^[A-Za-z0-9][A-Za-z0-9_.@-]+$",
     165              :                               REG_EXTENDED));
     166              :     }
     167              : 
     168           33 :     if (0 != regexec (&reg,
     169           33 :                       is.id,
     170              :                       0, NULL, 0))
     171            0 :       id_wellformed = false;
     172           33 :     if (! id_wellformed)
     173              :     {
     174            0 :       GNUNET_JSON_parse_free (spec);
     175            0 :       return TALER_MHD_reply_with_error (connection,
     176              :                                          MHD_HTTP_BAD_REQUEST,
     177              :                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
     178              :                                          "id");
     179              :     }
     180              :   }
     181              : 
     182           33 :   if (! TMH_location_object_valid (is.address))
     183              :   {
     184            0 :     GNUNET_break_op (0);
     185            0 :     GNUNET_JSON_parse_free (spec);
     186            0 :     return TALER_MHD_reply_with_error (connection,
     187              :                                        MHD_HTTP_BAD_REQUEST,
     188              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     189              :                                        "address");
     190              :   }
     191              : 
     192           33 :   if (! TMH_location_object_valid (is.jurisdiction))
     193              :   {
     194            0 :     GNUNET_break_op (0);
     195            0 :     GNUNET_JSON_parse_free (spec);
     196            0 :     return TALER_MHD_reply_with_error (connection,
     197              :                                        MHD_HTTP_BAD_REQUEST,
     198              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     199              :                                        "jurisdiction");
     200              :   }
     201              : 
     202           33 :   if ( (NULL != is.logo) &&
     203            0 :        (! TMH_image_data_url_valid (is.logo)) )
     204              :   {
     205            0 :     GNUNET_break_op (0);
     206            0 :     GNUNET_JSON_parse_free (spec);
     207            0 :     return TALER_MHD_reply_with_error (connection,
     208              :                                        MHD_HTTP_BAD_REQUEST,
     209              :                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     210              :                                        "logo");
     211              :   }
     212              : 
     213              :   {
     214              :     /* Test if an instance of this id is known */
     215              :     struct TMH_MerchantInstance *mi;
     216              : 
     217           33 :     mi = TMH_lookup_instance (is.id);
     218           33 :     if (NULL != mi)
     219              :     {
     220            2 :       if (mi->deleted)
     221              :       {
     222            0 :         GNUNET_JSON_parse_free (spec);
     223            0 :         return TALER_MHD_reply_with_error (connection,
     224              :                                            MHD_HTTP_CONFLICT,
     225              :                                            TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_PURGE_REQUIRED,
     226            0 :                                            is.id);
     227              :       }
     228              :       /* Check for idempotency */
     229            2 :       if ( (0 == strcmp (mi->settings.id,
     230            2 :                          is.id)) &&
     231            2 :            (0 == strcmp (mi->settings.name,
     232            2 :                          is.name)) &&
     233            2 :            ((mi->settings.email == is.email) ||
     234            0 :             (NULL != is.email && NULL != mi->settings.email &&
     235            0 :              0 == strcmp (mi->settings.email,
     236            0 :                           is.email))) &&
     237            2 :            ((mi->settings.website == is.website) ||
     238            0 :             (NULL != is.website && NULL != mi->settings.website &&
     239            0 :              0 == strcmp (mi->settings.website,
     240            0 :                           is.website))) &&
     241            2 :            ((mi->settings.logo == is.logo) ||
     242            0 :             (NULL != is.logo && NULL != mi->settings.logo &&
     243            0 :              0 == strcmp (mi->settings.logo,
     244            0 :                           is.logo))) &&
     245            2 :            ( ( (NULL != auth_password) &&
     246              :                (GNUNET_OK ==
     247            0 :                 TMH_check_auth (auth_password,
     248              :                                 &mi->auth.auth_salt,
     249            2 :                                 &mi->auth.auth_hash)) ) ||
     250            4 :              ( (NULL == auth_password) &&
     251              :                (GNUNET_YES ==
     252            4 :                 GNUNET_is_zero (&mi->auth.auth_hash))) ) &&
     253            2 :            (1 == json_equal (mi->settings.address,
     254            4 :                              is.address)) &&
     255            2 :            (1 == json_equal (mi->settings.jurisdiction,
     256            2 :                              is.jurisdiction)) &&
     257            2 :            (mi->settings.use_stefan == is.use_stefan) &&
     258            2 :            (GNUNET_TIME_relative_cmp (mi->settings.default_wire_transfer_delay,
     259              :                                       ==,
     260            2 :                                       is.default_wire_transfer_delay)) &&
     261            2 :            (GNUNET_TIME_relative_cmp (mi->settings.default_pay_delay,
     262              :                                       ==,
     263            2 :                                       is.default_pay_delay)) &&
     264            2 :            (GNUNET_TIME_relative_cmp (mi->settings.default_refund_delay,
     265              :                                       ==,
     266              :                                       is.default_refund_delay)) )
     267              :       {
     268            2 :         GNUNET_JSON_parse_free (spec);
     269            2 :         return TALER_MHD_reply_static (connection,
     270              :                                        MHD_HTTP_NO_CONTENT,
     271              :                                        NULL,
     272              :                                        NULL,
     273              :                                        0);
     274              :       }
     275            0 :       GNUNET_JSON_parse_free (spec);
     276            0 :       return TALER_MHD_reply_with_error (connection,
     277              :                                          MHD_HTTP_CONFLICT,
     278              :                                          TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS,
     279            0 :                                          is.id);
     280              :     }
     281              :   }
     282              : 
     283              :   /* Check MFA is satisfied */
     284           31 :   if (validation_needed)
     285              :   {
     286            0 :     enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
     287              : 
     288            0 :     if ( (0 != (TEH_TCS_SMS & TEH_mandatory_tan_channels)) &&
     289            0 :          (NULL == is.phone) )
     290              :     {
     291            0 :       GNUNET_break_op (0);
     292            0 :       GNUNET_JSON_parse_free (spec);
     293            0 :       return TALER_MHD_reply_with_error (connection,
     294              :                                          MHD_HTTP_BAD_REQUEST,
     295              :                                          TALER_EC_GENERIC_PARAMETER_MISSING,
     296              :                                          "phone_number");
     297              : 
     298              :     }
     299            0 :     if ( (0 != (TEH_TCS_EMAIL & TEH_mandatory_tan_channels)) &&
     300            0 :          (NULL == is.email) )
     301              :     {
     302            0 :       GNUNET_break_op (0);
     303            0 :       GNUNET_JSON_parse_free (spec);
     304            0 :       return TALER_MHD_reply_with_error (connection,
     305              :                                          MHD_HTTP_BAD_REQUEST,
     306              :                                          TALER_EC_GENERIC_PARAMETER_MISSING,
     307              :                                          "email");
     308              :     }
     309            0 :     switch (TEH_mandatory_tan_channels)
     310              :     {
     311            0 :     case TEH_TCS_NONE:
     312            0 :       GNUNET_assert (0);
     313              :       ret = GNUNET_OK;
     314              :       break;
     315            0 :     case TEH_TCS_SMS:
     316            0 :       is.phone_validated = true;
     317            0 :       ret = TMH_mfa_challenges_do (hc,
     318              :                                    TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION,
     319              :                                    true,
     320              :                                    TALER_MERCHANT_MFA_CHANNEL_SMS,
     321              :                                    is.phone,
     322              :                                    TALER_MERCHANT_MFA_CHANNEL_NONE);
     323            0 :       break;
     324            0 :     case TEH_TCS_EMAIL:
     325            0 :       is.email_validated = true;
     326            0 :       ret = TMH_mfa_challenges_do (hc,
     327              :                                    TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION,
     328              :                                    true,
     329              :                                    TALER_MERCHANT_MFA_CHANNEL_EMAIL,
     330              :                                    is.email,
     331              :                                    TALER_MERCHANT_MFA_CHANNEL_NONE);
     332            0 :       break;
     333            0 :     case TEH_TCS_EMAIL_AND_SMS:
     334            0 :       is.phone_validated = true;
     335            0 :       is.email_validated = true;
     336            0 :       ret = TMH_mfa_challenges_do (hc,
     337              :                                    TALER_MERCHANT_MFA_CO_INSTANCE_PROVISION,
     338              :                                    true,
     339              :                                    TALER_MERCHANT_MFA_CHANNEL_SMS,
     340              :                                    is.phone,
     341              :                                    TALER_MERCHANT_MFA_CHANNEL_EMAIL,
     342              :                                    is.email,
     343              :                                    TALER_MERCHANT_MFA_CHANNEL_NONE);
     344            0 :       break;
     345              :     }
     346            0 :     if (GNUNET_OK != ret)
     347              :     {
     348            0 :       GNUNET_JSON_parse_free (spec);
     349              :       return (GNUNET_NO == ret)
     350              :         ? MHD_YES
     351            0 :         : MHD_NO;
     352              :     }
     353              :   }
     354              : 
     355              :   /* handle authentication token setup */
     356           31 :   if (NULL == auth_password)
     357              :   {
     358           25 :     memset (&ias.auth_salt,
     359              :             0,
     360              :             sizeof (ias.auth_salt));
     361           25 :     memset (&ias.auth_hash,
     362              :             0,
     363              :             sizeof (ias.auth_hash));
     364              :   }
     365              :   else
     366              :   {
     367              :     /* Sets 'auth_salt' and 'auth_hash' */
     368            6 :     TMH_compute_auth (auth_password,
     369              :                       &ias.auth_salt,
     370              :                       &ias.auth_hash);
     371              :   }
     372              : 
     373              :   /* create in-memory data structure */
     374              :   {
     375              :     struct TMH_MerchantInstance *mi;
     376              :     enum GNUNET_DB_QueryStatus qs;
     377              : 
     378           31 :     mi = GNUNET_new (struct TMH_MerchantInstance);
     379           31 :     mi->wm_head = wm_head;
     380           31 :     mi->wm_tail = wm_tail;
     381           31 :     mi->settings = is;
     382           31 :     mi->settings.address = json_incref (mi->settings.address);
     383           31 :     mi->settings.jurisdiction = json_incref (mi->settings.jurisdiction);
     384           31 :     mi->settings.id = GNUNET_strdup (is.id);
     385           31 :     mi->settings.name = GNUNET_strdup (is.name);
     386           31 :     if (NULL != is.email)
     387            0 :       mi->settings.email = GNUNET_strdup (is.email);
     388           31 :     if (NULL != is.phone)
     389            0 :       mi->settings.phone = GNUNET_strdup (is.phone);
     390           31 :     if (NULL != is.website)
     391            0 :       mi->settings.website = GNUNET_strdup (is.website);
     392           31 :     if (NULL != is.logo)
     393            0 :       mi->settings.logo = GNUNET_strdup (is.logo);
     394           31 :     mi->auth = ias;
     395           31 :     mi->validation_needed = validation_needed;
     396           31 :     GNUNET_CRYPTO_eddsa_key_create (&mi->merchant_priv.eddsa_priv);
     397           31 :     GNUNET_CRYPTO_eddsa_key_get_public (&mi->merchant_priv.eddsa_priv,
     398              :                                         &mi->merchant_pub.eddsa_pub);
     399              : 
     400           31 :     for (unsigned int i = 0; i<MAX_RETRIES; i++)
     401              :     {
     402           31 :       if (GNUNET_OK !=
     403           31 :           TMH_db->start (TMH_db->cls,
     404              :                          "post /instances"))
     405              :       {
     406            0 :         mi->rc = 1;
     407            0 :         TMH_instance_decref (mi);
     408            0 :         GNUNET_JSON_parse_free (spec);
     409            0 :         return TALER_MHD_reply_with_error (connection,
     410              :                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
     411              :                                            TALER_EC_GENERIC_DB_START_FAILED,
     412              :                                            NULL);
     413              :       }
     414           31 :       qs = TMH_db->insert_instance (TMH_db->cls,
     415           31 :                                     &mi->merchant_pub,
     416           31 :                                     &mi->merchant_priv,
     417           31 :                                     &mi->settings,
     418           31 :                                     &mi->auth,
     419              :                                     validation_needed);
     420           31 :       switch (qs)
     421              :       {
     422            0 :       case GNUNET_DB_STATUS_HARD_ERROR:
     423              :         {
     424              :           MHD_RESULT ret;
     425              : 
     426            0 :           TMH_db->rollback (TMH_db->cls);
     427            0 :           GNUNET_break (0);
     428            0 :           ret = TALER_MHD_reply_with_error (connection,
     429              :                                             MHD_HTTP_INTERNAL_SERVER_ERROR,
     430              :                                             TALER_EC_GENERIC_DB_STORE_FAILED,
     431            0 :                                             is.id);
     432            0 :           mi->rc = 1;
     433            0 :           TMH_instance_decref (mi);
     434            0 :           GNUNET_JSON_parse_free (spec);
     435            0 :           return ret;
     436              :         }
     437            0 :       case GNUNET_DB_STATUS_SOFT_ERROR:
     438            0 :         goto retry;
     439            0 :       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     440              :         {
     441              :           MHD_RESULT ret;
     442              : 
     443            0 :           TMH_db->rollback (TMH_db->cls);
     444            0 :           GNUNET_break (0);
     445            0 :           ret = TALER_MHD_reply_with_error (connection,
     446              :                                             MHD_HTTP_CONFLICT,
     447              :                                             TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS,
     448            0 :                                             is.id);
     449            0 :           mi->rc = 1;
     450            0 :           TMH_instance_decref (mi);
     451            0 :           GNUNET_JSON_parse_free (spec);
     452            0 :           return ret;
     453              :         }
     454           31 :       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     455              :         /* handled below */
     456           31 :         break;
     457              :       }
     458           31 :       qs = TMH_db->commit (TMH_db->cls);
     459           31 :       if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
     460           31 :         qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     461            0 : retry:
     462           31 :       if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
     463           31 :         break; /* success! -- or hard failure */
     464              :     } /* for .. MAX_RETRIES */
     465           31 :     if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
     466              :     {
     467            0 :       mi->rc = 1;
     468            0 :       TMH_instance_decref (mi);
     469            0 :       GNUNET_JSON_parse_free (spec);
     470            0 :       return TALER_MHD_reply_with_error (connection,
     471              :                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
     472              :                                          TALER_EC_GENERIC_DB_COMMIT_FAILED,
     473              :                                          NULL);
     474              :     }
     475              :     /* Finally, also update our running process */
     476           31 :     GNUNET_assert (GNUNET_OK ==
     477              :                    TMH_add_instance (mi));
     478           31 :     TMH_reload_instances (mi->settings.id);
     479              :   }
     480           31 :   GNUNET_JSON_parse_free (spec);
     481           31 :   if (GNUNET_TIME_relative_is_zero (login_token_expiration))
     482              :   {
     483           31 :     return TALER_MHD_reply_static (connection,
     484              :                                    MHD_HTTP_NO_CONTENT,
     485              :                                    NULL,
     486              :                                    NULL,
     487              :                                    0);
     488              :   }
     489              : 
     490              :   {
     491              :     struct TALER_MERCHANTDB_LoginTokenP btoken;
     492            0 :     enum TMH_AuthScope iscope = TMH_AS_REFRESHABLE | TMH_AS_SPA;
     493              :     enum GNUNET_DB_QueryStatus qs;
     494              :     struct GNUNET_TIME_Timestamp expiration_time;
     495            0 :     bool refreshable = true;
     496              : 
     497            0 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
     498              :                                 &btoken,
     499              :                                 sizeof (btoken));
     500              :     expiration_time
     501            0 :       = GNUNET_TIME_relative_to_timestamp (login_token_expiration);
     502            0 :     qs = TMH_db->insert_login_token (TMH_db->cls,
     503            0 :                                      is.id,
     504              :                                      &btoken,
     505              :                                      GNUNET_TIME_timestamp_get (),
     506              :                                      expiration_time,
     507              :                                      iscope,
     508              :                                      "login token from instance creation");
     509            0 :     switch (qs)
     510              :     {
     511            0 :     case GNUNET_DB_STATUS_HARD_ERROR:
     512              :     case GNUNET_DB_STATUS_SOFT_ERROR:
     513              :     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     514            0 :       GNUNET_break (0);
     515            0 :       return TALER_MHD_reply_with_ec (connection,
     516              :                                       TALER_EC_GENERIC_DB_STORE_FAILED,
     517              :                                       "insert_login_token");
     518            0 :     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     519            0 :       break;
     520              :     }
     521              : 
     522              :     {
     523              :       char *tok;
     524              :       MHD_RESULT ret;
     525              :       char *val;
     526              : 
     527            0 :       val = GNUNET_STRINGS_data_to_string_alloc (&btoken,
     528              :                                                  sizeof (btoken));
     529            0 :       GNUNET_asprintf (&tok,
     530              :                        RFC_8959_PREFIX "%s",
     531              :                        val);
     532            0 :       GNUNET_free (val);
     533            0 :       ret = TALER_MHD_REPLY_JSON_PACK (
     534              :         connection,
     535              :         MHD_HTTP_OK,
     536              :         GNUNET_JSON_pack_string ("access_token",
     537              :                                  tok),
     538              :         GNUNET_JSON_pack_string ("token",
     539              :                                  tok),
     540              :         GNUNET_JSON_pack_string ("scope",
     541              :                                  TMH_get_name_by_scope (iscope,
     542              :                                                         &refreshable)),
     543              :         GNUNET_JSON_pack_bool ("refreshable",
     544              :                                refreshable),
     545              :         GNUNET_JSON_pack_timestamp ("expiration",
     546              :                                     expiration_time));
     547            0 :       GNUNET_free (tok);
     548            0 :       return ret;
     549              :     }
     550              :   }
     551              : }
     552              : 
     553              : 
     554              : /**
     555              :  * Generate an instance, given its configuration.
     556              :  *
     557              :  * @param rh context of the handler
     558              :  * @param connection the MHD connection to handle
     559              :  * @param[in,out] hc context with further information about the request
     560              :  * @return MHD result code
     561              :  */
     562              : MHD_RESULT
     563           33 : TMH_private_post_instances (const struct TMH_RequestHandler *rh,
     564              :                             struct MHD_Connection *connection,
     565              :                             struct TMH_HandlerContext *hc)
     566              : {
     567           66 :   return post_instances (rh,
     568              :                          connection,
     569              :                          hc,
     570           33 :                          GNUNET_TIME_UNIT_ZERO,
     571              :                          false);
     572              : }
     573              : 
     574              : 
     575              : /**
     576              :  * Generate an instance, given its configuration.
     577              :  * Public handler to be used when self-provisioning.
     578              :  *
     579              :  * @param rh context of the handler
     580              :  * @param connection the MHD connection to handle
     581              :  * @param[in,out] hc context with further information about the request
     582              :  * @return MHD result code
     583              :  */
     584              : MHD_RESULT
     585            0 : TMH_public_post_instances (const struct TMH_RequestHandler *rh,
     586              :                            struct MHD_Connection *connection,
     587              :                            struct TMH_HandlerContext *hc)
     588              : {
     589              :   struct GNUNET_TIME_Relative expiration;
     590              : 
     591            0 :   TALER_MHD_parse_request_rel_time (connection,
     592              :                                     "token_validity_ms",
     593              :                                     &expiration);
     594            0 :   if (GNUNET_YES !=
     595              :       TMH_have_self_provisioning)
     596              :   {
     597            0 :     GNUNET_break_op (0);
     598            0 :     return TALER_MHD_reply_with_error (connection,
     599              :                                        MHD_HTTP_FORBIDDEN,
     600              :                                        TALER_EC_MERCHANT_GENERIC_UNAUTHORIZED,
     601              :                                        "Self-provisioning is not enabled");
     602              :   }
     603              : 
     604            0 :   return post_instances (rh,
     605              :                          connection,
     606              :                          hc,
     607              :                          expiration,
     608              :                          TEH_TCS_NONE !=
     609              :                          TEH_mandatory_tan_channels);
     610              : }
     611              : 
     612              : 
     613              : /* end of taler-merchant-httpd_private-post-instances.c */
        

Generated by: LCOV version 2.0-1